Matrix2d and Matrix3d generalized for integer coordinates, added transformation methods for polygons, regions, boxes, edges, etc. Fill enhancements basically implemented. Needs testing.

This commit is contained in:
Matthias Koefferlein 2021-03-05 15:31:40 +01:00
parent beefaf40f5
commit dbeee1531e
19 changed files with 1391 additions and 527 deletions

View File

@ -134,6 +134,8 @@ EdgePairs &EdgePairs::transform (const T &trans)
template DB_PUBLIC EdgePairs &EdgePairs::transform (const db::ICplxTrans &);
template DB_PUBLIC EdgePairs &EdgePairs::transform (const db::Trans &);
template DB_PUBLIC EdgePairs &EdgePairs::transform (const db::Disp &);
template DB_PUBLIC EdgePairs &EdgePairs::transform (const db::IMatrix2d &);
template DB_PUBLIC EdgePairs &EdgePairs::transform (const db::IMatrix3d &);
const db::RecursiveShapeIterator &
EdgePairs::iter () const

View File

@ -177,6 +177,8 @@ Edges &Edges::transform (const T &trans)
template DB_PUBLIC Edges &Edges::transform (const db::ICplxTrans &);
template DB_PUBLIC Edges &Edges::transform (const db::Trans &);
template DB_PUBLIC Edges &Edges::transform (const db::Disp &);
template DB_PUBLIC Edges &Edges::transform (const db::IMatrix2d &);
template DB_PUBLIC Edges &Edges::transform (const db::IMatrix3d &);
template <class Sh>
void Edges::insert (const Sh &shape)

View File

@ -382,19 +382,58 @@ rasterize_extended (const db::Polygon &fp, const db::Box &fc_bbox, db::AreaMap &
return true;
}
DB_PUBLIC bool
fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_cell_index, const db::Box &fc_bbox, const db::Point &origin, bool enhanced_fill,
static db::IMatrix2d
compute_shear_matrix (const db::Vector &row_step, const db::Vector &column_step)
{
db::IMatrix2d mr = db::IMatrix2d (1.0, 0.0, -double (row_step.y ()) / double (row_step.x ()), 1.0);
double csy = column_step.y () + mr.m21 () * column_step.x ();
db::IMatrix2d mc = db::IMatrix2d (1.0, -double (column_step.x ()) / csy, 0.0, 1.0);
return mc * mr;
}
DB_PUBLIC bool
fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_cell_index, const db::Box &fc_bbox, const db::Point &origin, bool enhanced_fill,
std::vector <db::Polygon> *remaining_parts, const db::Vector &fill_margin)
{
if (fc_bbox.empty () || fc_bbox.width () == 0 || fc_bbox.height () == 0) {
throw tl::Exception (tl::to_string (tr ("Invalid fill cell footprint (empty or zero width/height)")));
}
return fill_region (cell, fp0, fill_cell_index, fc_bbox.p1 () - db::Point (), db::Vector (fc_bbox.width (), 0), db::Vector (0, fc_bbox.height ()), origin, enhanced_fill, remaining_parts, fill_margin);
}
DB_PUBLIC bool
fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill,
std::vector <db::Polygon> *remaining_parts, const db::Vector &fill_margin)
{
if (row_step.x () <= 0 || column_step.y () <= 0) {
throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row step must have a positive x component while column step must have a positive y component")));
}
if (db::vprod_sign (row_step, column_step) <= 0) {
throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row_step x column_step vector vector product must be > 0")));
}
db::IMatrix2d shear = compute_shear_matrix (row_step, column_step);
db::IMatrix2d inverse_shear = shear.inverted ();
tl_assert (shear.trans (row_step).y () == 0);
tl_assert (shear.trans (row_step).x () == row_step.x ());
tl_assert (shear.trans (column_step).x () == 0);
tl_assert (shear.trans (column_step).y () == column_step.y ());
std::vector <db::Polygon> filled_regions;
db::EdgeProcessor ep;
// under- and oversize the polygon to remove slivers that cannot be filled.
db::Coord dx = fc_bbox.width () / 2 - 1, dy = fc_bbox.height () / 2 - 1;
db::Coord dx = row_step.x () / 2 - 1, dy = column_step.y () / 2 - 1;
std::vector <db::Polygon> fpa;
std::vector <db::Polygon> fpb;
fpa.push_back (fp0);
fpa.push_back (fp0.transformed (shear));
ep.size (fpa, -dx, 0, fpb, 3 /*mode*/, false /*=don't resolve holes*/);
fpa.swap (fpb);
@ -423,8 +462,11 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
db::AreaMap am;
db::Box raster_box (0, 0, row_step.x (), column_step.y ());
// Rasterize to determine fill regions
if ((enhanced_fill && rasterize_extended (*fp, fc_bbox, am)) || (!enhanced_fill && rasterize_simple (*fp, fc_bbox, origin, am))) {
// NOTE: rasterization happens post-shear transformation (e.g. with a rectangular kernel)
if ((enhanced_fill && rasterize_extended (*fp, raster_box, am)) || (!enhanced_fill && rasterize_simple (*fp, raster_box, origin, am))) {
size_t nx = am.nx ();
size_t ny = am.ny ();
@ -445,13 +487,13 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
ninsts += (jj - j);
db::Vector p0 (am.p0 () - fc_bbox.p1 ());
p0 += db::Vector (db::Coord (i) * fc_bbox.width (), db::Coord (j) * fc_bbox.height ());
db::Vector p0 (inverse_shear.trans (am.p0 ()) - kernel_origin);
p0 += row_step * long (i) + column_step * long (j);
db::CellInstArray array;
if (jj > j + 1) {
array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0), db::Vector (0, fc_bbox.height ()), db::Vector (fc_bbox.width (), 0), (unsigned long) (jj - j), 1);
array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0), column_step, db::Vector (), (unsigned long) (jj - j), 1);
} else {
array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0));
}
@ -459,9 +501,19 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
cell->insert (array);
if (remaining_parts) {
db::Box filled_box = array.raw_bbox () * fc_bbox;
filled_regions.push_back (db::Polygon (filled_box.enlarged (fill_margin)));
db::Point fill_stripe[4] = {
db::Point () + p0 + kernel_origin,
db::Point () + p0 + kernel_origin + column_step * long (jj - j),
db::Point () + p0 + kernel_origin + column_step * long (jj - j) + row_step,
db::Point () + p0 + kernel_origin + row_step
};
filled_regions.push_back (db::Polygon ());
filled_regions.back ().assign_hull (fill_stripe, fill_stripe + 4);
}
any_fill = true;
}
@ -484,9 +536,19 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
if (any_fill) {
if (remaining_parts) {
std::vector <db::Polygon> fp1;
if (fill_margin != db::Vector ()) {
ep.size (filled_regions, fill_margin.x (), fill_margin.y (), fp1, 3 /*mode*/, false /*=don't resolve holes*/);
filled_regions.swap (fp1);
fp1.clear ();
}
fp1.push_back (fp0);
ep.boolean (fp1, filled_regions, *remaining_parts, db::BooleanOp::ANotB, false /*=don't resolve holes*/);
}
return true;
@ -497,13 +559,33 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
}
DB_PUBLIC void
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point &origin, bool enhanced_fill,
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_bbox, const db::Point &origin, bool enhanced_fill,
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons)
{
if (fc_bbox.empty () || fc_bbox.width () == 0 || fc_bbox.height () == 0) {
throw tl::Exception (tl::to_string (tr ("Invalid fill cell footprint (empty or zero width/height)")));
}
fill_region (cell, fr, fill_cell_index, fc_bbox.p1 () - db::Point (), db::Vector (fc_bbox.width (), 0), db::Vector (0, fc_bbox.height ()),
origin, enhanced_fill, remaining_parts, fill_margin, remaining_polygons);
}
DB_PUBLIC void
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill,
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons)
{
if (row_step.x () <= 0 || column_step.y () <= 0) {
throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row step must have a positive x component while column step must have a positive y component")));
}
if (db::vprod_sign (row_step, column_step) <= 0) {
throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row_step x column_step vector vector product must be > 0")));
}
std::vector<db::Polygon> rem_pp, rem_poly;
for (db::Region::const_iterator p = fr.begin_merged (); !p.at_end (); ++p) {
if (!fill_region (cell, *p, fill_cell_index, fc_box, origin, enhanced_fill, remaining_parts ? &rem_pp : 0, fill_margin)) {
if (!fill_region (cell, *p, fill_cell_index, kernel_origin, row_step, column_step, origin, enhanced_fill, remaining_parts ? &rem_pp : 0, fill_margin)) {
if (remaining_polygons) {
rem_poly.push_back (*p);
}

View File

@ -37,6 +37,8 @@ class Region;
* @param fp0 The polygon to fill. Ideally, this polygon is merged and does not overlap with any other polygons.
* @param fill_cell_index The index of the cell to use for tiling
* @param fc_bbox The fill cell's footprint box. The footprint gives the area covered by one instance of the tiling cell.
* @param row_step (some_versions) The row advance vector of the fill cell. By default this is (fc_bbox.width(), 0)
* @param column_step (some_versions) The column advance vector of the fill cell. By default this is (0, fc_bbox.height())
* @param origin Specifies the origin of the fill raster if enhanced_fill is false
* @param enhanced_fill If set, the tiling offset will be optimized such that as much tiling cells fit into each polygon
*
@ -46,12 +48,45 @@ class Region;
* @param fill_margin Only used if remaining_parts is not 0 (see there)
*
* Return value: true, if the polygon could be filled, false if no fill tile at all could be applied (remaining_parts will not be fed in that case)
*
* Explanation for the fill kernel_origin, row step and column step vectors:
*
* The "kernel" is a rectangular or diamond-shaped area which is repeated along it's primary
* axes. In case of a box, the kernel is a rectangle and the primary axes are the x and y axes.
* The step vectors describe the repetition: in case of the box, the row step vector is (w,0) and
* the column step vector is (h,0) (w and h are the box width and heigth respectively). Hence
* the kernel will be repeated seamlessly.
*
* The kernel's boundary in case of the diamond kernel is:
*
* (o,o+c,o+c+r,o+r)
*
* (o = kernel_origin, r = row_step, c = column_step)
*
* Formally, the kernel will be placed a positions
*
* p(i,j) = p0 + i * row_step + j * column_step
*
* p0 is a position chosen by the fill alogorithm or the "origin", if enhanced_fill is false.
*
* This pattern is overlaid with the polygon to fill and all instances where the kernel moved by p(i,j) is entirely inside
* the polygon generate a fill cell instance with a displacement of p.
*
* Afterwards, the residual parts are computed by subtracting all moved kernels from the polygon to fill.
* This implies that ideally the fc_boxes should overlap while they are repeated with row_step and column_step.
*
* As a practical consequence, if all fill cell geometries are within the kernel's boundary, they will also
* be within the polygon to fill.
*/
DB_PUBLIC bool
fill_region (db::Cell *cell, const db::Polygon &fp, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point &origin, bool enhanced_fill,
std::vector <db::Polygon> *remaining_parts = 0, const db::Vector &fill_margin = db::Vector ());
DB_PUBLIC bool
fill_region (db::Cell *cell, const db::Polygon &fp, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill,
std::vector <db::Polygon> *remaining_parts = 0, const db::Vector &fill_margin = db::Vector ());
/**
* @brief A version of the fill tool that operates with region objects
@ -65,5 +100,9 @@ DB_PUBLIC void
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point &origin, bool enhanced_fill,
db::Region *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), db::Region *remaining_polygons = 0);
DB_PUBLIC void
fill_region (db::Cell *cell, const db::Region &fp, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill,
db::Region *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), db::Region *remaining_polygons = 0);
}

View File

@ -37,14 +37,16 @@ inline double mnorm (double x)
return fabs (x) < 1e-14 ? 0.0 : x;
}
template <class C>
std::string
Matrix2d::to_string () const
matrix_2d<C>::to_string () const
{
return tl::sprintf ("(%.12g,%.12g) (%.12g,%.12g)", mnorm (m_m11), mnorm (m_m12), mnorm (m_m21), mnorm (m_m22));
}
std::pair<double, double>
Matrix2d::mag () const
template <class C>
std::pair<double, double>
matrix_2d<C>::mag () const
{
double s1 = sqrt (m_m11 * m_m11 + m_m21 * m_m21);
double s2 = sqrt (m_m12 * m_m12 + m_m22 * m_m22);
@ -52,14 +54,16 @@ Matrix2d::mag () const
return std::make_pair (n * s1, n * s2);
}
template <class C>
bool
Matrix2d::has_rotation () const
matrix_2d<C>::has_rotation () const
{
return fabs (m_m11 - 1.0) > 1e-10 || fabs (m_m12) > 1e-10 || fabs (m_m21) > 1e-10 || fabs (m_m22 - 1.0) > 1e-10;
}
double
Matrix2d::angle () const
template <class C>
double
matrix_2d<C>::angle () const
{
std::pair <double, double> m = mag ();
double u1 = m.first;
@ -82,15 +86,17 @@ Matrix2d::angle () const
return 180.0 * atan2 (sin_a, cos_a) / M_PI;
}
Matrix2d
Matrix2d::rotation (double a)
template <class C>
matrix_2d<C>
matrix_2d<C>::rotation (double a)
{
a *= M_PI / 180.0;
return Matrix2d (cos (a), -sin (a), sin (a), cos (a));
}
bool
Matrix2d::has_shear () const
template <class C>
bool
matrix_2d<C>::has_shear () const
{
std::pair <double, double> m = mag ();
double u1 = m.first;
@ -104,8 +110,9 @@ Matrix2d::has_shear () const
return fabs (fsin_a) > 1e-10;
}
double
Matrix2d::shear_angle () const
template <class C>
double
matrix_2d<C>::shear_angle () const
{
std::pair <double, double> m = mag ();
double u1 = m.first;
@ -124,8 +131,9 @@ Matrix2d::shear_angle () const
return 180.0 * atan2 (fsin_a, fcos_a) / M_PI;
}
Matrix2d
Matrix2d::shear (double a)
template <class C>
matrix_2d<C>
matrix_2d<C>::shear (double a)
{
a *= M_PI / 180.0;
double cos_a = cos (a);
@ -134,21 +142,32 @@ Matrix2d::shear (double a)
return Matrix2d (f * cos_a, f * sin_a, f * sin_a, f * cos_a);
}
bool
Matrix2d::is_ortho () const
template <class C>
bool
matrix_2d<C>::is_ortho () const
{
return fabs (m_m11 * m_m12 + m_m21 * m_m22) < 1e-10 && fabs (m_m11 * m_m12) < 1e-10 && fabs (m_m21 * m_m22) < 1e-10;
}
bool
Matrix2d::equal (const Matrix2d &d) const
template <class C>
bool
matrix_2d<C>::is_unity () const
{
static matrix_2d<C> u;
return equal (u);
}
template <class C>
bool
matrix_2d<C>::equal (const matrix_2d<C> &d) const
{
return fabs (m_m11 - d.m_m11) < 1e-10 && fabs (m_m12 - d.m_m12) < 1e-10 &&
fabs (m_m21 - d.m_m21) < 1e-10 && fabs (m_m22 - d.m_m22) < 1e-10;
}
bool
Matrix2d::less (const Matrix2d &d) const
template <class C>
bool
matrix_2d<C>::less (const matrix_2d<C> &d) const
{
if (fabs (m_m11 - d.m_m11) > 1e-10) {
return m_m11 < d.m_m11;
@ -165,10 +184,14 @@ Matrix2d::less (const Matrix2d &d) const
return false;
}
template class matrix_2d<db::Coord>;
template class matrix_2d<db::DCoord>;
// --------------------------------------------------------------------------------------------
double
Matrix3d::det () const
template <class C>
double
matrix_3d<C>::det () const
{
double d = 0.0;
for (int i0 = 0; i0 < 3; ++i0) {
@ -182,8 +205,9 @@ Matrix3d::det () const
return d;
}
db::DVector
Matrix3d::trans (const db::DPoint &p, const db::DVector &v) const
template <class C>
db::vector<C>
matrix_3d<C>::trans (const db::point<C> &p, const db::vector<C> &v) const
{
double t[2][2];
for (int i = 0; i < 2; ++i) {
@ -191,11 +215,12 @@ Matrix3d::trans (const db::DPoint &p, const db::DVector &v) const
t[i][j] = (m_m[i][j] * m_m[2][1 - j] - m_m[i][1 - j] * m_m[2][j]) * (j == 0 ? p.y() : p.x()) + (m_m[2][2] * m_m[i][j] - m_m[i][2] * m_m[2][j]);
}
}
return db::DVector(v.x() * t[0][0] + v.y() * t[0][1], v.x() * t[1][0] + v.y() * t[1][1]);
return db::vector<C>(v.x() * t[0][0] + v.y() * t[0][1], v.x() * t[1][0] + v.y() * t[1][1]);
}
template <class C>
bool
Matrix3d::can_transform (const db::DPoint &p) const
matrix_3d<C>::can_transform (const db::point<C> &p) const
{
double r[3] = { 0, 0, 0 };
for (int i = 0; i < 3; ++i) {
@ -205,8 +230,9 @@ Matrix3d::can_transform (const db::DPoint &p) const
return (r[2] > (std::abs (r[0]) + std::abs (r[1])) * 1e-10);
}
db::DPoint
Matrix3d::trans (const db::DPoint &p) const
template <class C>
db::point<C>
matrix_3d<C>::trans (const db::point<C> &p) const
{
double r[3] = { 0, 0, 0 };
for (int i = 0; i < 3; ++i) {
@ -215,14 +241,15 @@ Matrix3d::trans (const db::DPoint &p) const
// safe approximation to the forbidden area where z <= 0
double z = std::max (r [2], (std::abs (r[0]) + std::abs (r[1])) * 1e-10);
return db::DPoint (r[0] / z, r[1] / z);
return db::point<C> (r[0] / z, r[1] / z);
}
Matrix3d
Matrix3d::inverted () const
template <class C>
matrix_3d<C>
matrix_3d<C>::inverted () const
{
double m[3][3];
Matrix3d r (1.0);
matrix_3d<C> r (1.0);
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
@ -268,71 +295,88 @@ Matrix3d::inverted () const
return r;
}
db::DVector
Matrix3d::disp () const
template <class C>
db::vector<C>
matrix_3d<C>::disp () const
{
return db::DVector (m_m[0][2] / m_m[2][2], m_m[1][2] / m_m[2][2]);
return db::vector<C> (m_m[0][2] / m_m[2][2], m_m[1][2] / m_m[2][2]);
}
double
Matrix3d::perspective_tilt_x (double z) const
template <class C>
double
matrix_3d<C>::perspective_tilt_x (double z) const
{
db::DVector d = disp ();
db::Matrix3d m = db::Matrix3d::disp (-d) * *this;
db::vector<C> d = disp ();
db::matrix_3d<C> m = db::matrix_3d<C>::disp (-d) * *this;
return 180 * atan (z * (m.m ()[2][0] * m.m ()[1][1] - m.m ()[2][1] * m.m ()[1][0]) / (m.m ()[0][0] * m.m ()[1][1] - m.m ()[0][1] * m.m ()[1][0])) / M_PI;
}
double
Matrix3d::perspective_tilt_y (double z) const
template <class C>
double
matrix_3d<C>::perspective_tilt_y (double z) const
{
db::DVector d = disp ();
db::Matrix3d m = db::Matrix3d::disp (-d) * *this;
db::vector<C> d = disp ();
db::matrix_3d<C> m = db::matrix_3d<C>::disp (-d) * *this;
return 180 * atan (z * (m.m ()[2][1] * m.m ()[0][0] - m.m ()[2][0] * m.m ()[0][1]) / (m.m ()[0][0] * m.m ()[1][1] - m.m ()[0][1] * m.m ()[1][0])) / M_PI;
}
bool
Matrix3d::has_perspective () const
template <class C>
bool
matrix_3d<C>::has_perspective () const
{
return fabs (m_m[2][0]) + fabs (m_m[2][1]) > 1e-10;
}
Matrix3d
Matrix3d::perspective (double tx, double ty, double z)
template <class C>
matrix_3d<C>
matrix_3d<C>::perspective (double tx, double ty, double z)
{
tx *= M_PI / 180.0;
ty *= M_PI / 180.0;
return Matrix3d (1.0, 0.0, 0.0, 1.0, 0.0, 0.0, tan (tx) / z, tan (ty) / z);
return matrix_3d<C> (1.0, 0.0, 0.0, 1.0, 0.0, 0.0, tan (tx) / z, tan (ty) / z);
}
Matrix2d
Matrix3d::m2d () const
template <class C>
matrix_2d<C>
matrix_3d<C>::m2d () const
{
db::DVector d = disp ();
db::Matrix3d m = db::Matrix3d::disp (-d) * *this;
db::vector<C> d = disp ();
db::matrix_3d<C> m = db::matrix_3d<C>::disp (-d) * *this;
if (has_perspective ()) {
m = Matrix3d::perspective (-perspective_tilt_x (1.0), -perspective_tilt_y (1.0), 1.0) * m;
m = matrix_3d<C>::perspective (-perspective_tilt_x (1.0), -perspective_tilt_y (1.0), 1.0) * m;
}
return Matrix2d (m.m_m[0][0] / m.m_m[2][2], m.m_m[0][1] / m.m_m[2][2], m.m_m[1][0] / m.m_m[2][2], m.m_m[1][1] / m.m_m[2][2]);
return matrix_2d<C> (m.m_m[0][0] / m.m_m[2][2], m.m_m[0][1] / m.m_m[2][2], m.m_m[1][0] / m.m_m[2][2], m.m_m[1][1] / m.m_m[2][2]);
}
std::string
Matrix3d::to_string () const
template <class C>
std::string
matrix_3d<C>::to_string () const
{
return tl::sprintf ("(%.12g,%.12g,%.12g)", mnorm (m_m[0][0]), mnorm (m_m[0][1]), mnorm (m_m[0][2])) + " "
+ tl::sprintf ("(%.12g,%.12g,%.12g)", mnorm (m_m[1][0]), mnorm (m_m[1][1]), mnorm (m_m[1][2])) + " "
+ tl::sprintf ("(%.12g,%.12g,%.12g)", mnorm (m_m[2][0]), mnorm (m_m[2][1]), mnorm (m_m[2][2]));
}
bool
Matrix3d::is_ortho () const
template <class C>
bool
matrix_3d<C>::is_ortho () const
{
return ! has_perspective () && m2d ().is_ortho ();
}
bool
Matrix3d::equal (const Matrix3d &d) const
template <class C>
bool
matrix_3d<C>::is_unity () const
{
static matrix_3d<C> u;
return equal (u);
}
template <class C>
bool
matrix_3d<C>::equal (const matrix_3d<C> &d) const
{
for (unsigned int i = 0; i < 3; ++i) {
for (unsigned int j = 0; j < 3; ++j) {
@ -344,8 +388,9 @@ Matrix3d::equal (const Matrix3d &d) const
return true;
}
bool
Matrix3d::less (const Matrix3d &d) const
template <class C>
bool
matrix_3d<C>::less (const matrix_3d<C> &d) const
{
for (unsigned int i = 0; i < 3; ++i) {
for (unsigned int j = 0; j < 3; ++j) {
@ -357,6 +402,9 @@ Matrix3d::less (const Matrix3d &d) const
return false;
}
template class matrix_3d<db::Coord>;
template class matrix_3d<db::DCoord>;
// --------------------------------------------------------------------------------------------
/**
@ -775,7 +823,7 @@ adjust_matrix (Matrix3d &matrix, const std::vector <db::DPoint> &landmarks_befor
namespace tl
{
template<> bool test_extractor_impl (tl::Extractor &ex, db::Matrix2d &m)
template<class C> bool test_extractor_impl_matrix2d (tl::Extractor &ex, db::matrix_2d<C> &m)
{
double m11 = 0.0, m12 = 0.0, m21 = 0.0, m22 = 0.0;
@ -811,18 +859,18 @@ namespace tl
return false;
}
m = db::Matrix2d (m11, m12, m21, m22);
m = db::matrix_2d<C> (m11, m12, m21, m22);
return true;
}
template<> void extractor_impl (tl::Extractor &ex, db::Matrix2d &m)
template<class C> void extractor_impl_matrix2d (tl::Extractor &ex, db::matrix_2d<C> &m)
{
if (! test_extractor_impl (ex, m)) {
ex.error (tl::to_string (tr ("Expected a 2d matrix specification")));
}
}
template<> bool test_extractor_impl (tl::Extractor &ex, db::Matrix3d &m)
template<class C> bool test_extractor_impl_matrix3d (tl::Extractor &ex, db::matrix_3d<C> &m)
{
double m11 = 0.0, m12 = 0.0, m13 = 0.0, m21 = 0.0, m22 = 0.0, m23 = 0.0, m31 = 0.0, m32 = 0.0, m33 = 0.0;
@ -892,16 +940,56 @@ namespace tl
return false;
}
m = db::Matrix3d (m11, m12, m13, m21, m22, m23, m31, m32, m33);
m = db::matrix_3d<C> (m11, m12, m13, m21, m22, m23, m31, m32, m33);
return true;
}
template<> void extractor_impl (tl::Extractor &ex, db::Matrix3d &m)
template<class C> void extractor_impl_matrix3d (tl::Extractor &ex, db::matrix_3d<C> &m)
{
if (! test_extractor_impl (ex, m)) {
ex.error (tl::to_string (tr ("Expected a 3d matrix specification")));
}
}
template<> void extractor_impl<db::matrix_2d<db::Coord> > (tl::Extractor &ex, db::matrix_2d<db::Coord> &m)
{
extractor_impl_matrix2d (ex, m);
}
template<> void extractor_impl<db::matrix_2d<db::DCoord> > (tl::Extractor &ex, db::matrix_2d<db::DCoord> &m)
{
extractor_impl_matrix2d (ex, m);
}
template<> void extractor_impl<db::matrix_3d<db::Coord> > (tl::Extractor &ex, db::matrix_3d<db::Coord> &m)
{
extractor_impl_matrix3d (ex, m);
}
template<> void extractor_impl<db::matrix_3d<db::DCoord> > (tl::Extractor &ex, db::matrix_3d<db::DCoord> &m)
{
extractor_impl_matrix3d (ex, m);
}
template<> bool test_extractor_impl<db::matrix_2d<db::Coord> > (tl::Extractor &ex, db::matrix_2d<db::Coord> &m)
{
return test_extractor_impl_matrix2d (ex, m);
}
template<> bool test_extractor_impl<db::matrix_2d<db::DCoord> > (tl::Extractor &ex, db::matrix_2d<db::DCoord> &m)
{
return test_extractor_impl_matrix2d (ex, m);
}
template<> bool test_extractor_impl<db::matrix_3d<db::Coord> > (tl::Extractor &ex, db::matrix_3d<db::Coord> &m)
{
return test_extractor_impl_matrix3d (ex, m);
}
template<> bool test_extractor_impl<db::matrix_3d<db::DCoord> > (tl::Extractor &ex, db::matrix_3d<db::DCoord> &m)
{
return test_extractor_impl_matrix3d (ex, m);
}
}

View File

@ -42,23 +42,24 @@ namespace db
/**
* @brief A class representing a 2d matrix, mainly to represent a rotation or shear transformation of 2d vectors
*/
class DB_PUBLIC Matrix2d
template <class C>
class DB_PUBLIC matrix_2d
{
public:
/**
* @brief typedefs for compatibility with the other transformations
*/
typedef double target_coord_type;
typedef double coord_type;
typedef db::DPoint displacement_type;
typedef Matrix2d inverse_trans;
typedef C target_coord_type;
typedef C coord_type;
typedef db::point<C> displacement_type;
typedef matrix_2d<C> inverse_trans;
/**
* @brief Default ctor
*
* Creates a null matrix
*/
Matrix2d ()
matrix_2d ()
: m_m11 (0.0), m_m12 (0.0), m_m21 (0.0), m_m22 (0.0)
{
// .. nothing yet ..
@ -69,18 +70,30 @@ public:
*
* Creates a matrix (m11, m12) (m21, m22)
*/
Matrix2d (double m11, double m12, double m21, double m22)
matrix_2d (double m11, double m12, double m21, double m22)
: m_m11 (m11), m_m12 (m12), m_m21 (m21), m_m22 (m22)
{
// .. nothing yet ..
}
/**
* @brief Full ctor
*
* Creates a matrix (m11, m12) (m21, m22)
*/
template <class D>
matrix_2d (const matrix_2d<D> &m)
: m_m11 (m.m11 ()), m_m12 (m.m12 ()), m_m21 (m.m21 ()), m_m22 (m.m22 ())
{
// .. nothing yet ..
}
/**
* @brief Scalar ctor
*
* Creates a matrix (d, 0) (0, d)
*/
Matrix2d (double d)
matrix_2d (double d)
: m_m11 (d), m_m12 (0.0), m_m21 (0.0), m_m22 (d)
{
// .. nothing yet ..
@ -91,7 +104,7 @@ public:
*
* Creates a matrix (d1, 0) (0, d2)
*/
Matrix2d (double d1, double d2)
matrix_2d (double d1, double d2)
: m_m11 (d1), m_m12 (0.0), m_m21 (0.0), m_m22 (d2)
{
// .. nothing yet ..
@ -101,7 +114,7 @@ public:
* @brief Make a matrix from a transformation
*/
template <class Tr>
Matrix2d (const Tr &t)
matrix_2d (const Tr &t)
{
*this = t.to_matrix2d ();
}
@ -109,9 +122,10 @@ public:
/**
* @brief Add operator
*/
Matrix2d operator+ (const Matrix2d &other) const
template <class D>
matrix_2d operator+ (const matrix_2d<D> &other) const
{
Matrix2d m (*this);
matrix_2d m (*this);
m += other;
return m;
}
@ -119,7 +133,8 @@ public:
/**
* @brief Add to operator
*/
Matrix2d &operator+= (const Matrix2d &other)
template <class D>
matrix_2d &operator+= (const matrix_2d<D> &other)
{
m_m11 += other.m_m11;
m_m12 += other.m_m12;
@ -131,18 +146,19 @@ public:
/**
* @brief Product of two matrices
*/
Matrix2d operator* (const Matrix2d &other) const
template <class D>
matrix_2d operator* (const matrix_2d<D> &other) const
{
return Matrix2d (m_m11 * other.m_m11 + m_m12 * other.m_m21,
m_m11 * other.m_m12 + m_m12 * other.m_m22,
m_m21 * other.m_m11 + m_m22 * other.m_m21,
m_m21 * other.m_m12 + m_m22 * other.m_m22);
return matrix_2d (m_m11 * other.m_m11 + m_m12 * other.m_m21,
m_m11 * other.m_m12 + m_m12 * other.m_m22,
m_m21 * other.m_m11 + m_m22 * other.m_m21,
m_m21 * other.m_m12 + m_m22 * other.m_m22);
}
/**
* @brief Multiply another to this matrix
*/
Matrix2d &operator*= (const Matrix2d &other)
matrix_2d &operator*= (const matrix_2d &other)
{
*this = (*this * other);
return *this;
@ -151,9 +167,9 @@ public:
/**
* @brief Multiply with a scalar
*/
Matrix2d operator* (double d) const
matrix_2d operator* (double d) const
{
Matrix2d m (*this);
matrix_2d m (*this);
m *= d;
return m;
}
@ -161,7 +177,7 @@ public:
/**
* @brief Multiply a scalar to this matrix
*/
Matrix2d &operator*= (double d)
matrix_2d &operator*= (double d)
{
m_m11 *= d;
m_m12 *= d;
@ -173,15 +189,15 @@ public:
/**
* @brief Transformation of a vector
*/
db::DVector operator* (const db::DVector &v) const
db::vector<C> operator* (const db::vector<C> &v) const
{
return db::DVector (m_m11 * v.x () + m_m12 * v.y (), m_m21 * v.x () + m_m22 * v.y ());
return db::vector<C> (m_m11 * v.x () + m_m12 * v.y (), m_m21 * v.x () + m_m22 * v.y ());
}
/**
* @brief "trans" alias for compatibility with the other transformations
*/
db::DVector trans (const db::DVector &p) const
db::vector<C> trans (const db::vector<C> &p) const
{
return operator* (p);
}
@ -189,7 +205,7 @@ public:
/**
* @brief "operator()" alias for compatibility with the other transformations
*/
db::DVector operator() (const db::DVector &p) const
db::vector<C> operator() (const db::vector<C> &p) const
{
return operator* (p);
}
@ -197,15 +213,15 @@ public:
/**
* @brief Transformation of a point
*/
db::DPoint operator* (const db::DPoint &v) const
db::point<C> operator* (const db::point<C> &v) const
{
return db::DPoint (m_m11 * v.x () + m_m12 * v.y (), m_m21 * v.x () + m_m22 * v.y ());
return db::point<C> (m_m11 * v.x () + m_m12 * v.y (), m_m21 * v.x () + m_m22 * v.y ());
}
/**
* @brief "trans" alias for compatibility with the other transformations
*/
db::DPoint trans (const db::DPoint &p) const
db::point<C> trans (const db::point<C> &p) const
{
return operator* (p);
}
@ -213,7 +229,7 @@ public:
/**
* @brief "operator()" alias for compatibility with the other transformations
*/
db::DPoint operator() (const db::DPoint &p) const
db::point<C> operator() (const db::point<C> &p) const
{
return operator* (p);
}
@ -221,9 +237,9 @@ public:
/**
* @brief Return the transposed matrix
*/
Matrix2d transposed () const
matrix_2d<C> transposed () const
{
return Matrix2d (m_m11, m_m21, m_m12, m_m22);
return matrix_2d<C> (m_m11, m_m21, m_m12, m_m22);
}
/**
@ -245,9 +261,9 @@ public:
/**
* @brief Return the inverted matrix
*/
Matrix2d inverted () const
matrix_2d<C> inverted () const
{
Matrix2d m (*this);
matrix_2d<C> m (*this);
m.invert ();
return m;
}
@ -325,9 +341,9 @@ public:
* @param mx The x magnification
* @param my The y magnification
*/
static Matrix2d mag (double mx, double my)
static matrix_2d<C> mag (double mx, double my)
{
return Matrix2d (mx, 0.0, 0.0, my);
return matrix_2d<C> (mx, 0.0, 0.0, my);
}
/**
@ -335,9 +351,9 @@ public:
*
* @param m The magnification
*/
static Matrix2d mag (double m)
static matrix_2d<C> mag (double m)
{
return Matrix2d (m, 0.0, 0.0, m);
return matrix_2d<C> (m, 0.0, 0.0, m);
}
/**
@ -356,9 +372,9 @@ public:
/**
* @brief Create the mirror matrix
*/
static Matrix2d mirror (bool m)
static matrix_2d<C> mirror (bool m)
{
return Matrix2d (1.0, 0.0, 0.0, m ? -1.0 : 1.0);
return matrix_2d<C> (1.0, 0.0, 0.0, m ? -1.0 : 1.0);
}
/**
@ -380,7 +396,7 @@ public:
/**
* @brief Create the rotation matrix from the given angle
*/
static Matrix2d rotation (double a);
static matrix_2d<C> rotation (double a);
/**
* @brief Determine the shear component of the matrix and return the shear angle in degree
@ -403,7 +419,7 @@ public:
/**
* @brief Create the shear matrix from the given angle
*/
static Matrix2d shear (double a);
static matrix_2d<C> shear (double a);
/**
* @brief Determine whether the matrix represents an orthogonal transformation
@ -412,6 +428,13 @@ public:
*/
bool is_ortho () const;
/**
* @brief Determine whether the matrix represents an unit transformation
*
* This method is provided for compatibility to the other transformations.
*/
bool is_unity () const;
/**
* @brief Convert to a string
*/
@ -420,37 +443,41 @@ public:
/**
* @brief A fuzzy compare operator (equal)
*/
bool equal (const Matrix2d &d) const;
bool equal (const matrix_2d<C> &d) const;
/**
* @brief A fuzzy compare operator (less)
*/
bool less (const Matrix2d &d) const;
bool less (const matrix_2d<C> &d) const;
private:
double m_m11, m_m12, m_m21, m_m22;
};
typedef matrix_2d<db::DCoord> Matrix2d;
typedef matrix_2d<db::Coord> IMatrix2d;
/**
* @brief A class representing a 3d matrix, mainly to represent a rotation, shear or perspective transformation of 2d vectors
*/
class DB_PUBLIC Matrix3d
template <class C>
class DB_PUBLIC matrix_3d
{
public:
/**
* @brief typedefs for compatibility with the other transformations
*/
typedef double target_coord_type;
typedef double coord_type;
typedef db::DPoint displacement_type;
typedef Matrix3d inverse_trans;
typedef C target_coord_type;
typedef C coord_type;
typedef db::point<C> displacement_type;
typedef matrix_3d<C> inverse_trans;
/**
* @brief Default ctor
*
* Creates a null matrix
*/
Matrix3d ()
matrix_3d ()
{
set (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
}
@ -460,7 +487,7 @@ public:
*
* Creates a matrix (m11, m12, 0) (m21, m22, 0) (0, 0, 1)
*/
Matrix3d (double m11, double m12, double m21, double m22)
matrix_3d (double m11, double m12, double m21, double m22)
{
set (m11, m12, 0.0, m21, m22, 0.0, 0.0, 0.0, 1.0);
}
@ -470,17 +497,33 @@ public:
*
* Creates a matrix (m11, m12, m13) (m21, m22, m23) (m31, m32, m33)
*/
Matrix3d (double m11, double m12, double m13, double m21, double m22, double m23, double m31, double m32, double m33)
matrix_3d (double m11, double m12, double m13, double m21, double m22, double m23, double m31, double m32, double m33)
{
set (m11, m12, m13, m21, m22, m23, m31, m32, m33);
}
/**
* @brief Full ctor
*
* Creates a matrix (m11, m12) (m21, m22)
*/
template <class D>
matrix_3d (const matrix_3d<D> &m)
{
const double (&mm) [3][3] = m.m ();
for (unsigned int i = 0; i < 3; ++i) {
for (unsigned int j = 0; j < 3; ++j) {
m_m [i][j] = mm [i][j];
}
}
}
/**
* @brief Matrix2d ctor from eight components
*
* Creates a matrix (m11, m12, d1) (m21, m22, d2) (p1, p2, 1)
*/
Matrix3d (double m11, double m12, double m21, double m22, double d1, double d2, double p1, double p2)
matrix_3d (double m11, double m12, double m21, double m22, double d1, double d2, double p1, double p2)
{
set (m11, m12, d1, m21, m22, d2, p1, p2, 1.0);
}
@ -490,7 +533,8 @@ public:
*
* Creates a matrix representing the given Matrix2d.
*/
explicit Matrix3d (const Matrix2d &m)
template <class D>
explicit matrix_3d (const matrix_2d<D> &m)
{
set (m.m11 (), m.m12 (), 0.0, m.m21 (), m.m22 (), 0.0, 0.0, 0.0, 1.0);
}
@ -499,7 +543,7 @@ public:
* @brief Make a matrix from a transformation
*/
template <class Tr>
explicit Matrix3d (const Tr &t)
explicit matrix_3d (const Tr &t)
{
*this = t.to_matrix3d ();
}
@ -509,7 +553,7 @@ public:
*
* Creates a matrix (d, 0, 0) (0, d, 0) (0, 0, 1)
*/
explicit Matrix3d (double d)
explicit matrix_3d (double d)
{
set (d, 0.0, 0.0, 0.0, d, 0.0, 0.0, 0.0, 1.0);
}
@ -517,9 +561,10 @@ public:
/**
* @brief Add operator
*/
Matrix3d operator+ (const Matrix3d &other) const
template <class D>
matrix_3d operator+ (const matrix_3d<D> &other) const
{
Matrix3d m (*this);
matrix_3d m (*this);
m += other;
return m;
}
@ -527,7 +572,8 @@ public:
/**
* @brief Add to operator
*/
Matrix3d &operator+= (const Matrix3d &other)
template <class D>
matrix_3d &operator+= (const matrix_3d<D> &other)
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
@ -540,13 +586,14 @@ public:
/**
* @brief Product of two matrices
*/
Matrix3d operator* (const Matrix3d &other) const
template <class D>
matrix_3d operator* (const matrix_3d<D> &other) const
{
Matrix3d res;
matrix_3d res;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 3; ++k) {
res.m_m [i][j] += m_m [i][k] * other.m_m [k][j];
res.m_m [i][j] += m_m [i][k] * other.m () [k][j];
}
}
}
@ -556,7 +603,8 @@ public:
/**
* @brief Multiply another to this matrix
*/
Matrix3d &operator*= (const Matrix3d &other)
template <class D>
matrix_3d &operator*= (const matrix_3d<D> &other)
{
*this = (*this * other);
return *this;
@ -565,9 +613,9 @@ public:
/**
* @brief Multiply with a scalar
*/
Matrix3d operator* (double d) const
matrix_3d operator* (double d) const
{
Matrix3d m (*this);
matrix_3d m (*this);
m *= d;
return m;
}
@ -575,7 +623,7 @@ public:
/**
* @brief Multiply a scalar to this matrix
*/
Matrix3d &operator*= (double d)
matrix_3d &operator*= (double d)
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
@ -591,17 +639,17 @@ public:
* A point can be transformed if the resulting point is
* located in the positive z plane.
*/
bool can_transform (const db::DPoint &p) const;
bool can_transform (const db::point<C> &p) const;
/**
* @brief Transforms a vector which emerges from a certain point
*/
db::DVector trans (const db::DPoint &p, const db::DVector &v) const;
db::vector<C> trans (const db::point<C> &p, const db::vector<C> &v) const;
/**
* @brief Transforms a point
*/
db::DPoint trans (const db::DPoint &p) const;
db::point<C> trans (const db::point<C> &p) const;
/**
* @brief Transforms a vector
@ -613,34 +661,34 @@ public:
* In this implementation we assume the vector starts at 0, 0. This at least renders this
* feature useful for implementing shear and anisotropic scaling.
*/
db::DVector trans (const db::DVector &p) const
db::vector<C> trans (const db::vector<C> &p) const
{
return this->trans (db::DPoint () + p) - this->trans (db::DPoint ());
return this->trans (db::point<C> () + p) - this->trans (db::point<C> ());
}
/**
* @brief "trans" alias for compatibility with the other transformations
*/
template <class C>
db::DPoint trans (const db::point<C> &p) const
template <class D>
db::point<C> trans (const db::point<D> &p) const
{
return trans (db::DPoint (p));
return trans (db::point<C> (p));
}
/**
* @brief "trans" alias for compatibility with the other transformations
*/
template <class C>
db::DVector trans (const db::vector<C> &p) const
template <class D>
db::vector<C> trans (const db::vector<D> &p) const
{
return trans (db::DVector (p));
return trans (db::vector<C> (p));
}
/**
* @brief "operator()" alias for compatibility with the other transformations
*/
template <class C>
db::DPoint operator() (const db::point<C> &p) const
template <class D>
db::point<C> operator() (const db::point<D> &p) const
{
return trans (p);
}
@ -648,8 +696,8 @@ public:
/**
* @brief "operator()" alias for compatibility with the other transformations
*/
template <class C>
db::DVector operator() (const db::vector<C> &p) const
template <class D>
db::vector<C> operator() (const db::vector<D> &p) const
{
return trans (p);
}
@ -657,9 +705,9 @@ public:
/**
* @brief Return the transposed matrix
*/
Matrix3d transposed () const
matrix_3d transposed () const
{
Matrix3d res;
matrix_3d res;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
res.m_m [i][j] = m_m [j][i];
@ -684,7 +732,7 @@ public:
/**
* @brief Return the inverted matrix
*/
Matrix3d inverted () const;
matrix_3d inverted () const;
/**
* @brief In-place invert
@ -697,7 +745,12 @@ public:
/**
* @brief Accessor to the internal matrix
*/
const double (*m () const) [3] { return m_m; }
const double (&m () const) [3][3] { return m_m; }
/**
* @brief Accessor to the internal matrix
*/
double (&m ()) [3][3] { return m_m; }
/**
* @brief Return the magnification component of the matrix
@ -730,17 +783,17 @@ public:
/**
* @brief Create the magnification matrix with isotropic magnification
*/
static Matrix3d mag (double m)
static matrix_3d mag (double m)
{
return Matrix3d (m, 0.0, 0.0, m);
return matrix_3d (m, 0.0, 0.0, m);
}
/**
* @brief Create the magnification matrix with anisotropic magnification
*/
static Matrix3d mag (double mx, double my)
static matrix_3d mag (double mx, double my)
{
return Matrix3d (mx, 0.0, 0.0, my);
return matrix_3d (mx, 0.0, 0.0, my);
}
/**
@ -759,9 +812,9 @@ public:
/**
* @brief Create the mirror matrix
*/
static Matrix3d mirror (bool m)
static matrix_3d mirror (bool m)
{
return Matrix3d (1.0, 0.0, 0.0, m ? -1.0 : 1.0);
return matrix_3d (1.0, 0.0, 0.0, m ? -1.0 : 1.0);
}
/**
@ -789,9 +842,9 @@ public:
/**
* @brief Create the rotation matrix from the given angle
*/
static Matrix3d rotation (double a)
static matrix_3d rotation (double a)
{
return Matrix3d (Matrix2d::rotation (a));
return matrix_3d (Matrix2d::rotation (a));
}
/**
@ -821,9 +874,9 @@ public:
/**
* @brief Create the shear matrix from the given angle
*/
static Matrix3d shear (double a)
static matrix_3d shear (double a)
{
return Matrix3d (Matrix2d::shear (a));
return matrix_3d (Matrix2d::shear (a));
}
/**
@ -860,19 +913,19 @@ public:
* @param ty The tilt angle in y direction (around the x axis) in degree for the given observer distance.
* @param z The observer distance.
*/
static Matrix3d perspective (double tx, double ty, double z);
static matrix_3d perspective (double tx, double ty, double z);
/**
* @brief Get the displacement vector component
*/
db::DVector disp () const;
db::vector<C> disp () const;
/**
* @brief Create the mirror matrix
*/
static Matrix3d disp (const db::DVector &d)
static matrix_3d disp (const db::vector<C> &d)
{
return Matrix3d (1.0, 0.0, 0.0, 1.0, d.x (), d.y (), 0.0, 0.0);
return matrix_3d (1.0, 0.0, 0.0, 1.0, d.x (), d.y (), 0.0, 0.0);
}
/**
@ -882,10 +935,17 @@ public:
*/
bool is_ortho () const;
/**
* @brief Determine whether the matrix represents an unit transformation
*
* This method is provided for compatibility to the other transformations.
*/
bool is_unity () const;
/**
* @brief Get the 2d matrix component (without perspective transformation or displacement)
*/
Matrix2d m2d () const;
matrix_2d<C> m2d () const;
/**
* @brief Convert to a string
@ -895,12 +955,12 @@ public:
/**
* @brief A fuzzy compare operator (equal)
*/
bool equal (const Matrix3d &d) const;
bool equal (const matrix_3d &d) const;
/**
* @brief A fuzzy compare operator (less)
*/
bool less (const Matrix3d &d) const;
bool less (const matrix_3d &d) const;
private:
double m_m[3][3];
@ -919,6 +979,9 @@ private:
}
};
typedef matrix_3d<db::DCoord> Matrix3d;
typedef matrix_3d<db::Coord> IMatrix3d;
/**
* @brief Some adjustment flags
*
@ -982,10 +1045,15 @@ void DB_PUBLIC adjust_matrix (Matrix3d &matrix, const std::vector <db::DPoint> &
namespace tl
{
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::Matrix2d &t);
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::Matrix3d &t);
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::Matrix2d &t);
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::Matrix3d &t);
template<> DB_PUBLIC void extractor_impl<db::matrix_2d<db::Coord> > (tl::Extractor &ex, db::matrix_2d<db::Coord> &t);
template<> DB_PUBLIC void extractor_impl<db::matrix_2d<db::DCoord> > (tl::Extractor &ex, db::matrix_2d<db::DCoord> &t);
template<> DB_PUBLIC void extractor_impl<db::matrix_3d<db::Coord> > (tl::Extractor &ex, db::matrix_3d<db::Coord> &t);
template<> DB_PUBLIC void extractor_impl<db::matrix_3d<db::DCoord> > (tl::Extractor &ex, db::matrix_3d<db::DCoord> &t);
template<> DB_PUBLIC bool test_extractor_impl<db::matrix_2d<db::Coord> > (tl::Extractor &ex, db::matrix_2d<db::Coord> &t);
template<> DB_PUBLIC bool test_extractor_impl<db::matrix_2d<db::DCoord> > (tl::Extractor &ex, db::matrix_2d<db::DCoord> &t);
template<> DB_PUBLIC bool test_extractor_impl<db::matrix_3d<db::Coord> > (tl::Extractor &ex, db::matrix_3d<db::Coord> &t);
template<> DB_PUBLIC bool test_extractor_impl<db::matrix_3d<db::DCoord> > (tl::Extractor &ex, db::matrix_3d<db::DCoord> &t);
} // namespace tl
#endif

View File

@ -145,6 +145,8 @@ Region &Region::transform (const T &trans)
template DB_PUBLIC Region &Region::transform (const db::ICplxTrans &);
template DB_PUBLIC Region &Region::transform (const db::Trans &);
template DB_PUBLIC Region &Region::transform (const db::Disp &);
template DB_PUBLIC Region &Region::transform (const db::IMatrix2d &);
template DB_PUBLIC Region &Region::transform (const db::IMatrix3d &);
template <class Sh>
void Region::insert (const Sh &shape)

View File

@ -1299,22 +1299,29 @@ static void move_tree_shapes3 (db::Cell *cell, db::Cell &source_cell, const db::
static void
fill_region1 (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin)
{
if (fc_box.empty () || fc_box.width () == 0 || fc_box.height () == 0) {
throw tl::Exception (tl::to_string (tr ("Invalid fill cell footprint (empty or zero width/height)")));
}
db::fill_region (cell, fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0, 0, db::Vector (), 0);
}
static void
fill_region1d (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point *origin)
{
db::fill_region (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0, 0, db::Vector (), 0);
}
static void
fill_region2 (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin,
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons)
{
if (fc_box.empty () || fc_box.width () == 0 || fc_box.height () == 0) {
throw tl::Exception (tl::to_string (tr ("Invalid fill cell footprint (empty or zero width/height)")));
}
db::fill_region (cell, fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons);
}
static void
fill_region2d (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point *origin,
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons)
{
db::fill_region (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons);
}
static db::Instance cell_inst_dtransform_simple (db::Cell *cell, const db::Instance &inst, const db::DTrans &t)
{
const db::Layout *layout = cell->layout ();
@ -1774,21 +1781,41 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"@brief Fills the given region with cells of the given type\n"
"@param region The region to fill\n"
"@param fill_cell_index The fill cell to place\n"
"@param fc_box The fill cell's footprint\n"
"@param fc_box The fill cell's footprint (the 'fill kernel')\n"
"@param origin The global origin of the fill pattern or nil to allow local (per-polygon) optimization\n"
"\n"
"This method creates a regular pattern of fill cells to cover the interior of the given region as far as possible. "
"This process is also known as tiling. The current implementation supports rectangular (not necessarily square) tile cells. "
"This process is also known as tiling. This implementation supports rectangular (not necessarily square) tile cells. "
"The tile cell's footprint is given by the fc_box parameter and the cells will be arranged with their footprints forming "
"a seamless array.\n"
"\n"
"The algorithm supports a global fill raster as well as local (per-polygon) origin optimization. In the latter case "
"the origin of the regular raster is optimized per individual polygon of the fill region.\n"
"\n"
"A more elaborate version of this method is available which also returns information about the non-filled parts.\n"
"The implementation will basically try to find a repetition pattern of the tile cell's footprint (the 'fill kernel') "
"and fit any many instances as possible into the given region. This version will use a fixed pattern while "
"a more elaborate version of this method is available which tries to optimize the number of fill cell instances. "
"This elaborate version will also return information about the non-filled parts.\n"
"\n"
"There is also a version available which offers a diamond-shape generic fill kernel instead of a box.\n"
"\n"
"This method has been introduced in version 0.23.\n"
) +
gsi::method_ext ("fill_region", &fill_region1d, gsi::arg ("region"), gsi::arg ("fill_cell_index"), gsi::arg ("kernel_origin"), gsi::arg ("row_step"), gsi::arg ("column_step"), gsi::arg ("origin"),
"@brief Fills the given region with cells of the given type (diamond-shape fill kernel)\n"
"@param region The region to fill\n"
"@param fill_cell_index The fill cell to place\n"
"@param kernel_origin The fill cell's footprint\n"
"@param row_step The fill cell's footprint\n"
"@param column_step The fill cell's footprint\n"
"@param origin The global origin of the fill pattern or nil to allow local (per-polygon) optimization\n"
"\n"
"This version is similar to the version providing a rectangular fill kernel, but it offers a more generic, diamond-shaped kernel.\n"
"The kerne is defined by an origin and two vectors (row_step and column_step) which span the diamond.\n"
"This version will try to fit as many of these diamond-shaped kernels into the region to fill.\n"
"\n"
"This variant has been introduced in version 0.27.\n"
) +
gsi::method_ext ("fill_region", &fill_region2, gsi::arg ("region"), gsi::arg ("fill_cell_index"), gsi::arg ("fc_box"), gsi::arg ("origin"), gsi::arg ("remaining_parts"), gsi::arg ("fill_margin"), gsi::arg ("remaining_polygons"),
"@brief Fills the given region with cells of the given type (extended version)\n"
"@param region The region to fill\n"
@ -1832,6 +1859,24 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"\n"
"This method has been introduced in version 0.23.\n"
) +
gsi::method_ext ("fill_region", &fill_region2d, gsi::arg ("region"), gsi::arg ("fill_cell_index"), gsi::arg ("kernel_origin"), gsi::arg ("row_step"), gsi::arg ("column_step"), gsi::arg ("origin"), gsi::arg ("remaining_parts"), gsi::arg ("fill_margin"), gsi::arg ("remaining_polygons"),
"@brief Fills the given region with cells of the given type (diamond-shape fill kernel, extended version)\n"
"@param region The region to fill\n"
"@param fill_cell_index The fill cell to place\n"
"@param kernel_origin The fill cell's footprint\n"
"@param row_step The fill cell's footprint\n"
"@param column_step The fill cell's footprint\n"
"@param origin The global origin of the fill pattern or nil to allow local (per-polygon) optimization\n"
"@param remaining_parts See explanation below\n"
"@param fill_margin See explanation below\n"
"@param remaining_polygons See explanation below\n"
"\n"
"This version is similar to the version providing a rectangular fill kernel, but it offers a more generic, diamond-shaped kernel.\n"
"The kerne is defined by an origin and two vectors (row_step and column_step) which span the diamond.\n"
"This version will try to fit as many of these diamond-shaped kernels into the region to fill.\n"
"\n"
"This variant has been introduced in version 0.27.\n"
) +
gsi::method_ext ("begin_shapes_rec", &begin_shapes_rec, gsi::arg ("layer"),
"@brief Delivers a recursive shape iterator for the shapes below the cell on the given layer\n"
"@param layer The layer from which to get the shapes\n"

View File

@ -398,6 +398,30 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
"\n"
"@return The transformed edge pairs.\n"
) +
method ("transformed", (db::EdgePairs (db::EdgePairs::*)(const db::IMatrix2d &) const) &db::EdgePairs::transformed, gsi::arg ("t"),
"@brief Transform the edge pair collection\n"
"\n"
"Transforms the edge pairs with the given 2d matrix transformation.\n"
"Does not modify the edge pair collection but returns the transformed edge pairs.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed edge pairs.\n"
"\n"
"This variant has been introduced in version 0.27.\n"
) +
method ("transformed", (db::EdgePairs (db::EdgePairs::*)(const db::IMatrix3d &) const) &db::EdgePairs::transformed, gsi::arg ("t"),
"@brief Transform the edge pair collection\n"
"\n"
"Transforms the edge pairs with the given 3d matrix transformation.\n"
"Does not modify the edge pair collection but returns the transformed edge pairs.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed edge pairs.\n"
"\n"
"This variant has been introduced in version 0.27.\n"
) +
method ("transform", (db::EdgePairs &(db::EdgePairs::*)(const db::Trans &)) &db::EdgePairs::transform, gsi::arg ("t"),
"@brief Transform the edge pair collection (modifies self)\n"
"\n"
@ -418,6 +442,30 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
"\n"
"@return The transformed edge pair collection.\n"
) +
method ("transform", (db::EdgePairs &(db::EdgePairs::*)(const db::IMatrix2d &)) &db::EdgePairs::transform, gsi::arg ("t"),
"@brief Transform the edge pair collection (modifies self)\n"
"\n"
"Transforms the edge pair collection with the given 2d matrix transformation.\n"
"This version modifies the edge pair collection and returns a reference to self.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed edge pair collection.\n"
"\n"
"This variant has been introduced in version 0.27.\n"
) +
method ("transform", (db::EdgePairs &(db::EdgePairs::*)(const db::IMatrix3d &)) &db::EdgePairs::transform, gsi::arg ("t"),
"@brief Transform the edge pair collection (modifies self)\n"
"\n"
"Transforms the edge pair collection with the given 3d matrix transformation.\n"
"This version modifies the edge pair collection and returns a reference to self.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed edge pair collection.\n"
"\n"
"This variant has been introduced in version 0.27.\n"
) +
method_ext ("insert", &insert_e, gsi::arg ("edge_pairs"),
"@brief Inserts all edge pairs from the other edge pair collection into this edge pair collection\n"
"This method has been introduced in version 0.25."

View File

@ -1040,6 +1040,30 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
"\n"
"@return The transformed edge collection.\n"
) +
method ("transformed", (db::Edges (db::Edges::*)(const db::IMatrix2d &) const) &db::Edges::transformed, gsi::arg ("t"),
"@brief Transform the edge collection\n"
"\n"
"Transforms the edge collection with the given 2d matrix transformation.\n"
"Does not modify the edge collection but returns the transformed edge collection.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed edge collection.\n"
"\n"
"This variant has been introduced in version 0.27."
) +
method ("transformed", (db::Edges (db::Edges::*)(const db::IMatrix3d &) const) &db::Edges::transformed, gsi::arg ("t"),
"@brief Transform the edge collection\n"
"\n"
"Transforms the edge collection with the given 3d matrix transformation.\n"
"Does not modify the edge collection but returns the transformed edge collection.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed edge collection.\n"
"\n"
"This variant has been introduced in version 0.27."
) +
method ("transform", (db::Edges &(db::Edges::*)(const db::Trans &)) &db::Edges::transform, gsi::arg ("t"),
"@brief Transform the edge collection (modifies self)\n"
"\n"
@ -1060,6 +1084,30 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
"\n"
"@return The transformed edge collection.\n"
) +
method ("transform", (db::Edges &(db::Edges::*)(const db::IMatrix2d &)) &db::Edges::transform, gsi::arg ("t"),
"@brief Transform the edge collection (modifies self)\n"
"\n"
"Transforms the edge collection with the given 2d matrix transformation.\n"
"This version modifies the edge collection and returns a reference to self.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed edge collection.\n"
"\n"
"This variant has been introduced in version 0.27."
) +
method ("transform", (db::Edges &(db::Edges::*)(const db::IMatrix3d &)) &db::Edges::transform, gsi::arg ("t"),
"@brief Transform the edge collection (modifies self)\n"
"\n"
"Transforms the edge collection with the given 3d matrix transformation.\n"
"This version modifies the edge collection and returns a reference to self.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed edge collection.\n"
"\n"
"This variant has been introduced in version 0.27."
) +
method_ext ("width_check", &width2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
"@brief Performs a width check with options\n"
"@param d The minimum width for which the edges are checked\n"

View File

@ -24,6 +24,9 @@
#include "gsiDecl.h"
#include "dbMatrix.h"
#include "dbTrans.h"
#include "dbBox.h"
#include "dbPolygon.h"
#include "dbEdge.h"
namespace gsi
{
@ -31,62 +34,104 @@ namespace gsi
// ---------------------------------------------------------------
// Matrix2d binding
static db::Matrix2d *new_matrix2d ()
template <class C>
static db::matrix_2d<C> *new_matrix2d ()
{
return new db::Matrix2d (1.0);
return new db::matrix_2d<C> (1.0);
}
static db::Matrix2d *new_matrix2d_m (double mag)
template <class C>
static db::matrix_2d<C> *new_matrix2d_m (double mag)
{
return new db::Matrix2d (mag);
return new db::matrix_2d<C> (mag);
}
static db::Matrix2d *new_matrix2d_m2 (double mx, double my)
template <class C>
static db::matrix_2d<C> *new_matrix2d_m2 (double mx, double my)
{
return new db::Matrix2d (mx, my);
return new db::matrix_2d<C> (mx, my);
}
static db::Matrix2d *new_matrix2d_t (const db::DCplxTrans &t)
template <class C>
static db::matrix_2d<C> *new_matrix2d_t (const db::DCplxTrans &t)
{
return new db::Matrix2d (t);
return new db::matrix_2d<C> (t);
}
static db::Matrix2d *new_matrix2d_mrm (double mag, double rot, bool m)
template <class C>
static db::matrix_2d<C> *new_matrix2d_mrm (double mag, double rot, bool m)
{
return new db::Matrix2d (db::Matrix2d::rotation (rot) * db::Matrix2d::mag (mag) * db::Matrix2d::mirror (m));
return new db::matrix_2d<C> (db::matrix_2d<C>::rotation (rot) * db::matrix_2d<C>::mag (mag) * db::matrix_2d<C>::mirror (m));
}
static db::Matrix2d *new_matrix2d_smrm (double shear, double mx, double my, double rot, bool m)
template <class C>
static db::matrix_2d<C> *new_matrix2d_smrm (double shear, double mx, double my, double rot, bool m)
{
return new db::Matrix2d (db::Matrix2d::rotation (rot) * db::Matrix2d::shear (shear) * db::Matrix2d::mag (mx, my) * db::Matrix2d::mirror (m));
return new db::matrix_2d<C> (db::matrix_2d<C>::rotation (rot) * db::matrix_2d<C>::shear (shear) * db::matrix_2d<C>::mag (mx, my) * db::matrix_2d<C>::mirror (m));
}
static db::Matrix2d *new_matrix2d_m4 (double m11, double m12, double m21, double m22)
template <class C>
static db::matrix_2d<C> *new_matrix2d_m4 (double m11, double m12, double m21, double m22)
{
return new db::Matrix2d (m11, m12, m21, m22);
return new db::matrix_2d<C> (m11, m12, m21, m22);
}
static db::DCplxTrans to_cplx_trans (const db::Matrix2d *m)
template <class C>
static db::complex_trans<C, C> to_cplx_trans (const db::matrix_2d<C> *m)
{
return db::DCplxTrans (db::Matrix3d (*m));
return db::complex_trans<C, C> (db::matrix_3d<C> (*m));
}
static db::Matrix2d sum_m (const db::Matrix2d *m, const db::Matrix2d &d)
template <class C>
static db::matrix_2d<C> sum_m (const db::matrix_2d<C> *m, const db::matrix_2d<C> &d)
{
return *m + d;
}
static db::Matrix2d prod_m (const db::Matrix2d *m, const db::Matrix2d &d)
template <class C>
static db::matrix_2d<C> prod_m (const db::matrix_2d<C> *m, const db::matrix_2d<C> &d)
{
return *m * d;
}
static db::DPoint trans_p (const db::Matrix2d *m, const db::DPoint &p)
template <class C>
static db::point<C> trans_p (const db::matrix_2d<C> *m, const db::point<C> &p)
{
return *m * p;
}
static double coeff_m (const db::Matrix2d *m, int i, int j)
template <class C>
static db::vector<C> trans_v (const db::matrix_2d<C> *m, const db::vector<C> &p)
{
return *m * p;
}
template <class C>
static db::polygon<C> trans_polygon (const db::matrix_2d<C> *m, const db::polygon<C> &p)
{
return p.transformed (*m);
}
template <class C>
static db::simple_polygon<C> trans_simple_polygon (const db::matrix_2d<C> *m, const db::simple_polygon<C> &p)
{
return p.transformed (*m);
}
template <class C>
static db::box<C> trans_box (const db::matrix_2d<C> *m, const db::box<C> &p)
{
return p.transformed (*m);
}
template <class C>
static db::edge<C> trans_edge (const db::matrix_2d<C> *m, const db::edge<C> &e)
{
return e.transformed (*m);
}
template <class C>
static double coeff_m (const db::matrix_2d<C> *m, int i, int j)
{
if (i == 0 && j == 0) {
return m->m11 ();
@ -101,211 +146,307 @@ static double coeff_m (const db::Matrix2d *m, int i, int j)
}
}
template <class C>
gsi::Methods
matrix2d_methods ()
{
return
gsi::constructor ("new", &new_matrix2d<C>,
"@brief Create a new Matrix2d representing a unit transformation"
) +
gsi::constructor ("new", &new_matrix2d_m<C>, gsi::arg ("m"),
"@brief Create a new Matrix2d representing an isotropic magnification\n"
"@param m The magnification\n"
) +
gsi::constructor ("new", &new_matrix2d_m2<C>, gsi::arg ("mx"), gsi::arg ("my"),
"@brief Create a new Matrix2d representing an anisotropic magnification\n"
"@param mx The magnification in x direction\n"
"@param my The magnification in y direction\n"
) +
gsi::constructor ("new", &new_matrix2d_t<C>, gsi::arg ("t"),
"@brief Create a new Matrix2d from the given complex transformation"
"@param t The transformation from which to create the matrix (not taking into account the displacement)\n"
) +
gsi::constructor ("newc", &new_matrix2d_mrm<C>, gsi::arg ("mag"), gsi::arg ("rotation"), gsi::arg ("mirror"),
"@brief Create a new Matrix2d representing an isotropic magnification, rotation and mirroring\n"
"@param mag The magnification in x direction\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirror The mirror flag (at x axis)\n"
"\n"
"This constructor is provided to construct a matrix similar to the complex transformation.\n"
"This constructor is called 'newc' to distinguish it from the constructors taking matrix coefficients ('c' is for composite).\n"
"The order of execution of the operations is mirror, magnification, rotation (as for complex transformations).\n"
) +
gsi::constructor ("newc", &new_matrix2d_smrm<C>, gsi::arg ("shear"), gsi::arg ("mx"), gsi::arg ("my"), gsi::arg ("rotation"), gsi::arg ("mirror"),
"@brief Create a new Matrix2d representing a shear, anisotropic magnification, rotation and mirroring\n"
"@param shear The shear angle\n"
"@param mx The magnification in x direction\n"
"@param my The magnification in y direction\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirror The mirror flag (at x axis)\n"
"\n"
"The order of execution of the operations is mirror, magnification, shear and rotation.\n"
"This constructor is called 'newc' to distinguish it from the constructor taking the four matrix coefficients ('c' is for composite).\n"
) +
gsi::constructor ("new", &new_matrix2d_m4<C>, gsi::arg ("m11"), gsi::arg ("m12"), gsi::arg ("m21"), gsi::arg ("m22"),
"@brief Create a new Matrix2d from the four coefficients\n"
) +
gsi::method ("m11", &db::matrix_2d<C>::m11,
"@brief Gets the m11 coefficient.\n"
"@return The value of the m11 coefficient\n"
) +
gsi::method ("m12", &db::matrix_2d<C>::m12,
"@brief Gets the m12 coefficient.\n"
"@return The value of the m12 coefficient\n"
) +
gsi::method ("m21", &db::matrix_2d<C>::m21,
"@brief Gets the m21 coefficient.\n"
"@return The value of the m21 coefficient\n"
) +
gsi::method ("m22", &db::matrix_2d<C>::m22,
"@brief Gets the m22 coefficient.\n"
"@return The value of the m22 coefficient\n"
) +
gsi::method_ext ("m", &coeff_m<C>, gsi::arg ("i"), gsi::arg ("j"),
"@brief Gets the m coefficient with the given index.\n"
"@return The coefficient [i,j]\n"
) +
gsi::method ("to_s", &db::matrix_2d<C>::to_string,
"@brief Convert the matrix to a string.\n"
"@return The string representing this matrix\n"
) +
gsi::method ("inverted", &db::matrix_2d<C>::inverted,
"@brief The inverse of this matrix.\n"
"@return The inverse of this matrix\n"
) +
gsi::method_ext ("trans|*", &trans_p<C>, gsi::arg ("p"),
"@brief Transforms a point with this matrix.\n"
"@param p The point to transform.\n"
"@return The transformed point\n"
) +
gsi::method_ext ("*", &trans_v<C>, gsi::arg ("v"),
"@brief Transforms a vector with this matrix.\n"
"@param v The vector to transform.\n"
"@return The transformed vector\n"
) +
gsi::method_ext ("*", &trans_edge<C>, gsi::arg ("e"),
"@brief Transforms an edge with this matrix.\n"
"@param e The edge to transform.\n"
"@return The transformed edge\n"
) +
gsi::method_ext ("*", &trans_box<C>, gsi::arg ("box"),
"@brief Transforms a box with this matrix.\n"
"@param box The box to transform.\n"
"@return The transformed box\n"
"\n"
"Please note that the box remains a box, even though the matrix supports shear and rotation. The returned box "
"will be the bounding box of the sheared and rotated rectangle."
) +
gsi::method_ext ("*", &trans_simple_polygon<C>, gsi::arg ("p"),
"@brief Transforms a simple polygon with this matrix.\n"
"@param p The simple polygon to transform.\n"
"@return The transformed simple polygon\n"
) +
gsi::method_ext ("*", &trans_polygon<C>, gsi::arg ("p"),
"@brief Transforms a polygon with this matrix.\n"
"@param p The polygon to transform.\n"
"@return The transformed polygon\n"
) +
gsi::method_ext ("*", &prod_m<C>, gsi::arg ("m"),
"@brief Product of two matrices.\n"
"@param m The other matrix.\n"
"@return The matrix product self*m\n"
) +
gsi::method_ext ("+", &sum_m<C>, gsi::arg ("m"),
"@brief Sum of two matrices.\n"
"@param m The other matrix.\n"
"@return The (element-wise) sum of self+m\n"
) +
gsi::method_ext ("cplx_trans", &to_cplx_trans<C>,
"@brief Converts this matrix to a complex transformation (if possible).\n"
"@return The complex transformation.\n"
"This method is successful only if the matrix does not contain shear components and the magnification must be isotropic.\n"
) +
gsi::method ("angle", &db::matrix_2d<C>::angle,
"@brief Returns the rotation angle of the rotation component of this matrix.\n"
"@return The angle in degree.\n"
"The matrix is decomposed into basic transformations assuming an execution order of "
"mirroring at the x axis, rotation, magnification and shear."
) +
gsi::method ("mag_x", (double (db::matrix_2d<C>::*) () const) &db::matrix_2d<C>::mag_x,
"@brief Returns the x magnification of the magnification component of this matrix.\n"
"@return The magnification factor.\n"
"The matrix is decomposed into basic transformations assuming an execution order of "
"mirroring at the x axis, magnification, shear and rotation."
) +
gsi::method ("mag_y", (double (db::matrix_2d<C>::*) () const) &db::matrix_2d<C>::mag_y,
"@brief Returns the y magnification of the magnification component of this matrix.\n"
"@return The magnification factor.\n"
"The matrix is decomposed into basic transformations assuming an execution order of "
"mirroring at the x axis, magnification, shear and rotation."
) +
gsi::method ("shear_angle", &db::matrix_2d<C>::shear_angle,
"@brief Returns the magnitude of the shear component of this matrix.\n"
"@return The shear angle in degree.\n"
"The matrix is decomposed into basic transformations assuming an execution order of "
"mirroring at the x axis, rotation, magnification and shear.\n"
"The shear basic transformation will tilt the x axis towards the y axis and vice versa. The shear angle "
"gives the tilt angle of the axes towards the other one. The possible range for this angle is -45 to 45 degree."
) +
gsi::method ("is_mirror?", &db::matrix_2d<C>::is_mirror,
"@brief Returns the mirror flag of this matrix.\n"
"@return True if this matrix has a mirror component.\n"
"The matrix is decomposed into basic transformations assuming an execution order of "
"mirroring at the x axis, rotation, magnification and shear."
);
}
gsi::Class<db::Matrix2d> decl_Matrix2d ("db", "Matrix2d",
gsi::constructor ("new", &new_matrix2d,
"@brief Create a new Matrix2d representing a unit transformation"
) +
gsi::constructor ("new", &new_matrix2d_m, gsi::arg ("m"),
"@brief Create a new Matrix2d representing an isotropic magnification\n"
"@param m The magnification\n"
) +
gsi::constructor ("new", &new_matrix2d_m2, gsi::arg ("mx"), gsi::arg ("my"),
"@brief Create a new Matrix2d representing an anisotropic magnification\n"
"@param mx The magnification in x direction\n"
"@param my The magnification in y direction\n"
) +
gsi::constructor ("new", &new_matrix2d_t, gsi::arg ("t"),
"@brief Create a new Matrix2d from the given complex transformation"
"@param t The transformation from which to create the matrix (not taking into account the displacement)\n"
) +
gsi::constructor ("newc", &new_matrix2d_mrm, gsi::arg ("mag"), gsi::arg ("rotation"), gsi::arg ("mirror"),
"@brief Create a new Matrix2d representing an isotropic magnification, rotation and mirroring\n"
"@param mag The magnification in x direction\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirror The mirror flag (at x axis)\n"
"\n"
"This constructor is provided to construct a matrix similar to the complex transformation.\n"
"This constructor is called 'newc' to distinguish it from the constructors taking matrix coefficients ('c' is for composite).\n"
"The order of execution of the operations is mirror, magnification, rotation (as for complex transformations).\n"
) +
gsi::constructor ("newc", &new_matrix2d_smrm, gsi::arg ("shear"), gsi::arg ("mx"), gsi::arg ("my"), gsi::arg ("rotation"), gsi::arg ("mirror"),
"@brief Create a new Matrix2d representing a shear, anisotropic magnification, rotation and mirroring\n"
"@param shear The shear angle\n"
"@param mx The magnification in x direction\n"
"@param my The magnification in y direction\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirror The mirror flag (at x axis)\n"
"\n"
"The order of execution of the operations is mirror, magnification, shear and rotation.\n"
"This constructor is called 'newc' to distinguish it from the constructor taking the four matrix coefficients ('c' is for composite).\n"
) +
gsi::constructor ("new", &new_matrix2d_m4, gsi::arg ("m11"), gsi::arg ("m12"), gsi::arg ("m21"), gsi::arg ("m22"),
"@brief Create a new Matrix2d from the four coefficients\n"
) +
gsi::method ("m11", &db::Matrix2d::m11,
"@brief Gets the m11 coefficient.\n"
"@return The value of the m11 coefficient\n"
) +
gsi::method ("m12", &db::Matrix2d::m12,
"@brief Gets the m12 coefficient.\n"
"@return The value of the m12 coefficient\n"
) +
gsi::method ("m21", &db::Matrix2d::m21,
"@brief Gets the m21 coefficient.\n"
"@return The value of the m21 coefficient\n"
) +
gsi::method ("m22", &db::Matrix2d::m22,
"@brief Gets the m22 coefficient.\n"
"@return The value of the m22 coefficient\n"
) +
gsi::method_ext ("m", &coeff_m, gsi::arg ("i"), gsi::arg ("j"),
"@brief Gets the m coefficient with the given index.\n"
"@return The coefficient [i,j]\n"
) +
gsi::method ("to_s", &db::Matrix2d::to_string,
"@brief Convert the matrix to a string.\n"
"@return The string representing this matrix\n"
) +
gsi::method ("inverted", &db::Matrix2d::inverted,
"@brief The inverse of this matrix.\n"
"@return The inverse of this matrix\n"
) +
gsi::method_ext ("trans", &trans_p, gsi::arg ("p"),
"@brief Transforms a point with this matrix.\n"
"@param p The point to transform.\n"
"@return The product if self and the point p\n"
) +
gsi::method_ext ("*", &prod_m, gsi::arg ("m"),
"@brief Product of two matrices.\n"
"@param m The other matrix.\n"
"@return The matrix product self*m\n"
) +
gsi::method_ext ("+", &sum_m, gsi::arg ("m"),
"@brief Sum of two matrices.\n"
"@param m The other matrix.\n"
"@return The (element-wise) sum of self+m\n"
) +
gsi::method_ext ("cplx_trans", &to_cplx_trans,
"@brief Converts this matrix to a complex transformation (if possible).\n"
"@return The complex transformation.\n"
"This method is successful only if the matrix does not contain shear components and the magnification must be isotropic.\n"
) +
gsi::method ("angle", &db::Matrix2d::angle,
"@brief Returns the rotation angle of the rotation component of this matrix.\n"
"@return The angle in degree.\n"
"The matrix is decomposed into basic transformations assuming an execution order of "
"mirroring at the x axis, rotation, magnification and shear."
) +
gsi::method ("mag_x", (double (db::Matrix2d::*) () const) &db::Matrix2d::mag_x,
"@brief Returns the x magnification of the magnification component of this matrix.\n"
"@return The magnification factor.\n"
"The matrix is decomposed into basic transformations assuming an execution order of "
"mirroring at the x axis, magnification, shear and rotation."
) +
gsi::method ("mag_y", (double (db::Matrix2d::*) () const) &db::Matrix2d::mag_y,
"@brief Returns the y magnification of the magnification component of this matrix.\n"
"@return The magnification factor.\n"
"The matrix is decomposed into basic transformations assuming an execution order of "
"mirroring at the x axis, magnification, shear and rotation."
) +
gsi::method ("shear_angle", &db::Matrix2d::shear_angle,
"@brief Returns the magnitude of the shear component of this matrix.\n"
"@return The shear angle in degree.\n"
"The matrix is decomposed into basic transformations assuming an execution order of "
"mirroring at the x axis, rotation, magnification and shear.\n"
"The shear basic transformation will tilt the x axis towards the y axis and vice versa. The shear angle "
"gives the tilt angle of the axes towards the other one. The possible range for this angle is -45 to 45 degree."
) +
gsi::method ("is_mirror?", &db::Matrix2d::is_mirror,
"@brief Returns the mirror flag of this matrix.\n"
"@return True if this matrix has a mirror component.\n"
"The matrix is decomposed into basic transformations assuming an execution order of "
"mirroring at the x axis, rotation, magnification and shear."
),
matrix2d_methods<db::DCoord> (),
"@brief A 2d matrix object used mainly for representing rotation and shear transformations.\n"
"\n"
"This object represents a 2x2 matrix. This matrix is used to represent affine transformations "
"This object represents a 2x2 matrix. This matrix is used to implement affine transformations "
"in the 2d space mainly. It can be decomposed into basic transformations: mirroring, rotation and shear. "
"In that case, the assumed execution order of the basic transformations is "
"mirroring at the x axis, rotation, magnification and shear."
"mirroring at the x axis, rotation, magnification and shear.\n"
"\n"
"The matrix is a generalisation of the transformations and is of limited use in a layout database context. "
"It is useful however to implement shear transformations on polygons, edges and polygon or edge collections."
"\n\n"
"This class was introduced in version 0.22.\n"
);
gsi::Class<db::IMatrix2d> decl_IMatrix2d ("db", "IMatrix2d",
matrix2d_methods<db::Coord> (),
"@brief A 2d matrix object used mainly for representing rotation and shear transformations (integer coordinate version).\n"
"\n"
"This object represents a 2x2 matrix. This matrix is used to implement affine transformations "
"in the 2d space mainly. It can be decomposed into basic transformations: mirroring, rotation and shear. "
"In that case, the assumed execution order of the basic transformations is "
"mirroring at the x axis, rotation, magnification and shear."
"\n\n"
"The integer variant was introduced in version 0.27.\n"
);
// ---------------------------------------------------------------
// Matrix2d binding
// Matrix3d binding
static db::Matrix3d *new_matrix3d ()
template <class C>
static db::matrix_3d<C> *new_matrix3d ()
{
return new db::Matrix3d (1.0);
return new db::matrix_3d<C> (1.0);
}
static db::Matrix3d *new_matrix3d_t (const db::DCplxTrans &t)
template <class C>
static db::matrix_3d<C> *new_matrix3d_t (const db::complex_trans<C, C> &t)
{
return new db::Matrix3d (t);
return new db::matrix_3d<C> (t);
}
static db::Matrix3d *new_matrix3d_m (double mag)
template <class C>
static db::matrix_3d<C> *new_matrix3d_m (double mag)
{
return new db::Matrix3d (mag);
return new db::matrix_3d<C> (mag);
}
static db::Matrix3d *new_matrix3d_mrm (double mag, double rot, bool m)
template <class C>
static db::matrix_3d<C> *new_matrix3d_mrm (double mag, double rot, bool m)
{
return new db::Matrix3d (db::Matrix3d::rotation (rot) * db::Matrix3d::mag (mag) * db::Matrix3d::mirror (m));
return new db::matrix_3d<C> (db::matrix_3d<C>::rotation (rot) * db::matrix_3d<C>::mag (mag) * db::matrix_3d<C>::mirror (m));
}
static db::Matrix3d *new_matrix3d_smrm (double shear, double mx, double my, double rot, bool m)
template <class C>
static db::matrix_3d<C> *new_matrix3d_smrm (double shear, double mx, double my, double rot, bool m)
{
return new db::Matrix3d (db::Matrix3d::rotation (rot) * db::Matrix3d::shear (shear) * db::Matrix3d::mag (mx, my) * db::Matrix3d::mirror (m));
return new db::matrix_3d<C> (db::matrix_3d<C>::rotation (rot) * db::matrix_3d<C>::shear (shear) * db::matrix_3d<C>::mag (mx, my) * db::matrix_3d<C>::mirror (m));
}
static db::Matrix3d *new_matrix3d_dsmrm (const db::DVector &d, double shear, double mx, double my, double rot, bool m)
template <class C>
static db::matrix_3d<C> *new_matrix3d_dsmrm (const db::vector<C> &d, double shear, double mx, double my, double rot, bool m)
{
return new db::Matrix3d (db::Matrix3d::disp (d) * db::Matrix3d::rotation (rot) * db::Matrix3d::shear (shear) * db::Matrix3d::mag (mx, my) * db::Matrix3d::mirror (m));
return new db::matrix_3d<C> (db::matrix_3d<C>::disp (d) * db::matrix_3d<C>::rotation (rot) * db::matrix_3d<C>::shear (shear) * db::matrix_3d<C>::mag (mx, my) * db::matrix_3d<C>::mirror (m));
}
static db::Matrix3d *new_matrix3d_pdsmrm (double tx, double ty, double z, const db::DVector &d, double shear, double mx, double my, double rot, bool m)
template <class C>
static db::matrix_3d<C> *new_matrix3d_pdsmrm (double tx, double ty, double z, const db::vector<C> &d, double shear, double mx, double my, double rot, bool m)
{
return new db::Matrix3d (db::Matrix3d::disp (d) * db::Matrix3d::perspective (tx, ty, z) * db::Matrix3d::rotation (rot) * db::Matrix3d::shear (shear) * db::Matrix3d::mag (mx, my) * db::Matrix3d::mirror (m));
return new db::matrix_3d<C> (db::matrix_3d<C>::disp (d) * db::matrix_3d<C>::perspective (tx, ty, z) * db::matrix_3d<C>::rotation (rot) * db::matrix_3d<C>::shear (shear) * db::matrix_3d<C>::mag (mx, my) * db::matrix_3d<C>::mirror (m));
}
static db::Matrix3d *new_matrix3d_m4 (double m11, double m12, double m21, double m22)
template <class C>
static db::matrix_3d<C> *new_matrix3d_m4 (double m11, double m12, double m21, double m22)
{
return new db::Matrix3d (m11, m12, m21, m22);
return new db::matrix_3d<C> (m11, m12, m21, m22);
}
static db::Matrix3d *new_matrix3d_m6 (double m11, double m12, double m21, double m22, double dx, double dy)
template <class C>
static db::matrix_3d<C> *new_matrix3d_m6 (double m11, double m12, double m21, double m22, double dx, double dy)
{
return new db::Matrix3d (m11, m12, m21, m22, dx, dy, 0.0, 0.0);
return new db::matrix_3d<C> (m11, m12, m21, m22, dx, dy, 0.0, 0.0);
}
static db::Matrix3d *new_matrix3d_m9 (double m11, double m12, double m13, double m21, double m22, double m23, double m31, double m32, double m33)
template <class C>
static db::matrix_3d<C> *new_matrix3d_m9 (double m11, double m12, double m13, double m21, double m22, double m23, double m31, double m32, double m33)
{
return new db::Matrix3d (m11, m12, m13, m21, m22, m23, m31, m32, m33);
return new db::matrix_3d<C> (m11, m12, m13, m21, m22, m23, m31, m32, m33);
}
static db::DCplxTrans to_cplx_trans3 (const db::Matrix3d *m)
template <class C>
static db::DCplxTrans to_cplx_trans3 (const db::matrix_3d<C> *m)
{
return db::DCplxTrans (*m);
}
static db::Matrix3d sum_m3 (const db::Matrix3d *m, const db::Matrix3d &d)
template <class C>
static db::matrix_3d<C> sum_m3 (const db::matrix_3d<C> *m, const db::matrix_3d<C> &d)
{
return *m + d;
}
static db::Matrix3d prod_m3 (const db::Matrix3d *m, const db::Matrix3d &d)
template <class C>
static db::matrix_3d<C> prod_m3 (const db::matrix_3d<C> *m, const db::matrix_3d<C> &d)
{
return *m * d;
}
static db::DPoint trans_p3 (const db::Matrix3d *m, const db::DPoint &p)
template <class C>
static db::point<C> trans_p3 (const db::matrix_3d<C> *m, const db::point<C> &p)
{
return *m * p;
}
static double coeff_m3 (const db::Matrix3d *m, int i, int j)
template <class C>
static db::vector<C> trans_v3 (const db::matrix_3d<C> *m, const db::vector<C> &p)
{
return *m * p;
}
template <class C>
static db::polygon<C> trans_polygon3 (const db::matrix_3d<C> *m, const db::polygon<C> &p)
{
return p.transformed (*m);
}
template <class C>
static db::simple_polygon<C> trans_simple_polygon3 (const db::matrix_3d<C> *m, const db::simple_polygon<C> &p)
{
return p.transformed (*m);
}
template <class C>
static db::box<C> trans_box3 (const db::matrix_3d<C> *m, const db::box<C> &p)
{
return p.transformed (*m);
}
template <class C>
static db::edge<C> trans_edge3 (const db::matrix_3d<C> *m, const db::edge<C> &e)
{
return e.transformed (*m);
}
template <class C>
static double coeff_m3 (const db::matrix_3d<C> *m, int i, int j)
{
if (i < 0 || i >= 3 || j < 0 || j >= 3) {
return 0.0;
@ -359,166 +500,198 @@ static int adjust_all ()
return db::MatrixAdjustFlags::All;
}
template <class C>
gsi::Methods
matrix3d_methods ()
{
return
gsi::constructor ("new", &new_matrix3d<C>,
"@brief Create a new Matrix3d representing a unit transformation"
) +
gsi::constructor ("new", &new_matrix3d_m<C>, gsi::arg ("m"),
"@brief Create a new Matrix3d representing a magnification\n"
"@param m The magnification\n"
) +
gsi::constructor ("new", &new_matrix3d_t<C>, gsi::arg ("t"),
"@brief Create a new Matrix3d from the given complex transformation"
"@param t The transformation from which to create the matrix\n"
) +
gsi::constructor ("newc", &new_matrix3d_mrm<C>, gsi::arg ("mag"), gsi::arg ("rotation"), gsi::arg ("mirrx"),
"@brief Create a new Matrix3d representing a isotropic magnification, rotation and mirroring\n"
"@param mag The magnification\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirrx The mirror flag (at x axis)\n"
"\n"
"The order of execution of the operations is mirror, magnification and rotation.\n"
"This constructor is called 'newc' to distinguish it from the constructors taking coefficients ('c' is for composite).\n"
) +
gsi::constructor ("newc", &new_matrix3d_smrm<C>, gsi::arg ("shear"), gsi::arg ("mx"), gsi::arg ("my"), gsi::arg ("rotation"), gsi::arg ("mirrx"),
"@brief Create a new Matrix3d representing a shear, anisotropic magnification, rotation and mirroring\n"
"@param shear The shear angle\n"
"@param mx The magnification in x direction\n"
"@param mx The magnification in y direction\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirrx The mirror flag (at x axis)\n"
"\n"
"The order of execution of the operations is mirror, magnification, rotation and shear.\n"
"This constructor is called 'newc' to distinguish it from the constructor taking the four matrix coefficients ('c' is for composite).\n"
) +
gsi::constructor ("newc", &new_matrix3d_dsmrm<C>, gsi::arg ("u"), gsi::arg ("shear"), gsi::arg ("mx"), gsi::arg ("my"), gsi::arg ("rotation"), gsi::arg ("mirrx"),
"@brief Create a new Matrix3d representing a displacement, shear, anisotropic magnification, rotation and mirroring\n"
"@param u The displacement\n"
"@param shear The shear angle\n"
"@param mx The magnification in x direction\n"
"@param mx The magnification in y direction\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirrx The mirror flag (at x axis)\n"
"\n"
"The order of execution of the operations is mirror, magnification, rotation, shear and displacement.\n"
"This constructor is called 'newc' to distinguish it from the constructor taking the four matrix coefficients ('c' is for composite).\n"
"\n"
"Starting with version 0.25 the displacement is of vector type."
) +
gsi::constructor ("newc", &new_matrix3d_pdsmrm<C>, gsi::arg ("tx"), gsi::arg ("ty"), gsi::arg ("z"), gsi::arg ("u"), gsi::arg ("shear"), gsi::arg ("mx"), gsi::arg ("my"), gsi::arg ("rotation"), gsi::arg ("mirrx"),
"@brief Create a new Matrix3d representing a perspective distortion, displacement, shear, anisotropic magnification, rotation and mirroring\n"
"@param tx The perspective tilt angle x (around the y axis)\n"
"@param ty The perspective tilt angle y (around the x axis)\n"
"@param z The observer distance at which the tilt angles are given\n"
"@param u The displacement\n"
"@param shear The shear angle\n"
"@param mx The magnification in x direction\n"
"@param mx The magnification in y direction\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirrx The mirror flag (at x axis)\n"
"\n"
"The order of execution of the operations is mirror, magnification, rotation, shear, perspective distortion and displacement.\n"
"This constructor is called 'newc' to distinguish it from the constructor taking the four matrix coefficients ('c' is for composite).\n"
"\n"
"The tx and ty parameters represent the perspective distortion. They denote a tilt of the xy plane around the y axis (tx) or the x axis (ty) in degree. "
"The same effect is achieved for different tilt angles for different observer distances. Hence, the observer distance must be given at which the tilt angles are given. "
"If the magnitude of the tilt angle is not important, z can be set to 1.\n"
"\n"
"Starting with version 0.25 the displacement is of vector type."
) +
gsi::constructor ("new", &new_matrix3d_m4<C>, gsi::arg ("m11"), gsi::arg ("m12"), gsi::arg ("m21"), gsi::arg ("m22"),
"@brief Create a new Matrix3d from the four coefficients of a Matrix2d\n"
) +
gsi::constructor ("new", &new_matrix3d_m6<C>, gsi::arg ("m11"), gsi::arg ("m12"), gsi::arg ("m21"), gsi::arg ("m22"), gsi::arg ("dx"), gsi::arg ("dy"),
"@brief Create a new Matrix3d from the four coefficients of a Matrix2d plus a displacement\n"
) +
gsi::constructor ("new", &new_matrix3d_m9<C>, gsi::arg ("m11"), gsi::arg ("m12"), gsi::arg ("m13"), gsi::arg ("m21"), gsi::arg ("m22"), gsi::arg ("m23"), gsi::arg ("m31"), gsi::arg ("m32"), gsi::arg ("m33"),
"@brief Create a new Matrix3d from the nine matrix coefficients\n"
) +
gsi::method_ext ("m", &coeff_m3<C>, gsi::arg ("i"), gsi::arg ("j"),
"@brief Gets the m coefficient with the given index.\n"
"@return The coefficient [i,j]\n"
) +
gsi::method ("to_s", &db::matrix_3d<C>::to_string,
"@brief Convert the matrix to a string.\n"
"@return The string representing this matrix\n"
) +
gsi::method ("inverted", &db::matrix_3d<C>::inverted,
"@brief The inverse of this matrix.\n"
"@return The inverse of this matrix\n"
) +
gsi::method_ext ("*", &prod_m3<C>, gsi::arg ("m"),
"@brief Product of two matrices.\n"
"@param m The other matrix.\n"
"@return The matrix product self*m\n"
) +
gsi::method_ext ("+", &sum_m3<C>, gsi::arg ("m"),
"@brief Sum of two matrices.\n"
"@param m The other matrix.\n"
"@return The (element-wise) sum of self+m\n"
) +
gsi::method_ext ("trans|*", &trans_p3<C>, gsi::arg ("p"),
"@brief Transforms a point with this matrix.\n"
"@param p The point to transform.\n"
"@return The transformed point\n"
) +
gsi::method_ext ("*", &trans_v3<C>, gsi::arg ("v"),
"@brief Transforms a vector with this matrix.\n"
"@param v The vector to transform.\n"
"@return The transformed vector\n"
) +
gsi::method_ext ("*", &trans_edge3<C>, gsi::arg ("e"),
"@brief Transforms an edge with this matrix.\n"
"@param e The edge to transform.\n"
"@return The transformed edge\n"
) +
gsi::method_ext ("*", &trans_box3<C>, gsi::arg ("box"),
"@brief Transforms a box with this matrix.\n"
"@param box The box to transform.\n"
"@return The transformed box\n"
"\n"
"Please note that the box remains a box, even though the matrix supports shear and rotation. The returned box "
"will be the bounding box of the sheared and rotated rectangle."
) +
gsi::method_ext ("*", &trans_simple_polygon3<C>, gsi::arg ("p"),
"@brief Transforms a simple polygon with this matrix.\n"
"@param p The simple polygon to transform.\n"
"@return The transformed simple polygon\n"
) +
gsi::method_ext ("*", &trans_polygon3<C>, gsi::arg ("p"),
"@brief Transforms a polygon with this matrix.\n"
"@param p The polygon to transform.\n"
"@return The transformed polygon\n"
) +
gsi::method_ext ("cplx_trans", &to_cplx_trans3<C>,
"@brief Converts this matrix to a complex transformation (if possible).\n"
"@return The complex transformation.\n"
"This method is successful only if the matrix does not contain shear or perspective distortion components and the magnification must be isotropic.\n"
) +
gsi::method ("mag_x", (double (db::matrix_3d<C>::*) () const) &db::matrix_3d<C>::mag_x,
"@brief Returns the x magnification of the magnification component of this matrix.\n"
"@return The magnification factor.\n"
) +
gsi::method ("mag_y", (double (db::matrix_3d<C>::*) () const) &db::matrix_3d<C>::mag_y,
"@brief Returns the y magnification of the magnification component of this matrix.\n"
"@return The magnification factor.\n"
) +
gsi::method ("angle", &db::matrix_3d<C>::angle,
"@brief Returns the rotation angle of the rotation component of this matrix.\n"
"@return The angle in degree.\n"
"See the description of this class for details about the basic transformations."
) +
gsi::method ("shear_angle", &db::matrix_3d<C>::shear_angle,
"@brief Returns the magnitude of the shear component of this matrix.\n"
"@return The shear angle in degree.\n"
"The shear basic transformation will tilt the x axis towards the y axis and vice versa. The shear angle "
"gives the tilt angle of the axes towards the other one. The possible range for this angle is -45 to 45 degree."
"See the description of this class for details about the basic transformations."
) +
gsi::method ("disp", (db::vector<C> (db::matrix_3d<C>::*) () const) &db::matrix_3d<C>::disp,
"@brief Returns the displacement vector of this transformation.\n"
"\n"
"Starting with version 0.25 this method returns a vector type instead of a point.\n"
"@return The displacement vector.\n"
) +
gsi::method ("tx", &db::matrix_3d<C>::perspective_tilt_x, gsi::arg ("z"),
"@brief Returns the perspective tilt angle tx.\n"
"@param z The observer distance at which the tilt angle is computed.\n"
"@return The tilt angle tx.\n"
"The tx and ty parameters represent the perspective distortion. They denote a tilt of the xy plane around the y axis (tx) or the x axis (ty) in degree. "
"The same effect is achieved for different tilt angles at different observer distances. Hence, the observer distance must be specified at which the tilt angle is computed. "
"If the magnitude of the tilt angle is not important, z can be set to 1.\n"
) +
gsi::method ("ty", &db::matrix_3d<C>::perspective_tilt_y, gsi::arg ("z"),
"@brief Returns the perspective tilt angle ty.\n"
"@param z The observer distance at which the tilt angle is computed.\n"
"@return The tilt angle ty.\n"
"The tx and ty parameters represent the perspective distortion. They denote a tilt of the xy plane around the y axis (tx) or the x axis (ty) in degree. "
"The same effect is achieved for different tilt angles at different observer distances. Hence, the observer distance must be specified at which the tilt angle is computed. "
"If the magnitude of the tilt angle is not important, z can be set to 1.\n"
) +
gsi::method ("is_mirror?", &db::matrix_3d<C>::is_mirror,
"@brief Returns the mirror flag of this matrix.\n"
"@return True if this matrix has a mirror component.\n"
"See the description of this class for details about the basic transformations."
);
}
gsi::Class<db::Matrix3d> decl_Matrix3d ("db", "Matrix3d",
gsi::constructor ("new", &new_matrix3d,
"@brief Create a new Matrix3d representing a unit transformation"
) +
gsi::constructor ("new", &new_matrix3d_m, gsi::arg ("m"),
"@brief Create a new Matrix3d representing a magnification\n"
"@param m The magnification\n"
) +
gsi::constructor ("new", &new_matrix3d_t, gsi::arg ("t"),
"@brief Create a new Matrix3d from the given complex transformation"
"@param t The transformation from which to create the matrix\n"
) +
gsi::constructor ("newc", &new_matrix3d_mrm, gsi::arg ("mag"), gsi::arg ("rotation"), gsi::arg ("mirrx"),
"@brief Create a new Matrix3d representing a isotropic magnification, rotation and mirroring\n"
"@param mag The magnification\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirrx The mirror flag (at x axis)\n"
"\n"
"The order of execution of the operations is mirror, magnification and rotation.\n"
"This constructor is called 'newc' to distinguish it from the constructors taking coefficients ('c' is for composite).\n"
) +
gsi::constructor ("newc", &new_matrix3d_smrm, gsi::arg ("shear"), gsi::arg ("mx"), gsi::arg ("my"), gsi::arg ("rotation"), gsi::arg ("mirrx"),
"@brief Create a new Matrix3d representing a shear, anisotropic magnification, rotation and mirroring\n"
"@param shear The shear angle\n"
"@param mx The magnification in x direction\n"
"@param mx The magnification in y direction\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirrx The mirror flag (at x axis)\n"
"\n"
"The order of execution of the operations is mirror, magnification, rotation and shear.\n"
"This constructor is called 'newc' to distinguish it from the constructor taking the four matrix coefficients ('c' is for composite).\n"
) +
gsi::constructor ("newc", &new_matrix3d_dsmrm, gsi::arg ("u"), gsi::arg ("shear"), gsi::arg ("mx"), gsi::arg ("my"), gsi::arg ("rotation"), gsi::arg ("mirrx"),
"@brief Create a new Matrix3d representing a displacement, shear, anisotropic magnification, rotation and mirroring\n"
"@param u The displacement\n"
"@param shear The shear angle\n"
"@param mx The magnification in x direction\n"
"@param mx The magnification in y direction\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirrx The mirror flag (at x axis)\n"
"\n"
"The order of execution of the operations is mirror, magnification, rotation, shear and displacement.\n"
"This constructor is called 'newc' to distinguish it from the constructor taking the four matrix coefficients ('c' is for composite).\n"
"\n"
"Starting with version 0.25 the displacement is of vector type."
) +
gsi::constructor ("newc", &new_matrix3d_pdsmrm, gsi::arg ("tx"), gsi::arg ("ty"), gsi::arg ("z"), gsi::arg ("u"), gsi::arg ("shear"), gsi::arg ("mx"), gsi::arg ("my"), gsi::arg ("rotation"), gsi::arg ("mirrx"),
"@brief Create a new Matrix3d representing a perspective distortion, displacement, shear, anisotropic magnification, rotation and mirroring\n"
"@param tx The perspective tilt angle x (around the y axis)\n"
"@param ty The perspective tilt angle y (around the x axis)\n"
"@param z The observer distance at which the tilt angles are given\n"
"@param u The displacement\n"
"@param shear The shear angle\n"
"@param mx The magnification in x direction\n"
"@param mx The magnification in y direction\n"
"@param rotation The rotation angle (in degree)\n"
"@param mirrx The mirror flag (at x axis)\n"
"\n"
"The order of execution of the operations is mirror, magnification, rotation, shear, perspective distortion and displacement.\n"
"This constructor is called 'newc' to distinguish it from the constructor taking the four matrix coefficients ('c' is for composite).\n"
"\n"
"The tx and ty parameters represent the perspective distortion. They denote a tilt of the xy plane around the y axis (tx) or the x axis (ty) in degree. "
"The same effect is achieved for different tilt angles for different observer distances. Hence, the observer distance must be given at which the tilt angles are given. "
"If the magnitude of the tilt angle is not important, z can be set to 1.\n"
"\n"
"Starting with version 0.25 the displacement is of vector type."
) +
gsi::constructor ("new", &new_matrix3d_m4, gsi::arg ("m11"), gsi::arg ("m12"), gsi::arg ("m21"), gsi::arg ("m22"),
"@brief Create a new Matrix3d from the four coefficients of a Matrix2d\n"
) +
gsi::constructor ("new", &new_matrix3d_m6, gsi::arg ("m11"), gsi::arg ("m12"), gsi::arg ("m21"), gsi::arg ("m22"), gsi::arg ("dx"), gsi::arg ("dy"),
"@brief Create a new Matrix3d from the four coefficients of a Matrix2d plus a displacement\n"
) +
gsi::constructor ("new", &new_matrix3d_m9, gsi::arg ("m11"), gsi::arg ("m12"), gsi::arg ("m13"), gsi::arg ("m21"), gsi::arg ("m22"), gsi::arg ("m23"), gsi::arg ("m31"), gsi::arg ("m32"), gsi::arg ("m33"),
"@brief Create a new Matrix3d from the nine matrix coefficients\n"
) +
gsi::method_ext ("m", &coeff_m3, gsi::arg ("i"), gsi::arg ("j"),
"@brief Gets the m coefficient with the given index.\n"
"@return The coefficient [i,j]\n"
) +
gsi::method ("to_s", &db::Matrix3d::to_string,
"@brief Convert the matrix to a string.\n"
"@return The string representing this matrix\n"
) +
gsi::method ("inverted", &db::Matrix3d::inverted,
"@brief The inverse of this matrix.\n"
"@return The inverse of this matrix\n"
) +
gsi::method_ext ("trans", &trans_p3, gsi::arg ("p"),
"@brief Transforms a point with this matrix.\n"
"@param p The point to transform.\n"
"@return The product if self and the point p\n"
) +
gsi::method_ext ("*", &prod_m3, gsi::arg ("m"),
"@brief Product of two matrices.\n"
"@param m The other matrix.\n"
"@return The matrix product self*m\n"
) +
gsi::method_ext ("*", &trans_p3, gsi::arg ("p"),
"@brief Transform a point.\n"
"@param p The point to transform.\n"
"@return The transformed point\n"
) +
gsi::method_ext ("+", &sum_m3, gsi::arg ("m"),
"@brief Sum of two matrices.\n"
"@param m The other matrix.\n"
"@return The (element-wise) sum of self+m\n"
) +
gsi::method_ext ("cplx_trans", &to_cplx_trans3,
"@brief Converts this matrix to a complex transformation (if possible).\n"
"@return The complex transformation.\n"
"This method is successful only if the matrix does not contain shear or perspective distortion components and the magnification must be isotropic.\n"
) +
gsi::method ("mag_x", (double (db::Matrix3d::*) () const) &db::Matrix3d::mag_x,
"@brief Returns the x magnification of the magnification component of this matrix.\n"
"@return The magnification factor.\n"
) +
gsi::method ("mag_y", (double (db::Matrix3d::*) () const) &db::Matrix3d::mag_y,
"@brief Returns the y magnification of the magnification component of this matrix.\n"
"@return The magnification factor.\n"
) +
gsi::method ("angle", &db::Matrix3d::angle,
"@brief Returns the rotation angle of the rotation component of this matrix.\n"
"@return The angle in degree.\n"
"See the description of this class for details about the basic transformations."
) +
gsi::method ("shear_angle", &db::Matrix3d::shear_angle,
"@brief Returns the magnitude of the shear component of this matrix.\n"
"@return The shear angle in degree.\n"
"The shear basic transformation will tilt the x axis towards the y axis and vice versa. The shear angle "
"gives the tilt angle of the axes towards the other one. The possible range for this angle is -45 to 45 degree."
"See the description of this class for details about the basic transformations."
) +
gsi::method ("disp", (db::DVector (db::Matrix3d::*) () const) &db::Matrix3d::disp,
"@brief Returns the displacement vector of this transformation.\n"
"\n"
"Starting with version 0.25 this method returns a vector type instead of a point.\n"
"@return The displacement vector.\n"
) +
gsi::method ("tx", &db::Matrix3d::perspective_tilt_x, gsi::arg ("z"),
"@brief Returns the perspective tilt angle tx.\n"
"@param z The observer distance at which the tilt angle is computed.\n"
"@return The tilt angle tx.\n"
"The tx and ty parameters represent the perspective distortion. They denote a tilt of the xy plane around the y axis (tx) or the x axis (ty) in degree. "
"The same effect is achieved for different tilt angles at different observer distances. Hence, the observer distance must be specified at which the tilt angle is computed. "
"If the magnitude of the tilt angle is not important, z can be set to 1.\n"
) +
gsi::method ("ty", &db::Matrix3d::perspective_tilt_y, gsi::arg ("z"),
"@brief Returns the perspective tilt angle ty.\n"
"@param z The observer distance at which the tilt angle is computed.\n"
"@return The tilt angle ty.\n"
"The tx and ty parameters represent the perspective distortion. They denote a tilt of the xy plane around the y axis (tx) or the x axis (ty) in degree. "
"The same effect is achieved for different tilt angles at different observer distances. Hence, the observer distance must be specified at which the tilt angle is computed. "
"If the magnitude of the tilt angle is not important, z can be set to 1.\n"
) +
gsi::method ("is_mirror?", &db::Matrix3d::is_mirror,
"@brief Returns the mirror flag of this matrix.\n"
"@return True if this matrix has a mirror component.\n"
"See the description of this class for details about the basic transformations."
) +
matrix3d_methods<db::DCoord> () +
gsi::method_ext ("adjust", &adjust, gsi::arg ("landmarks_before"), gsi::arg ("landmarks_after"), gsi::arg ("flags"), gsi::arg ("fixed_point"),
"@brief Adjust a 3d matrix to match the given set of landmarks\n"
"\n"
@ -558,7 +731,7 @@ gsi::Class<db::Matrix3d> decl_Matrix3d ("db", "Matrix3d",
),
"@brief A 3d matrix object used mainly for representing rotation, shear, displacement and perspective transformations.\n"
"\n"
"This object represents a 3x3 matrix. This matrix is used to represent geometrical transformations "
"This object represents a 3x3 matrix. This matrix is used to implement generic geometrical transformations "
"in the 2d space mainly. It can be decomposed into basic transformations: mirroring, rotation, shear, displacement and perspective distortion. "
"In that case, the assumed execution order of the basic transformations is "
"mirroring at the x axis, rotation, magnification, shear, displacement and perspective distortion."
@ -566,4 +739,16 @@ gsi::Class<db::Matrix3d> decl_Matrix3d ("db", "Matrix3d",
"This class was introduced in version 0.22.\n"
);
gsi::Class<db::IMatrix3d> decl_IMatrix3d ("db", "IMatrix3d",
matrix3d_methods<db::Coord> (),
"@brief A 3d matrix object used mainly for representing rotation, shear, displacement and perspective transformations (integer coordinate version).\n"
"\n"
"This object represents a 3x3 matrix. This matrix is used to implement generic geometrical transformations "
"in the 2d space mainly. It can be decomposed into basic transformations: mirroring, rotation, shear, displacement and perspective distortion. "
"In that case, the assumed execution order of the basic transformations is "
"mirroring at the x axis, rotation, magnification, shear, displacement and perspective distortion."
"\n\n"
"The integer variant was introduced in version 0.27.\n"
);
}

View File

@ -1854,7 +1854,7 @@ Class<db::Polygon> decl_Polygon ("db", "Polygon",
"\n"
"This method was introduced in version 0.24.\n"
) +
method_ext ("transformed", &transformed_icplx_dp, gsi::arg ("t"),
method_ext ("#transformed", &transformed_icplx_dp, gsi::arg ("t"),
"@brief Transforms the polygon with a complex transformation\n"
"\n"
"Transforms the polygon with the given complex transformation.\n"

View File

@ -2209,8 +2209,32 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"@return The transformed region.\n"
) +
method ("transform", (db::Region &(db::Region::*)(const db::IMatrix2d &)) &db::Region::transform, gsi::arg ("t"),
"@brief Transform the region (modifies self)\n"
"\n"
"Transforms the region with the given 2d matrix transformation.\n"
"This version modifies the region and returns a reference to self.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed region.\n"
"\n"
"This variant was introduced in version 0.27.\n"
) +
method ("transform", (db::Region &(db::Region::*)(const db::IMatrix3d &)) &db::Region::transform, gsi::arg ("t"),
"@brief Transform the region (modifies self)\n"
"\n"
"Transforms the region with the given 3d matrix transformation.\n"
"This version modifies the region and returns a reference to self.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed region.\n"
"\n"
"This variant was introduced in version 0.27.\n"
) +
method ("transformed", (db::Region (db::Region::*)(const db::Trans &) const) &db::Region::transformed, gsi::arg ("t"),
"@brief Transform the region\n"
"@brief Transforms the region\n"
"\n"
"Transforms the region with the given transformation.\n"
"Does not modify the region but returns the transformed region.\n"
@ -2220,7 +2244,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"@return The transformed region.\n"
) +
method ("transformed|#transformed_icplx", (db::Region (db::Region::*)(const db::ICplxTrans &) const) &db::Region::transformed, gsi::arg ("t"),
"@brief Transform the region with a complex transformation\n"
"@brief Transforms the region with a complex transformation\n"
"\n"
"Transforms the region with the given complex transformation.\n"
"Does not modify the region but returns the transformed region.\n"
@ -2229,6 +2253,30 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"@return The transformed region.\n"
) +
method ("transformed", (db::Region (db::Region::*)(const db::IMatrix2d &) const) &db::Region::transformed, gsi::arg ("t"),
"@brief Transforms the region\n"
"\n"
"Transforms the region with the given 2d matrix transformation.\n"
"Does not modify the region but returns the transformed region.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed region.\n"
"\n"
"This variant was introduced in version 0.27.\n"
) +
method ("transformed", (db::Region (db::Region::*)(const db::IMatrix3d &) const) &db::Region::transformed, gsi::arg ("t"),
"@brief Transforms the region\n"
"\n"
"Transforms the region with the given 3d matrix transformation.\n"
"Does not modify the region but returns the transformed region.\n"
"\n"
"@param t The transformation to apply.\n"
"\n"
"@return The transformed region.\n"
"\n"
"This variant was introduced in version 0.27.\n"
) +
method_ext ("width_check", &width2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("negative", false),
"@brief Performs a width check with options\n"
"@param d The minimum width for which the polygons are checked\n"

View File

@ -0,0 +1,54 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2021 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 "dbFillTool.h"
#include "dbReader.h"
#include "dbRegion.h"
#include "dbTestSupport.h"
#include "dbRegion.h"
#include "tlUnitTest.h"
#include "tlStream.h"
TEST(1)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/fill_tool1.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type fill_cell = ly.cell_by_name ("FILL_CELL").second;
db::cell_index_type top_cell = ly.cell_by_name ("TOP").second;
unsigned int fill_layer = ly.get_layer (db::LayerProperties (1, 0));
db::Region fill_region (db::RecursiveShapeIterator (ly, ly.cell (top_cell), fill_layer));
db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, ly.cell (fill_cell).bbox (), db::Point (), false);
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/fill_tool_au1.gds");
}

View File

@ -630,3 +630,12 @@ TEST(10)
EXPECT_EQ ((m * p[2]).to_string (), "2,3");
}
TEST(11)
{
// double and integer versions basic functionality
EXPECT_EQ ((db::Matrix2d (1.0, 0.5, -0.5, 2.0) * db::DPoint (1, 2)).to_string (), "2,3.5");
EXPECT_EQ ((db::IMatrix2d (1.0, 0.5, -0.5, 2.0) * db::Point (10, 20)).to_string (), "20,35");
EXPECT_EQ ((db::Matrix3d (1.0, 0.5, 0.0, -0.5, 2.0, 1.0, 0.0, 0.0, 1.0) * db::DPoint (1, 2)).to_string (), "2,4.5");
EXPECT_EQ ((db::IMatrix3d (1.0, 0.5, 0.0, -0.5, 2.0, 1.0, 0.0, 0.0, 1.0) * db::DPoint (10, 20)).to_string (), "20,36");
}

View File

@ -8,6 +8,7 @@ include($$PWD/../../lib_ut.pri)
SOURCES = \
dbCompoundOperationTests.cc \
dbFillToolTests.cc \
dbRecursiveInstanceIteratorTests.cc \
dbRegionUtilsTests.cc \
dbUtilsTests.cc \

View File

@ -43,7 +43,8 @@
namespace db
{
class Matrix3d;
template <class C> class matrix_3d;
typedef matrix_3d<db::DCoord> Matrix3d;
/**
* @brief Generic base class of DXF reader exceptions

BIN
testdata/algo/fill_tool1.gds vendored Normal file

Binary file not shown.

View File

@ -67,6 +67,48 @@ class DBMatrix_TestClass < TestBase
end
def test_1i
m = RBA::IMatrix2d.new
assert_equal("(1,0) (0,1)", m.to_s)
m = RBA::IMatrix2d.new(2.0)
assert_equal("(2,0) (0,2)", m.to_s)
m = RBA::IMatrix2d.newc(2, 90, true)
assert_equal("(0,2) (2,0)", m.to_s)
m = RBA::IMatrix2d.new(RBA::ICplxTrans.new(2, 90, true, RBA::Point.new(0, 0)))
assert_equal("(0,2) (2,0)", m.to_s)
m = RBA::IMatrix2d.newc(0.0, 2, 2, 90, true)
assert_equal("(0,2) (2,0)", m.to_s)
m = RBA::IMatrix2d.newc(17.0, 2, 3, 90, true)
assert_equal("17.000000", "%.6f" % m.shear_angle)
assert_equal("90.0", m.angle.to_s)
assert_equal("2.000000", "%.6f" % m.mag_x)
assert_equal("3.000000", "%.6f" % m.mag_y)
assert_equal(true, m.is_mirror?)
m = RBA::IMatrix2d.new(1, 2, 3, 4)
assert_equal("(1,2) (3,4)", m.to_s)
assert_equal("1.0", m.m11.to_s)
assert_equal("2.0", m.m12.to_s)
assert_equal("3.0", m.m21.to_s)
assert_equal("4.0", m.m22.to_s)
assert_equal("4.0", m.m(1,1).to_s)
assert_equal("2.0", m.m(0,1).to_s)
m = RBA::IMatrix2d.newc(2, 90, true)
assert_equal(true, m.is_mirror?)
t = m.cplx_trans
assert_equal("m45 *2 0,0", t.to_s)
m = RBA::IMatrix2d.newc(2, 90, false)
assert_equal("90.0", m.angle.to_s)
assert_equal(false, m.is_mirror?)
t = m.inverted.cplx_trans
assert_equal("r270 *0.5 0,0", t.to_s)
p = m.trans(RBA::Point.new(1, 2))
assert_equal("-4,2", p.to_s)
assert_equal("(1,0) (0,1)", (m.inverted*m).to_s)
assert_equal("(0,-1.5) (1.5,0)", (m+m.inverted).to_s)
end
def test_2
m = RBA::Matrix3d.new
@ -127,6 +169,66 @@ class DBMatrix_TestClass < TestBase
end
def test_2i
m = RBA::IMatrix3d.new
assert_equal("(1,0,0) (0,1,0) (0,0,1)", m.to_s)
m = RBA::IMatrix3d.new(2.0)
assert_equal("(2,0,0) (0,2,0) (0,0,1)", m.to_s)
m = RBA::IMatrix3d.newc(2, 90, true)
assert_equal("(0,2,0) (2,0,0) (0,0,1)", m.to_s)
m = RBA::IMatrix3d.new(RBA::ICplxTrans.new(2, 90, true, RBA::Point.new(1, 2)))
assert_equal("(0,2,1) (2,0,2) (0,0,1)", m.to_s)
m = RBA::IMatrix3d.newc(0.0, 2, 3, 90, true)
assert_equal("(0,3,0) (2,0,0) (0,0,1)", m.to_s)
m = RBA::IMatrix3d.newc(17.0, 2, 3, 90, true)
assert_equal("17.000000", "%.6f" % m.shear_angle)
assert_equal("90.0", m.angle.to_s)
assert_equal("2.000000", "%.6f" % m.mag_x)
assert_equal("3.000000", "%.6f" % m.mag_y)
assert_equal(true, m.is_mirror?)
m = RBA::IMatrix3d.newc(RBA::Point.new(1, 2), 17.0, 2, 3, 90, true)
assert_equal("17.000000", "%.6f" % m.shear_angle)
assert_equal("90.0", m.angle.to_s)
assert_equal("2.000000", "%.6f" % m.mag_x)
assert_equal("3.000000", "%.6f" % m.mag_y)
assert_equal("1,2", m.disp.to_s)
assert_equal(true, m.is_mirror?)
m = RBA::IMatrix3d.new(1, 2, 3, 4)
assert_equal("(1,2,0) (3,4,0) (0,0,1)", m.to_s)
assert_equal("4.0", m.m(1,1).to_s)
assert_equal("2.0", m.m(0,1).to_s)
assert_equal("0.0", m.m(0,2).to_s)
assert_equal("1.0", m.m(2,2).to_s)
m = RBA::IMatrix3d.newc(2, 90, true)
assert_equal(true, m.is_mirror?)
t = m.cplx_trans
assert_equal("m45 *2 0,0", t.to_s)
m = RBA::IMatrix3d.newc(2, 90, false)
assert_equal("90.0", m.angle.to_s)
assert_equal(false, m.is_mirror?)
t = m.inverted.cplx_trans
assert_equal("r270 *0.5 0,0", t.to_s)
p = m.trans(RBA::Point.new(1, 2))
assert_equal("-4,2", p.to_s)
assert_equal("(1,0,0) (0,1,0) (0,0,1)", (m.inverted*m).to_s)
assert_equal("(0,-1.5,0) (1.5,0,0) (0,0,2)", (m+m.inverted).to_s)
m = RBA::IMatrix3d.new(0, 1, -1, 0, 1, 2)
t = m.cplx_trans
assert_equal("r270 *1 1,2", t.to_s)
m = RBA::IMatrix3d.new(0, 1, 1, -1, 0, 2, 0, 0, 1)
t = m.cplx_trans
assert_equal("r270 *1 1,2", t.to_s)
assert_equal("1", m.disp.x.to_s)
assert_equal("2", m.disp.y.to_s)
m = RBA::IMatrix3d.newc(0.1, -0.2, 1.0, RBA::Point.new(1, 2), 17.0, 2, 2, 270, true)
assert_equal("0.100000", "%.6f" % m.tx(1.0))
assert_equal("-0.200000", "%.6f" % m.ty(1.0))
assert_equal("17.000000", "%.6f" % m.shear_angle)
assert_equal("1,2", m.disp.to_s)
end
def test_3
p = [ RBA::DPoint.new(1, 1), RBA::DPoint.new(2, 1), RBA::DPoint.new(2, 2) ]
@ -142,6 +244,46 @@ class DBMatrix_TestClass < TestBase
end
def test_4
m = RBA::IMatrix2d::new(1.0, 0.5, -0.5, 2.0)
assert_equal((m * RBA::Point::new(10, 20)).to_s, "20,35")
assert_equal((m * RBA::Vector::new(10, 20)).to_s, "20,35")
assert_equal((m * RBA::Box::new(-5, -10, 10, 20)).to_s, "(-10,-25;20,43)")
assert_equal((m * RBA::Polygon::new(RBA::Box::new(-5, -10, 10, 20))).to_s, "(5,-25;-10,-18;5,43;20,35)")
assert_equal((m * RBA::SimplePolygon::new(RBA::Box::new(-5, -10, 10, 20))).to_s, "(5,-25;-10,-18;5,43;20,35)")
assert_equal((m * RBA::Edge::new(RBA::Point::new(-5, -10), RBA::Point::new(10, 20))).to_s, "(-10,-18;20,35)")
assert_equal(RBA::Region::new(RBA::Box::new(-5, -10, 10, 20)).transformed(m).to_s, "(5,-25;-10,-18;5,43;20,35)")
assert_equal(RBA::Edges::new(RBA::Edge::new(RBA::Point::new(-5, -10), RBA::Point::new(10, 20))).transformed(m).to_s, "(-10,-18;20,35)")
m = RBA::Matrix2d::new(1.0, 0.5, -0.5, 2.0)
assert_equal((m * RBA::DPoint::new(10, 20)).to_s, "20,35")
assert_equal((m * RBA::DVector::new(10, 20)).to_s, "20,35")
assert_equal((m * RBA::DBox::new(-5, -10, 10, 20)).to_s, "(-10,-25;20,42.5)")
assert_equal((m * RBA::DPolygon::new(RBA::DBox::new(-5, -10, 10, 20))).to_s, "(5,-25;-10,-17.5;5,42.5;20,35)")
assert_equal((m * RBA::DSimplePolygon::new(RBA::DBox::new(-5, -10, 10, 20))).to_s, "(5,-25;-10,-17.5;5,42.5;20,35)")
assert_equal((m * RBA::DEdge::new(RBA::DPoint::new(-5, -10), RBA::DPoint::new(10, 20))).to_s, "(-10,-17.5;20,35)")
m = RBA::IMatrix3d::new(1.0, 0.5, 1.0, -0.5, 2.0, 0.0, 0.0, 0.0, 1.0)
assert_equal((m * RBA::Point::new(10, 20)).to_s, "21,35")
assert_equal((m * RBA::Vector::new(10, 20)).to_s, "20,35")
assert_equal((m * RBA::Box::new(-5, -10, 10, 20)).to_s, "(-9,-25;21,43)")
assert_equal((m * RBA::Polygon::new(RBA::Box::new(-5, -10, 10, 20))).to_s, "(6,-25;-9,-18;6,43;21,35)")
assert_equal((m * RBA::SimplePolygon::new(RBA::Box::new(-5, -10, 10, 20))).to_s, "(6,-25;-9,-18;6,43;21,35)")
assert_equal((m * RBA::Edge::new(RBA::Point::new(-5, -10), RBA::Point::new(10, 20))).to_s, "(-9,-18;21,35)")
assert_equal(RBA::Region::new(RBA::Box::new(-5, -10, 10, 20)).transformed(m).to_s, "(6,-25;-9,-18;6,43;21,35)")
assert_equal(RBA::Edges::new(RBA::Edge::new(RBA::Point::new(-5, -10), RBA::Point::new(10, 20))).transformed(m).to_s, "(-9,-18;21,35)")
m = RBA::Matrix3d::new(1.0, 0.5, 1.0, -0.5, 2.0, 0.0, 0.0, 0.0, 1.0)
assert_equal((m * RBA::DPoint::new(10, 20)).to_s, "21,35")
assert_equal((m * RBA::DVector::new(10, 20)).to_s, "20,35")
assert_equal((m * RBA::DBox::new(-5, -10, 10, 20)).to_s, "(-9,-25;21,42.5)")
assert_equal((m * RBA::DPolygon::new(RBA::DBox::new(-5, -10, 10, 20))).to_s, "(6,-25;-9,-17.5;6,42.5;21,35)")
assert_equal((m * RBA::DSimplePolygon::new(RBA::DBox::new(-5, -10, 10, 20))).to_s, "(6,-25;-9,-17.5;6,42.5;21,35)")
assert_equal((m * RBA::DEdge::new(RBA::DPoint::new(-5, -10), RBA::DPoint::new(10, 20))).to_s, "(-9,-17.5;21,35)")
end
end
load("test_epilogue.rb")