diff --git a/src/db/db/dbEdgePairs.cc b/src/db/db/dbEdgePairs.cc index 2125714b5..a3d5d5ea8 100644 --- a/src/db/db/dbEdgePairs.cc +++ b/src/db/db/dbEdgePairs.cc @@ -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 diff --git a/src/db/db/dbEdges.cc b/src/db/db/dbEdges.cc index 07c0eece8..6e7ffc185 100644 --- a/src/db/db/dbEdges.cc +++ b/src/db/db/dbEdges.cc @@ -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 void Edges::insert (const Sh &shape) diff --git a/src/db/db/dbFillTool.cc b/src/db/db/dbFillTool.cc index 2fe2a7489..5c38bbf40 100644 --- a/src/db/db/dbFillTool.cc +++ b/src/db/db/dbFillTool.cc @@ -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 *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 *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 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 fpa; std::vector 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 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 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); } diff --git a/src/db/db/dbFillTool.h b/src/db/db/dbFillTool.h index 64407e4df..14e453442 100644 --- a/src/db/db/dbFillTool.h +++ b/src/db/db/dbFillTool.h @@ -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 *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 *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); + } diff --git a/src/db/db/dbMatrix.cc b/src/db/db/dbMatrix.cc index edbb39a2d..5c78bb240 100644 --- a/src/db/db/dbMatrix.cc +++ b/src/db/db/dbMatrix.cc @@ -37,14 +37,16 @@ inline double mnorm (double x) return fabs (x) < 1e-14 ? 0.0 : x; } +template std::string -Matrix2d::to_string () const +matrix_2d::to_string () const { return tl::sprintf ("(%.12g,%.12g) (%.12g,%.12g)", mnorm (m_m11), mnorm (m_m12), mnorm (m_m21), mnorm (m_m22)); } -std::pair -Matrix2d::mag () const +template +std::pair +matrix_2d::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 bool -Matrix2d::has_rotation () const +matrix_2d::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 +double +matrix_2d::angle () const { std::pair 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 +matrix_2d +matrix_2d::rotation (double a) { a *= M_PI / 180.0; return Matrix2d (cos (a), -sin (a), sin (a), cos (a)); } -bool -Matrix2d::has_shear () const +template +bool +matrix_2d::has_shear () const { std::pair 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 +double +matrix_2d::shear_angle () const { std::pair 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 +matrix_2d +matrix_2d::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 +bool +matrix_2d::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 +bool +matrix_2d::is_unity () const +{ + static matrix_2d u; + return equal (u); +} + +template +bool +matrix_2d::equal (const matrix_2d &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 +bool +matrix_2d::less (const matrix_2d &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; +template class matrix_2d; + // -------------------------------------------------------------------------------------------- -double -Matrix3d::det () const +template +double +matrix_3d::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 +db::vector +matrix_3d::trans (const db::point &p, const db::vector &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(v.x() * t[0][0] + v.y() * t[0][1], v.x() * t[1][0] + v.y() * t[1][1]); } +template bool -Matrix3d::can_transform (const db::DPoint &p) const +matrix_3d::can_transform (const db::point &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 +db::point +matrix_3d::trans (const db::point &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 (r[0] / z, r[1] / z); } -Matrix3d -Matrix3d::inverted () const +template +matrix_3d +matrix_3d::inverted () const { double m[3][3]; - Matrix3d r (1.0); + matrix_3d 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 +db::vector +matrix_3d::disp () const { - return db::DVector (m_m[0][2] / m_m[2][2], m_m[1][2] / m_m[2][2]); + return db::vector (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 +double +matrix_3d::perspective_tilt_x (double z) const { - db::DVector d = disp (); - db::Matrix3d m = db::Matrix3d::disp (-d) * *this; + db::vector d = disp (); + db::matrix_3d m = db::matrix_3d::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 +double +matrix_3d::perspective_tilt_y (double z) const { - db::DVector d = disp (); - db::Matrix3d m = db::Matrix3d::disp (-d) * *this; + db::vector d = disp (); + db::matrix_3d m = db::matrix_3d::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 +bool +matrix_3d::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 +matrix_3d +matrix_3d::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 (1.0, 0.0, 0.0, 1.0, 0.0, 0.0, tan (tx) / z, tan (ty) / z); } -Matrix2d -Matrix3d::m2d () const +template +matrix_2d +matrix_3d::m2d () const { - db::DVector d = disp (); - db::Matrix3d m = db::Matrix3d::disp (-d) * *this; + db::vector d = disp (); + db::matrix_3d m = db::matrix_3d::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::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 (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 +std::string +matrix_3d::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 +bool +matrix_3d::is_ortho () const { return ! has_perspective () && m2d ().is_ortho (); } -bool -Matrix3d::equal (const Matrix3d &d) const +template +bool +matrix_3d::is_unity () const +{ + static matrix_3d u; + return equal (u); +} + +template +bool +matrix_3d::equal (const matrix_3d &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 +bool +matrix_3d::less (const matrix_3d &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; +template class matrix_3d; + // -------------------------------------------------------------------------------------------- /** @@ -775,7 +823,7 @@ adjust_matrix (Matrix3d &matrix, const std::vector &landmarks_befor namespace tl { - template<> bool test_extractor_impl (tl::Extractor &ex, db::Matrix2d &m) + template bool test_extractor_impl_matrix2d (tl::Extractor &ex, db::matrix_2d &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 (m11, m12, m21, m22); return true; } - template<> void extractor_impl (tl::Extractor &ex, db::Matrix2d &m) + template void extractor_impl_matrix2d (tl::Extractor &ex, db::matrix_2d &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 bool test_extractor_impl_matrix3d (tl::Extractor &ex, db::matrix_3d &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 (m11, m12, m13, m21, m22, m23, m31, m32, m33); return true; } - template<> void extractor_impl (tl::Extractor &ex, db::Matrix3d &m) + template void extractor_impl_matrix3d (tl::Extractor &ex, db::matrix_3d &m) { if (! test_extractor_impl (ex, m)) { ex.error (tl::to_string (tr ("Expected a 3d matrix specification"))); } } + + template<> void extractor_impl > (tl::Extractor &ex, db::matrix_2d &m) + { + extractor_impl_matrix2d (ex, m); + } + + template<> void extractor_impl > (tl::Extractor &ex, db::matrix_2d &m) + { + extractor_impl_matrix2d (ex, m); + } + + template<> void extractor_impl > (tl::Extractor &ex, db::matrix_3d &m) + { + extractor_impl_matrix3d (ex, m); + } + + template<> void extractor_impl > (tl::Extractor &ex, db::matrix_3d &m) + { + extractor_impl_matrix3d (ex, m); + } + + template<> bool test_extractor_impl > (tl::Extractor &ex, db::matrix_2d &m) + { + return test_extractor_impl_matrix2d (ex, m); + } + + template<> bool test_extractor_impl > (tl::Extractor &ex, db::matrix_2d &m) + { + return test_extractor_impl_matrix2d (ex, m); + } + + template<> bool test_extractor_impl > (tl::Extractor &ex, db::matrix_3d &m) + { + return test_extractor_impl_matrix3d (ex, m); + } + + template<> bool test_extractor_impl > (tl::Extractor &ex, db::matrix_3d &m) + { + return test_extractor_impl_matrix3d (ex, m); + } } diff --git a/src/db/db/dbMatrix.h b/src/db/db/dbMatrix.h index 9f28ce9d9..8e5ab74c2 100644 --- a/src/db/db/dbMatrix.h +++ b/src/db/db/dbMatrix.h @@ -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 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 displacement_type; + typedef matrix_2d 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 + matrix_2d (const matrix_2d &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 - 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 + matrix_2d operator+ (const matrix_2d &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 + matrix_2d &operator+= (const matrix_2d &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 + matrix_2d operator* (const matrix_2d &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 operator* (const db::vector &v) const { - return db::DVector (m_m11 * v.x () + m_m12 * v.y (), m_m21 * v.x () + m_m22 * v.y ()); + return db::vector (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 trans (const db::vector &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 operator() (const db::vector &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 operator* (const db::point &v) const { - return db::DPoint (m_m11 * v.x () + m_m12 * v.y (), m_m21 * v.x () + m_m22 * v.y ()); + return db::point (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 trans (const db::point &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 operator() (const db::point &p) const { return operator* (p); } @@ -221,9 +237,9 @@ public: /** * @brief Return the transposed matrix */ - Matrix2d transposed () const + matrix_2d transposed () const { - return Matrix2d (m_m11, m_m21, m_m12, m_m22); + return matrix_2d (m_m11, m_m21, m_m12, m_m22); } /** @@ -245,9 +261,9 @@ public: /** * @brief Return the inverted matrix */ - Matrix2d inverted () const + matrix_2d inverted () const { - Matrix2d m (*this); + matrix_2d 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 mag (double mx, double my) { - return Matrix2d (mx, 0.0, 0.0, my); + return matrix_2d (mx, 0.0, 0.0, my); } /** @@ -335,9 +351,9 @@ public: * * @param m The magnification */ - static Matrix2d mag (double m) + static matrix_2d mag (double m) { - return Matrix2d (m, 0.0, 0.0, m); + return matrix_2d (m, 0.0, 0.0, m); } /** @@ -356,9 +372,9 @@ public: /** * @brief Create the mirror matrix */ - static Matrix2d mirror (bool m) + static matrix_2d mirror (bool m) { - return Matrix2d (1.0, 0.0, 0.0, m ? -1.0 : 1.0); + return matrix_2d (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 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 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 &d) const; /** * @brief A fuzzy compare operator (less) */ - bool less (const Matrix2d &d) const; + bool less (const matrix_2d &d) const; private: double m_m11, m_m12, m_m21, m_m22; }; +typedef matrix_2d Matrix2d; +typedef matrix_2d 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 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 displacement_type; + typedef matrix_3d 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 + matrix_3d (const matrix_3d &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 + explicit matrix_3d (const matrix_2d &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 - 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 + matrix_3d operator+ (const matrix_3d &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 + matrix_3d &operator+= (const matrix_3d &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 + matrix_3d operator* (const matrix_3d &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 + matrix_3d &operator*= (const matrix_3d &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 &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 trans (const db::point &p, const db::vector &v) const; /** * @brief Transforms a point */ - db::DPoint trans (const db::DPoint &p) const; + db::point trans (const db::point &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 trans (const db::vector &p) const { - return this->trans (db::DPoint () + p) - this->trans (db::DPoint ()); + return this->trans (db::point () + p) - this->trans (db::point ()); } /** * @brief "trans" alias for compatibility with the other transformations */ - template - db::DPoint trans (const db::point &p) const + template + db::point trans (const db::point &p) const { - return trans (db::DPoint (p)); + return trans (db::point (p)); } /** * @brief "trans" alias for compatibility with the other transformations */ - template - db::DVector trans (const db::vector &p) const + template + db::vector trans (const db::vector &p) const { - return trans (db::DVector (p)); + return trans (db::vector (p)); } /** * @brief "operator()" alias for compatibility with the other transformations */ - template - db::DPoint operator() (const db::point &p) const + template + db::point operator() (const db::point &p) const { return trans (p); } @@ -648,8 +696,8 @@ public: /** * @brief "operator()" alias for compatibility with the other transformations */ - template - db::DVector operator() (const db::vector &p) const + template + db::vector operator() (const db::vector &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 disp () const; /** * @brief Create the mirror matrix */ - static Matrix3d disp (const db::DVector &d) + static matrix_3d disp (const db::vector &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 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 Matrix3d; +typedef matrix_3d IMatrix3d; + /** * @brief Some adjustment flags * @@ -982,10 +1045,15 @@ void DB_PUBLIC adjust_matrix (Matrix3d &matrix, const std::vector & 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 > (tl::Extractor &ex, db::matrix_2d &t); + template<> DB_PUBLIC void extractor_impl > (tl::Extractor &ex, db::matrix_2d &t); + template<> DB_PUBLIC void extractor_impl > (tl::Extractor &ex, db::matrix_3d &t); + template<> DB_PUBLIC void extractor_impl > (tl::Extractor &ex, db::matrix_3d &t); + + template<> DB_PUBLIC bool test_extractor_impl > (tl::Extractor &ex, db::matrix_2d &t); + template<> DB_PUBLIC bool test_extractor_impl > (tl::Extractor &ex, db::matrix_2d &t); + template<> DB_PUBLIC bool test_extractor_impl > (tl::Extractor &ex, db::matrix_3d &t); + template<> DB_PUBLIC bool test_extractor_impl > (tl::Extractor &ex, db::matrix_3d &t); } // namespace tl #endif diff --git a/src/db/db/dbRegion.cc b/src/db/db/dbRegion.cc index 72f8742c7..58febc8c0 100644 --- a/src/db/db/dbRegion.cc +++ b/src/db/db/dbRegion.cc @@ -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 void Region::insert (const Sh &shape) diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index de891d776..168a20229 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -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 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 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" diff --git a/src/db/db/gsiDeclDbEdgePairs.cc b/src/db/db/gsiDeclDbEdgePairs.cc index 8db7d345e..9dc661e15 100644 --- a/src/db/db/gsiDeclDbEdgePairs.cc +++ b/src/db/db/gsiDeclDbEdgePairs.cc @@ -398,6 +398,30 @@ Class 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 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." diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 9cf71b45a..653481789 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -1040,6 +1040,30 @@ Class 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 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" diff --git a/src/db/db/gsiDeclDbMatrix.cc b/src/db/db/gsiDeclDbMatrix.cc index 07f9edefa..5585cbcee 100644 --- a/src/db/db/gsiDeclDbMatrix.cc +++ b/src/db/db/gsiDeclDbMatrix.cc @@ -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 +static db::matrix_2d *new_matrix2d () { - return new db::Matrix2d (1.0); + return new db::matrix_2d (1.0); } -static db::Matrix2d *new_matrix2d_m (double mag) +template +static db::matrix_2d *new_matrix2d_m (double mag) { - return new db::Matrix2d (mag); + return new db::matrix_2d (mag); } -static db::Matrix2d *new_matrix2d_m2 (double mx, double my) +template +static db::matrix_2d *new_matrix2d_m2 (double mx, double my) { - return new db::Matrix2d (mx, my); + return new db::matrix_2d (mx, my); } -static db::Matrix2d *new_matrix2d_t (const db::DCplxTrans &t) +template +static db::matrix_2d *new_matrix2d_t (const db::DCplxTrans &t) { - return new db::Matrix2d (t); + return new db::matrix_2d (t); } -static db::Matrix2d *new_matrix2d_mrm (double mag, double rot, bool m) +template +static db::matrix_2d *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 (db::matrix_2d::rotation (rot) * db::matrix_2d::mag (mag) * db::matrix_2d::mirror (m)); } -static db::Matrix2d *new_matrix2d_smrm (double shear, double mx, double my, double rot, bool m) +template +static db::matrix_2d *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 (db::matrix_2d::rotation (rot) * db::matrix_2d::shear (shear) * db::matrix_2d::mag (mx, my) * db::matrix_2d::mirror (m)); } -static db::Matrix2d *new_matrix2d_m4 (double m11, double m12, double m21, double m22) +template +static db::matrix_2d *new_matrix2d_m4 (double m11, double m12, double m21, double m22) { - return new db::Matrix2d (m11, m12, m21, m22); + return new db::matrix_2d (m11, m12, m21, m22); } -static db::DCplxTrans to_cplx_trans (const db::Matrix2d *m) +template +static db::complex_trans to_cplx_trans (const db::matrix_2d *m) { - return db::DCplxTrans (db::Matrix3d (*m)); + return db::complex_trans (db::matrix_3d (*m)); } -static db::Matrix2d sum_m (const db::Matrix2d *m, const db::Matrix2d &d) +template +static db::matrix_2d sum_m (const db::matrix_2d *m, const db::matrix_2d &d) { return *m + d; } -static db::Matrix2d prod_m (const db::Matrix2d *m, const db::Matrix2d &d) +template +static db::matrix_2d prod_m (const db::matrix_2d *m, const db::matrix_2d &d) { return *m * d; } -static db::DPoint trans_p (const db::Matrix2d *m, const db::DPoint &p) +template +static db::point trans_p (const db::matrix_2d *m, const db::point &p) { return *m * p; } -static double coeff_m (const db::Matrix2d *m, int i, int j) +template +static db::vector trans_v (const db::matrix_2d *m, const db::vector &p) +{ + return *m * p; +} + +template +static db::polygon trans_polygon (const db::matrix_2d *m, const db::polygon &p) +{ + return p.transformed (*m); +} + +template +static db::simple_polygon trans_simple_polygon (const db::matrix_2d *m, const db::simple_polygon &p) +{ + return p.transformed (*m); +} + +template +static db::box trans_box (const db::matrix_2d *m, const db::box &p) +{ + return p.transformed (*m); +} + +template +static db::edge trans_edge (const db::matrix_2d *m, const db::edge &e) +{ + return e.transformed (*m); +} + +template +static double coeff_m (const db::matrix_2d *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 +gsi::Methods +matrix2d_methods () +{ + return + 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::matrix_2d::m11, + "@brief Gets the m11 coefficient.\n" + "@return The value of the m11 coefficient\n" + ) + + gsi::method ("m12", &db::matrix_2d::m12, + "@brief Gets the m12 coefficient.\n" + "@return The value of the m12 coefficient\n" + ) + + gsi::method ("m21", &db::matrix_2d::m21, + "@brief Gets the m21 coefficient.\n" + "@return The value of the m21 coefficient\n" + ) + + gsi::method ("m22", &db::matrix_2d::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::matrix_2d::to_string, + "@brief Convert the matrix to a string.\n" + "@return The string representing this matrix\n" + ) + + gsi::method ("inverted", &db::matrix_2d::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 transformed point\n" + ) + + gsi::method_ext ("*", &trans_v, 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, 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, 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, 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, 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, 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::matrix_2d::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::*) () const) &db::matrix_2d::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::*) () const) &db::matrix_2d::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::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::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 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 (), "@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 decl_IMatrix2d ("db", "IMatrix2d", + matrix2d_methods (), + "@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 +static db::matrix_3d *new_matrix3d () { - return new db::Matrix3d (1.0); + return new db::matrix_3d (1.0); } -static db::Matrix3d *new_matrix3d_t (const db::DCplxTrans &t) +template +static db::matrix_3d *new_matrix3d_t (const db::complex_trans &t) { - return new db::Matrix3d (t); + return new db::matrix_3d (t); } -static db::Matrix3d *new_matrix3d_m (double mag) +template +static db::matrix_3d *new_matrix3d_m (double mag) { - return new db::Matrix3d (mag); + return new db::matrix_3d (mag); } -static db::Matrix3d *new_matrix3d_mrm (double mag, double rot, bool m) +template +static db::matrix_3d *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 (db::matrix_3d::rotation (rot) * db::matrix_3d::mag (mag) * db::matrix_3d::mirror (m)); } -static db::Matrix3d *new_matrix3d_smrm (double shear, double mx, double my, double rot, bool m) +template +static db::matrix_3d *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 (db::matrix_3d::rotation (rot) * db::matrix_3d::shear (shear) * db::matrix_3d::mag (mx, my) * db::matrix_3d::mirror (m)); } -static db::Matrix3d *new_matrix3d_dsmrm (const db::DVector &d, double shear, double mx, double my, double rot, bool m) +template +static db::matrix_3d *new_matrix3d_dsmrm (const db::vector &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 (db::matrix_3d::disp (d) * db::matrix_3d::rotation (rot) * db::matrix_3d::shear (shear) * db::matrix_3d::mag (mx, my) * db::matrix_3d::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 +static db::matrix_3d *new_matrix3d_pdsmrm (double tx, double ty, double z, const db::vector &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 (db::matrix_3d::disp (d) * db::matrix_3d::perspective (tx, ty, z) * db::matrix_3d::rotation (rot) * db::matrix_3d::shear (shear) * db::matrix_3d::mag (mx, my) * db::matrix_3d::mirror (m)); } -static db::Matrix3d *new_matrix3d_m4 (double m11, double m12, double m21, double m22) +template +static db::matrix_3d *new_matrix3d_m4 (double m11, double m12, double m21, double m22) { - return new db::Matrix3d (m11, m12, m21, m22); + return new db::matrix_3d (m11, m12, m21, m22); } -static db::Matrix3d *new_matrix3d_m6 (double m11, double m12, double m21, double m22, double dx, double dy) +template +static db::matrix_3d *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 (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 +static db::matrix_3d *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 (m11, m12, m13, m21, m22, m23, m31, m32, m33); } -static db::DCplxTrans to_cplx_trans3 (const db::Matrix3d *m) +template +static db::DCplxTrans to_cplx_trans3 (const db::matrix_3d *m) { return db::DCplxTrans (*m); } -static db::Matrix3d sum_m3 (const db::Matrix3d *m, const db::Matrix3d &d) +template +static db::matrix_3d sum_m3 (const db::matrix_3d *m, const db::matrix_3d &d) { return *m + d; } -static db::Matrix3d prod_m3 (const db::Matrix3d *m, const db::Matrix3d &d) +template +static db::matrix_3d prod_m3 (const db::matrix_3d *m, const db::matrix_3d &d) { return *m * d; } -static db::DPoint trans_p3 (const db::Matrix3d *m, const db::DPoint &p) +template +static db::point trans_p3 (const db::matrix_3d *m, const db::point &p) { return *m * p; } -static double coeff_m3 (const db::Matrix3d *m, int i, int j) +template +static db::vector trans_v3 (const db::matrix_3d *m, const db::vector &p) +{ + return *m * p; +} + +template +static db::polygon trans_polygon3 (const db::matrix_3d *m, const db::polygon &p) +{ + return p.transformed (*m); +} + +template +static db::simple_polygon trans_simple_polygon3 (const db::matrix_3d *m, const db::simple_polygon &p) +{ + return p.transformed (*m); +} + +template +static db::box trans_box3 (const db::matrix_3d *m, const db::box &p) +{ + return p.transformed (*m); +} + +template +static db::edge trans_edge3 (const db::matrix_3d *m, const db::edge &e) +{ + return e.transformed (*m); +} + +template +static double coeff_m3 (const db::matrix_3d *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 +gsi::Methods +matrix3d_methods () +{ + return + 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::matrix_3d::to_string, + "@brief Convert the matrix to a string.\n" + "@return The string representing this matrix\n" + ) + + gsi::method ("inverted", &db::matrix_3d::inverted, + "@brief The inverse of this matrix.\n" + "@return The inverse of this matrix\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 ("+", &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 ("trans|*", &trans_p3, 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, 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, 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, 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, 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, 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, + "@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::*) () const) &db::matrix_3d::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::*) () const) &db::matrix_3d::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::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::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 (db::matrix_3d::*) () const) &db::matrix_3d::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::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::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::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 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 () + 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 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 decl_Matrix3d ("db", "Matrix3d", "This class was introduced in version 0.22.\n" ); +gsi::Class decl_IMatrix3d ("db", "IMatrix3d", + matrix3d_methods (), + "@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" +); + } diff --git a/src/db/db/gsiDeclDbPolygon.cc b/src/db/db/gsiDeclDbPolygon.cc index 76f3315c9..f66aedfd7 100644 --- a/src/db/db/gsiDeclDbPolygon.cc +++ b/src/db/db/gsiDeclDbPolygon.cc @@ -1854,7 +1854,7 @@ Class 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" diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 91ee1dfec..9ebd1d2c0 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -2209,8 +2209,32 @@ Class 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 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 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" diff --git a/src/db/unit_tests/dbFillToolTests.cc b/src/db/unit_tests/dbFillToolTests.cc new file mode 100644 index 000000000..fbc6940a3 --- /dev/null +++ b/src/db/unit_tests/dbFillToolTests.cc @@ -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"); +} + diff --git a/src/db/unit_tests/dbMatrixTests.cc b/src/db/unit_tests/dbMatrixTests.cc index cfaf0ac70..605b41f04 100644 --- a/src/db/unit_tests/dbMatrixTests.cc +++ b/src/db/unit_tests/dbMatrixTests.cc @@ -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"); +} + diff --git a/src/db/unit_tests/unit_tests.pro b/src/db/unit_tests/unit_tests.pro index 3af34f474..1fc2fbe1d 100644 --- a/src/db/unit_tests/unit_tests.pro +++ b/src/db/unit_tests/unit_tests.pro @@ -8,6 +8,7 @@ include($$PWD/../../lib_ut.pri) SOURCES = \ dbCompoundOperationTests.cc \ + dbFillToolTests.cc \ dbRecursiveInstanceIteratorTests.cc \ dbRegionUtilsTests.cc \ dbUtilsTests.cc \ diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.h b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.h index 7aca5f607..5268e18e2 100644 --- a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.h +++ b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.h @@ -43,7 +43,8 @@ namespace db { -class Matrix3d; +template class matrix_3d; +typedef matrix_3d Matrix3d; /** * @brief Generic base class of DXF reader exceptions diff --git a/testdata/algo/fill_tool1.gds b/testdata/algo/fill_tool1.gds new file mode 100644 index 000000000..540163aa2 Binary files /dev/null and b/testdata/algo/fill_tool1.gds differ diff --git a/testdata/ruby/dbMatrix.rb b/testdata/ruby/dbMatrix.rb index 3cfe41d64..3defd7e78 100644 --- a/testdata/ruby/dbMatrix.rb +++ b/testdata/ruby/dbMatrix.rb @@ -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")