mirror of https://github.com/KLayout/klayout.git
WIP: because the fixed scheme works nicely, add a new scale_and_snap function.
This commit is contained in:
parent
895206dfa1
commit
1e2a8b264d
|
|
@ -632,56 +632,11 @@ AsIfFlatRegion::angle_check (double min, double max, bool inverse) const
|
|||
return res.release ();
|
||||
}
|
||||
|
||||
static inline db::Coord snap_to_grid (db::Coord c, db::Coord g)
|
||||
{
|
||||
// This form of snapping always snaps g/2 to right/top.
|
||||
if (c < 0) {
|
||||
c = -g * ((-c + (g - 1) / 2) / g);
|
||||
} else {
|
||||
c = g * ((c + g / 2) / g);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
db::Polygon
|
||||
AsIfFlatRegion::snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap)
|
||||
{
|
||||
db::Polygon pnew;
|
||||
|
||||
for (size_t i = 0; i < poly.holes () + 1; ++i) {
|
||||
|
||||
heap.clear ();
|
||||
|
||||
db::Polygon::polygon_contour_iterator b, e;
|
||||
|
||||
if (i == 0) {
|
||||
b = poly.begin_hull ();
|
||||
e = poly.end_hull ();
|
||||
} else {
|
||||
b = poly.begin_hole ((unsigned int) (i - 1));
|
||||
e = poly.end_hole ((unsigned int) (i - 1));
|
||||
}
|
||||
|
||||
for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) {
|
||||
heap.push_back (db::Point (snap_to_grid ((*pt).x (), gx), snap_to_grid ((*pt).y (), gy)));
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
pnew.assign_hull (heap.begin (), heap.end ());
|
||||
} else {
|
||||
pnew.insert_hole (heap.begin (), heap.end ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return pnew;
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::snapped (db::Coord gx, db::Coord gy)
|
||||
{
|
||||
if (gx < 0 || gy < 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Grid check requires a positive grid value")));
|
||||
throw tl::Exception (tl::to_string (tr ("Grid snap requires a positive grid value")));
|
||||
}
|
||||
|
||||
std::auto_ptr<FlatRegion> new_region (new FlatRegion (merged_semantics ()));
|
||||
|
|
@ -698,6 +653,31 @@ AsIfFlatRegion::snapped (db::Coord gx, db::Coord gy)
|
|||
return new_region.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy)
|
||||
{
|
||||
if (gx < 0 || gy < 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Grid snap requires a positive grid value")));
|
||||
}
|
||||
|
||||
if (mx <= 0 || dx <= 0 || my <= 0 || dy <= 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Scale and snap requires positive and non-null magnification or divisor values")));
|
||||
}
|
||||
|
||||
std::auto_ptr<FlatRegion> new_region (new FlatRegion (merged_semantics ()));
|
||||
|
||||
gx = std::max (db::Coord (1), gx);
|
||||
gy = std::max (db::Coord (1), gy);
|
||||
|
||||
std::vector<db::Point> heap;
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
new_region->raw_polygons ().insert (scaled_and_snapped_polygon (*p, gx, mx, dx, 0, gy, my, dy, 0, heap));
|
||||
}
|
||||
|
||||
return new_region.release ();
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -105,6 +105,13 @@ public:
|
|||
|
||||
virtual RegionDelegate *snapped (db::Coord gx, db::Coord gy);
|
||||
|
||||
virtual RegionDelegate *scaled_and_snapped_in_place (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy)
|
||||
{
|
||||
return scaled_and_snapped (gx, mx, dx, gy, my, dy);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy);
|
||||
|
||||
virtual EdgesDelegate *edges (const EdgeFilterBase *) const;
|
||||
|
||||
virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter)
|
||||
|
|
@ -247,7 +254,6 @@ protected:
|
|||
static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes);
|
||||
template <class Trans>
|
||||
static void produce_markers_for_angle_check (const db::Polygon &poly, const Trans &tr, double min, double max, bool inverse, db::Shapes &shapes);
|
||||
static db::Polygon snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap);
|
||||
|
||||
private:
|
||||
AsIfFlatRegion &operator= (const AsIfFlatRegion &other);
|
||||
|
|
|
|||
|
|
@ -168,6 +168,61 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A scale+grid reducer
|
||||
*
|
||||
* This reducer incarnation reduces the transformation to it's displacement modulo a grid
|
||||
* after a specified scaling has been applied.
|
||||
* The scaling is given by a divider and multiplier and is mult / div.
|
||||
*/
|
||||
struct DB_PUBLIC ScaleAndGridReducer
|
||||
: public TransformationReducer
|
||||
{
|
||||
ScaleAndGridReducer (db::Coord grid, db::Coord mult, db::Coord div)
|
||||
: m_mult (mult), m_grid (int64_t (grid) * int64_t (div))
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
db::ICplxTrans reduce (const db::ICplxTrans &trans) const
|
||||
{
|
||||
// NOTE: we need to keep magnification, angle and mirror so when combining the
|
||||
// reduced transformations, the result will be equivalent to reducing the combined
|
||||
// transformation.
|
||||
db::ICplxTrans res (trans);
|
||||
res.disp (db::Vector (mod (trans.disp ().x ()), mod (trans.disp ().y ())));
|
||||
return res;
|
||||
}
|
||||
|
||||
db::Trans reduce (const db::Trans &trans) const
|
||||
{
|
||||
db::Trans res (trans);
|
||||
res.disp (db::Vector (mod (trans.disp ().x ()), mod (trans.disp ().y ())));
|
||||
return res;
|
||||
}
|
||||
|
||||
bool is_translation_invariant () const { return false; }
|
||||
|
||||
private:
|
||||
int64_t m_mult;
|
||||
int64_t m_grid;
|
||||
|
||||
inline db::Coord mod (db::Coord c) const
|
||||
{
|
||||
int64_t cc = int64_t (c) * m_mult;
|
||||
if (cc < 0) {
|
||||
cc = m_grid - (-cc) % m_grid;
|
||||
if (cc == m_grid) {
|
||||
return 0;
|
||||
} else {
|
||||
return db::Coord (cc);
|
||||
}
|
||||
} else {
|
||||
return db::Coord (cc % m_grid);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class computing variants for cells according to a given criterion
|
||||
*
|
||||
|
|
|
|||
|
|
@ -72,7 +72,9 @@ public:
|
|||
virtual EdgePairsDelegate *angle_check (double, double, bool) const;
|
||||
|
||||
virtual RegionDelegate *snapped_in_place (db::Coord, db::Coord) { return this; }
|
||||
virtual RegionDelegate *snapped (db::Coord, db::Coord) { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *snapped (db::Coord, db::Coord) { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *scaled_and_snapped_in_place (db::Coord, db::Coord, db::Coord, db::Coord, db::Coord, db::Coord) { return this; }
|
||||
virtual RegionDelegate *scaled_and_snapped (db::Coord, db::Coord, db::Coord, db::Coord, db::Coord, db::Coord) { return new EmptyRegion (); }
|
||||
|
||||
virtual EdgesDelegate *edges (const EdgeFilterBase *) const;
|
||||
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &) { return this; }
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "dbCellVariants.h"
|
||||
#include "dbRegionUtils.h"
|
||||
#include "tlProgress.h"
|
||||
|
||||
namespace db
|
||||
|
|
@ -431,5 +433,108 @@ ContextCache::find_layout_context (db::cell_index_type from, db::cell_index_type
|
|||
return c->second;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Scale and snap a layout
|
||||
|
||||
void
|
||||
scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db::Coord d)
|
||||
{
|
||||
if (g < 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Snapping requires a positive grid value")));
|
||||
}
|
||||
|
||||
if (m <= 0 || d <= 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Scale and snap requires positive and non-null magnification or divisor values")));
|
||||
}
|
||||
|
||||
if (! g && m == d) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::cell_variants_collector<db::ScaleAndGridReducer> vars (db::ScaleAndGridReducer (g, m, d));
|
||||
|
||||
vars.collect (layout, cell);
|
||||
vars.separate_variants (layout, cell);
|
||||
|
||||
std::set<db::cell_index_type> called_cells;
|
||||
cell.collect_called_cells (called_cells);
|
||||
called_cells.insert (cell.cell_index ());
|
||||
|
||||
db::LayoutLocker layout_locker (&layout);
|
||||
layout.update ();
|
||||
|
||||
std::vector<db::Point> heap;
|
||||
|
||||
unsigned int work_layer = layout.insert_layer ();
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
if (called_cells.find (c->cell_index ()) == called_cells.end ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
|
||||
tl_assert (v.size () == size_t (1));
|
||||
db::ICplxTrans tr = v.begin ()->first;
|
||||
|
||||
// NOTE: tr_disp is already multiplied with mag, so it can be an integer
|
||||
db::Vector tr_disp = tr.disp ();
|
||||
|
||||
tr.disp (db::Vector ());
|
||||
db::ICplxTrans trinv = tr.inverted ();
|
||||
|
||||
for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) {
|
||||
|
||||
db::Shapes &s = c->shapes ((*l).first);
|
||||
db::Shapes &out = c->shapes (work_layer);
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes); ! si.at_end (); ++si) {
|
||||
|
||||
db::Polygon poly;
|
||||
si->polygon (poly);
|
||||
poly.transform (tr);
|
||||
out.insert (scaled_and_snapped_polygon (poly, g, m, d, tr_disp.x (), g, m, d, tr_disp.y (), heap).transformed (trinv));
|
||||
|
||||
}
|
||||
|
||||
s.swap (out);
|
||||
out.clear ();
|
||||
|
||||
}
|
||||
|
||||
// Snap instance placements to grid and magnify
|
||||
// NOTE: we can modify the instances because the ScaleAndGridReducer marked every cell with children
|
||||
// as a variant cell (an effect of ScaleAndGridReducer::want_variants(cell) == true where cells have children).
|
||||
// Variant cells are not copied blindly back to the original layout.
|
||||
|
||||
std::list<db::CellInstArray> new_insts;
|
||||
|
||||
for (db::Cell::const_iterator inst = c->begin (); ! inst.at_end (); ++inst) {
|
||||
|
||||
const db::CellInstArray &ia = inst->cell_inst ();
|
||||
for (db::CellInstArray::iterator i = ia.begin (); ! i.at_end (); ++i) {
|
||||
|
||||
db::Trans ti (*i);
|
||||
ti.disp (scaled_and_snapped_vector (ti.disp (), g, m, d, g, m, d));
|
||||
|
||||
if (ia.is_complex ()) {
|
||||
new_insts.push_back (db::CellInstArray (ia.object (), ia.complex_trans (ti)));
|
||||
} else {
|
||||
new_insts.push_back (db::CellInstArray (ia.object (), ti));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
c->clear_insts ();
|
||||
|
||||
for (std::list<db::CellInstArray>::const_iterator i = new_insts.begin (); i != new_insts.end (); ++i) {
|
||||
c->insert (*i);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -223,6 +223,14 @@ private:
|
|||
const db::Layout *mp_layout;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Scales and snaps the layout below the given cell
|
||||
*
|
||||
* This method will scale and snap all layers from the given cell and below to the
|
||||
* specified grid. Scaling happens by the rational factor m / d.
|
||||
*/
|
||||
void scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db::Coord d);
|
||||
|
||||
} // namespace db
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -389,6 +389,18 @@ Region::snapped (db::Coord gx, db::Coord gy) const
|
|||
return Region (mp_delegate->snapped (gx, gy));
|
||||
}
|
||||
|
||||
void
|
||||
Region::scale_and_snap (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy)
|
||||
{
|
||||
set_delegate (mp_delegate->scaled_and_snapped_in_place (gx, mx, dx, gy, my, dy));
|
||||
}
|
||||
|
||||
Region
|
||||
Region::scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy) const
|
||||
{
|
||||
return Region (mp_delegate->scaled_and_snapped (gx, mx, dx, gy, my, dy));
|
||||
}
|
||||
|
||||
Region
|
||||
Region::strange_polygon_check () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -903,6 +903,19 @@ public:
|
|||
*/
|
||||
Region snapped (db::Coord gx, db::Coord gy) const;
|
||||
|
||||
/**
|
||||
* @brief Scales and grid-snaps the region
|
||||
*
|
||||
* This method will scale the region by mx/dx in horizontal and by my/dy in vertical
|
||||
* direction and then snape to gx and gy respectively.
|
||||
*/
|
||||
void scale_and_snap (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy);
|
||||
|
||||
/**
|
||||
* @brief Returns the scaled and snapped region
|
||||
*/
|
||||
Region scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy) const;
|
||||
|
||||
/**
|
||||
* @brief Performs a check for "strange" polygons
|
||||
*
|
||||
|
|
|
|||
|
|
@ -260,6 +260,8 @@ public:
|
|||
|
||||
virtual RegionDelegate *snapped_in_place (db::Coord gx, db::Coord gy) = 0;
|
||||
virtual RegionDelegate *snapped (db::Coord gx, db::Coord gy) = 0;
|
||||
virtual RegionDelegate *scaled_and_snapped_in_place (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy) = 0;
|
||||
virtual RegionDelegate *scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy) = 0;
|
||||
|
||||
virtual EdgesDelegate *edges (const EdgeFilterBase *filter) const = 0;
|
||||
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter) = 0;
|
||||
|
|
|
|||
|
|
@ -350,5 +350,92 @@ region_to_edge_interaction_filter_base<OutputType>::fill_output ()
|
|||
template class region_to_edge_interaction_filter_base<db::Polygon>;
|
||||
template class region_to_edge_interaction_filter_base<db::Edge>;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// Polygon snapping
|
||||
|
||||
db::Polygon
|
||||
snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap)
|
||||
{
|
||||
db::Polygon pnew;
|
||||
|
||||
for (size_t i = 0; i < poly.holes () + 1; ++i) {
|
||||
|
||||
heap.clear ();
|
||||
|
||||
db::Polygon::polygon_contour_iterator b, e;
|
||||
|
||||
if (i == 0) {
|
||||
b = poly.begin_hull ();
|
||||
e = poly.end_hull ();
|
||||
} else {
|
||||
b = poly.begin_hole ((unsigned int) (i - 1));
|
||||
e = poly.end_hole ((unsigned int) (i - 1));
|
||||
}
|
||||
|
||||
for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) {
|
||||
heap.push_back (db::Point (snap_to_grid ((*pt).x (), gx), snap_to_grid ((*pt).y (), gy)));
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
pnew.assign_hull (heap.begin (), heap.end ());
|
||||
} else {
|
||||
pnew.insert_hole (heap.begin (), heap.end ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return pnew;
|
||||
}
|
||||
|
||||
db::Polygon
|
||||
scaled_and_snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord mx, db::Coord dx, db::Coord ox, db::Coord gy, db::Coord my, db::Coord dy, db::Coord oy, std::vector<db::Point> &heap)
|
||||
{
|
||||
db::Polygon pnew;
|
||||
|
||||
int64_t dgx = int64_t (gx) * int64_t (dx);
|
||||
int64_t dgy = int64_t (gy) * int64_t (dy);
|
||||
|
||||
for (size_t i = 0; i < poly.holes () + 1; ++i) {
|
||||
|
||||
heap.clear ();
|
||||
|
||||
db::Polygon::polygon_contour_iterator b, e;
|
||||
|
||||
if (i == 0) {
|
||||
b = poly.begin_hull ();
|
||||
e = poly.end_hull ();
|
||||
} else {
|
||||
b = poly.begin_hole ((unsigned int) (i - 1));
|
||||
e = poly.end_hole ((unsigned int) (i - 1));
|
||||
}
|
||||
|
||||
for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) {
|
||||
int64_t x = snap_to_grid (int64_t ((*pt).x ()) * mx + int64_t (ox), dgx) / int64_t (dx);
|
||||
int64_t y = snap_to_grid (int64_t ((*pt).y ()) * my + int64_t (oy), dgy) / int64_t (dy);
|
||||
heap.push_back (db::Point (db::Coord (x), db::Coord (y)));
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
pnew.assign_hull (heap.begin (), heap.end ());
|
||||
} else {
|
||||
pnew.insert_hole (heap.begin (), heap.end ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return pnew;
|
||||
}
|
||||
|
||||
db::Vector
|
||||
scaled_and_snapped_vector (const db::Vector &v, db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy)
|
||||
{
|
||||
int64_t dgx = int64_t (gx) * int64_t (dx);
|
||||
int64_t dgy = int64_t (gy) * int64_t (dy);
|
||||
|
||||
int64_t x = snap_to_grid (int64_t (v.x ()) * mx, dgx) / int64_t (dx);
|
||||
int64_t y = snap_to_grid (int64_t (v.y ()) * my, dgy) / int64_t (dy);
|
||||
|
||||
return db::Vector (db::Coord (x), db::Coord (y));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -524,6 +524,37 @@ private:
|
|||
OutputContainer *mp_output;
|
||||
};
|
||||
|
||||
template <class C>
|
||||
static inline C snap_to_grid (C c, C g)
|
||||
{
|
||||
// This form of snapping always snaps g/2 to right/top.
|
||||
if (c < 0) {
|
||||
c = -g * ((-c + (g - 1) / 2) / g);
|
||||
} else {
|
||||
c = g * ((c + g / 2) / g);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Snaps a polygon to the given grid
|
||||
* Heap is a vector of points reused for the point list
|
||||
*/
|
||||
DB_PUBLIC db::Polygon snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap);
|
||||
|
||||
/**
|
||||
* @brief Scales and snaps a polygon to the given grid
|
||||
* Heap is a vector of points reused for the point list
|
||||
* The coordinate transformation is q = ((p * m + o) % (g * d)) / d.
|
||||
*/
|
||||
DB_PUBLIC db::Polygon scaled_and_snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord mx, db::Coord dx, db::Coord ox, db::Coord gy, db::Coord my, db::Coord dy, db::Coord oy, std::vector<db::Point> &heap);
|
||||
|
||||
/**
|
||||
* @brief Scales and snaps a vector to the given grid
|
||||
* The coordinate transformation is q = ((p * m) % (g * d)) / d.
|
||||
*/
|
||||
DB_PUBLIC db::Vector scaled_and_snapped_vector (const db::Vector &v, db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy);
|
||||
|
||||
} // namespace db
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "dbPCellDeclaration.h"
|
||||
#include "dbHash.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "tlStream.h"
|
||||
|
||||
namespace gsi
|
||||
|
|
@ -812,6 +813,16 @@ static const std::string &layout_meta_get_description (const db::MetaInfo *mi)
|
|||
return mi->description;
|
||||
}
|
||||
|
||||
static void scale_and_snap1 (db::Layout *layout, db::Cell &cell, db::Coord g, db::Coord m, db::Coord d)
|
||||
{
|
||||
scale_and_snap (*layout, cell, g, m, d);
|
||||
}
|
||||
|
||||
static void scale_and_snap2 (db::Layout *layout, db::cell_index_type ci, db::Coord g, db::Coord m, db::Coord d)
|
||||
{
|
||||
scale_and_snap (*layout, layout->cell (ci), g, m, d);
|
||||
}
|
||||
|
||||
Class<db::MetaInfo> decl_LayoutMetaInfo ("db", "LayoutMetaInfo",
|
||||
gsi::constructor ("new", &layout_meta_info_ctor, gsi::arg ("name"), gsi::arg ("value"), gsi::arg ("description", std::string ()),
|
||||
"@brief Creates a layout meta info object\n"
|
||||
|
|
@ -1542,6 +1553,25 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"an index in the range of 0 to layers-1 needs to be a valid layer. These layers can be either valid, "
|
||||
"special or unused. Use \\is_valid_layer? and \\is_special_layer? to test for the first two states.\n"
|
||||
) +
|
||||
gsi::method_ext ("scale_and_snap", &scale_and_snap1, gsi::arg ("cell"), gsi::arg ("grid"), gsi::arg ("mult"), gsi::arg ("div"),
|
||||
"@brief Scales and snaps the layout below a given cell by the given rational factor and snaps to the given grid\n"
|
||||
"\n"
|
||||
"This method is useful to scale a layout by a non-integer factor. The "
|
||||
"scale factor is given by the rational number mult / div. After scaling, the "
|
||||
"layout will be snapped to the given grid.\n"
|
||||
"\n"
|
||||
"Snapping happens 'as-if-flat' - that is, touching edges will stay touching, regardless of their "
|
||||
"hierarchy path. To achieve this, this method usually needs to produce cell variants.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1.\n"
|
||||
) +
|
||||
gsi::method_ext ("scale_and_snap", &scale_and_snap2, gsi::arg ("cell_index"), gsi::arg ("grid"), gsi::arg ("mult"), gsi::arg ("div"),
|
||||
"@brief Scales and snaps the layout below a given cell by the given rational factor and snaps to the given grid\n"
|
||||
"\n"
|
||||
"Like the other version of \\scale_and_snap, but taking a cell index for the argument.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1.\n"
|
||||
) +
|
||||
gsi::method ("transform", (void (db::Layout::*) (const db::Trans &t)) &db::Layout::transform,
|
||||
"@brief Transforms the layout with the given transformation\n"
|
||||
"@args trans\n"
|
||||
|
|
|
|||
|
|
@ -949,10 +949,28 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"This method will snap the region to the given grid - each x or y coordinate is brought on the gx or gy grid by rounding "
|
||||
"to the nearest value which is a multiple of gx or gy.\n"
|
||||
"\n"
|
||||
"If gx or gy is 0 or less, no snapping happens in that direction.\n"
|
||||
"If gx or gy is 0, no snapping happens in that direction.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("scaled_and_snapped", &db::Region::scaled_and_snapped, gsi::arg ("gx"), gsi::arg ("mx"), gsi::arg ("dx"), gsi::arg ("gy"),gsi::arg ("my"), gsi::arg ("dy"),
|
||||
"@brief Returns the scaled and snapped region\n"
|
||||
"This method will scale and snap the region to the given grid and return the scaled and snapped region (see \\scale_and_snap). The original region is not modified.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1."
|
||||
) +
|
||||
method ("scale_and_snap", &db::Region::scale_and_snap, gsi::arg ("gx"), gsi::arg ("mx"), gsi::arg ("dx"), gsi::arg ("gy"),gsi::arg ("my"), gsi::arg ("dy"),
|
||||
"@brief Scales and snaps the region to the given grid\n"
|
||||
"This method will first scale the region by a rational factor of mx/dx horizontally and my/dy vertically and then "
|
||||
"snap the region to the given grid - each x or y coordinate is brought on the gx or gy grid by rounding "
|
||||
"to the nearest value which is a multiple of gx or gy.\n"
|
||||
"\n"
|
||||
"If gx or gy is 0, the result is brought on a grid of 1.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1."
|
||||
) +
|
||||
method ("grid_check", &db::Region::grid_check, gsi::arg ("gx"), gsi::arg ("gy"),
|
||||
"@brief Returns a marker for all vertices not being on the given grid\n"
|
||||
"This method will return an edge pair object for every vertex whose x coordinate is not a multiple of gx or whose "
|
||||
|
|
|
|||
Loading…
Reference in New Issue