![]() |
Pangolin
Header-only C++20 plane computational geometry library
|
A bit per cell of a rectangular window of the integer grid. More...
#include <bitmatrix.hpp>
Classes | |
| class | Iterator |
| Forward iterator over the set cells, in row-major order. More... | |
Public Types | |
| using | PointType = TPointType |
| Point type naming a cell by its lower-left corner. | |
| using | NumberType = typename PointType::NumberType |
| Coordinate type of a cell. | |
| using | RectangleType = Rectangle<PointType> |
| Rectangle over PointType, the type of a window. | |
| using | RegionType = PolygonWithHoles<PointType> |
| Region type asPolygonWithHoles produces. | |
| using | PolygonSetType = PolygonSet<PointType> |
| Region-set type asPolygonSet produces. | |
| using | ConvexType = Convex<PointType> |
| Convex type convexHull produces. | |
| using | value_type = PointType |
| Cell type the iterators yield. | |
| using | iterator = Iterator |
| Iteration is read-only, so both iterator types are Iterator. | |
| using | const_iterator = Iterator |
| Iteration is read-only, so both iterator types are Iterator. | |
Public Member Functions | |
| BitMatrix ()=default | |
| Creates a matrix whose window is empty, so no cell can be set. | |
| BitMatrix (PointType origin, int width, int height) | |
| Creates an empty matrix covering a window of the grid. | |
| BitMatrix (const RectangleType &box) | |
| Creates an empty matrix over the cells a rectangle covers. | |
| template<class TLabel> | |
| BitMatrix (const PolygonWithHoles< PointType, TLabel > ®ion) | |
| Rasterizes a rectilinear region, one bit per covered cell. | |
| template<class OtherPointType, class TLabel> | |
| BitMatrix (const PolygonWithHoles< OtherPointType, TLabel > ®ion) | |
| Rasterizes a rectilinear region given over another coordinate type. | |
| template<class TLabel> | |
| BitMatrix (const Polygon< PointType, TLabel > &polygon) | |
| Rasterizes a rectilinear polygon, one bit per covered cell. | |
| template<class OtherPointType, class TLabel> | |
| BitMatrix (const Polygon< OtherPointType, TLabel > &polygon) | |
| Rasterizes a rectilinear polygon given over another coordinate type. | |
| template<class TLabel> | |
| BitMatrix (const PolygonSet< PointType, TLabel > &set) | |
| Rasterizes a rectilinear set of regions, one bit per covered cell. | |
| template<class OtherPointType, class TLabel> | |
| BitMatrix (const PolygonSet< OtherPointType, TLabel > &set) | |
| Rasterizes a rectilinear set given over another coordinate type. | |
| template<std::ranges::input_range Range = std::initializer_list<PointType>> requires (detail::is_point_v<std::remove_cvref_t<std::ranges::range_value_t<Range>>> && !AnyShapeConcept<std::remove_cvref_t <Range>> && !detail::is_bit_matrix_v<std::remove_cvref_t<Range>>) | |
| BitMatrix (Range &&points) | |
| Sets one cell per point of a range, over the smallest window holding them. | |
| const PointType & | origin () const |
| Lower-left cell of the window. | |
| int | width () const |
| Number of cells per row of the window. | |
| int | height () const |
| Number of rows of the window. | |
| RectangleType | window () const |
| The window, as the rectangle its cells cover. | |
| bool | emptyWindow () const |
| Whether the window itself is degenerate, so no cell can be set. | |
| bool | inWindow (NumberType x, NumberType y) const |
| Whether a cell is inside the window, and so can be set. | |
| bool | inWindow (const PointType &cell) const |
| Whether a cell is inside the window, and so can be set. | |
| bool | sameWindow (const BitMatrix &other) const |
| Whether two matrices cover the same window. | |
| BitMatrix | resized (const RectangleType &box) const |
| Returns the same cells over another window, dropping those outside. | |
| BitMatrix | trimmed () const |
| Returns the same cells over the smallest window holding them. | |
| bool | get (NumberType x, NumberType y) const |
| Whether the cell is set; cells outside the window are not. | |
| bool | get (const PointType &cell) const |
| Whether the cell is set; cells outside the window are not. | |
| void | set (NumberType x, NumberType y) |
| Sets the cell; a cell outside the window is silently dropped. | |
| void | set (const PointType &cell) |
| Sets the cell; a cell outside the window is silently dropped. | |
| void | set (NumberType x, NumberType y, bool value) |
| Sets or clears the cell; a cell outside the window is dropped. | |
| template<std::ranges::input_range Range = std::initializer_list<PointType>> requires (detail::is_point_v<std::remove_cvref_t<std::ranges::range_value_t<Range>>> && !AnyShapeConcept<std::remove_cvref_t <Range>> && !detail::is_bit_matrix_v<std::remove_cvref_t<Range>>) | |
| void | set (Range &&points) |
| Sets one cell per point of a range; cells outside the window are dropped. | |
| void | reset (NumberType x, NumberType y) |
| Clears the cell; a cell outside the window is silently dropped. | |
| void | reset (const PointType &cell) |
| Clears the cell; a cell outside the window is silently dropped. | |
| template<std::ranges::input_range Range = std::initializer_list<PointType>> requires (detail::is_point_v<std::remove_cvref_t<std::ranges::range_value_t<Range>>> && !AnyShapeConcept<std::remove_cvref_t <Range>> && !detail::is_bit_matrix_v<std::remove_cvref_t<Range>>) | |
| void | reset (Range &&points) |
| Clears one cell per point of a range; cells outside the window are dropped. | |
| void | flip (NumberType x, NumberType y) |
| Flips the cell; a cell outside the window is silently dropped. | |
| void | flip (const PointType &cell) |
| Flips the cell; a cell outside the window is silently dropped. | |
| template<std::ranges::input_range Range = std::initializer_list<PointType>> requires (detail::is_point_v<std::remove_cvref_t<std::ranges::range_value_t<Range>>> && !AnyShapeConcept<std::remove_cvref_t <Range>> && !detail::is_bit_matrix_v<std::remove_cvref_t<Range>>) | |
| void | flip (Range &&points) |
| Flips one cell per point of a range; cells outside the window are dropped. | |
| void | setAll () |
| Sets every cell of the window. | |
| void | clear () |
| Clears every cell, keeping the window. | |
| bool | empty () const |
| Whether no cell is set, which an empty window always is. | |
| std::size_t | count () const |
| Number of set cells. | |
| template<class ResultNumber = NumberType> | |
| ResultNumber | area () const |
| Area the set cells cover, which is their number since each is a unit square. | |
| template<class ResultNumber = NumberType> | |
| ResultNumber | perimeter () const |
| Length of the boundary of the covered region. | |
| template<class ResultNumber = division_result_t<NumberType>> | |
| Point< ResultNumber > | centroid () const |
| Centroid of the covered region. | |
| Iterator | begin () const |
| Iterator over the set lattice points, in row-major order. | |
| Iterator | end () const |
| End of the iteration over the set lattice points. | |
| auto | latticeView () const |
| Returns a lazy view of the set cells as lattice points. | |
| auto | cellsView () const |
| Returns a lazy view of the set cells as the unit squares they cover. | |
| std::vector< PointType > | lattice () const |
| The set cells as lattice points, in row-major order. | |
| std::vector< RectangleType > | cells () const |
| The set cells as the unit squares they cover, in row-major order. | |
| std::vector< RectangleType > | rectangles () const |
| The covered region as maximal horizontal runs of cells. | |
| RectangleType | bbox () const |
| The rectangle the set cells cover, empty when no cell is set. | |
| template<class ResultNumber = double> | |
| Rectangle< Point< ResultNumber > > | fbox () const |
| A floating-point bounding box of the covered region. | |
| template<class ResultNumber = division_result_t<NumberType>> | |
| Point< ResultNumber > | pointInside () const |
| A point in the interior of the covered region. | |
| RegionType | asPolygonWithHoles () const |
| The covered region, as one region with holes. | |
| PolygonSetType | asPolygonSet () const |
| The covered region, as a set of regions with holes. | |
| ConvexType | convexHull () const |
| Convex hull of the covered region. | |
| BitMatrix | operator~ () const |
| Returns the complement within the same window. | |
| BitMatrix & | operator&= (const BitMatrix &other) |
| Drops every cell the other matrix does not have. | |
| BitMatrix & | operator|= (const BitMatrix &other) |
| Adds every cell of the other matrix that this window holds. | |
| BitMatrix & | operator^= (const BitMatrix &other) |
| Flips every cell the other matrix has and this window holds. | |
| BitMatrix | operator& (const BitMatrix &other) const |
| The cells both matrices have, over the overlap of the windows. | |
| BitMatrix | operator| (const BitMatrix &other) const |
| The cells either matrix has, over the hull of the windows. | |
| BitMatrix | operator^ (const BitMatrix &other) const |
| The cells exactly one matrix has, over the hull of the windows. | |
| BitMatrix | difference (const BitMatrix &other) const |
| The cells this matrix has and the other does not, over this window. | |
| BitMatrix | symmetricDifference (const BitMatrix &other) const |
| The cells exactly one matrix has; the same as operator^. | |
| bool | operator== (const BitMatrix &other) const |
| Whether the two matrices have the same window and the same cells. | |
| std::strong_ordering | operator<=> (const BitMatrix &other) const |
| Orders matrices lexicographically by (origin, width, height, bits). | |
| bool | samePointSet (const BitMatrix &other) const |
| Whether the two matrices cover the same region. | |
| bool | contains (const BitMatrix &other) const |
| Whether the covered region contains the other one. | |
| bool | interiorContains (const BitMatrix &other) const |
| Whether the interior of the covered region contains the other one. | |
| bool | boundaryContains (const BitMatrix &other) const |
| Whether the boundary of the covered region contains the other one. | |
| bool | intersects (const BitMatrix &other) const |
| Whether the two covered regions share a point. | |
| bool | interiorsIntersect (const BitMatrix &other) const |
| Whether the interiors of the two covered regions share a point. | |
| std::size_t | andCount (const BitMatrix &other) const |
| Number of cells set in both matrices. | |
| std::size_t | orCount (const BitMatrix &other) const |
| Number of cells set in either matrix. | |
| std::size_t | xorCount (const BitMatrix &other) const |
| Number of cells set in exactly one matrix. | |
| BitMatrix | translated (const PointType &vector) const |
| Returns the same cells translated by a vector. | |
| BitMatrix | operator+ (const PointType &vector) const |
| Returns the same cells translated by a vector. | |
| BitMatrix | operator- (const PointType &vector) const |
| Returns the same cells translated by the opposite of a vector. | |
| BitMatrix & | operator+= (const PointType &vector) |
| Translates the cells by a vector. | |
| BitMatrix & | operator-= (const PointType &vector) |
| Translates the cells by the opposite of a vector. | |
| BitMatrix | reflected () const |
| Returns the reflection of the covered region through the origin. | |
| BitMatrix | operator- () const |
| Returns the reflection of the covered region through the origin. | |
| BitMatrix | reflectedX () const |
| Returns the reflection of the covered region across the x-axis. | |
| BitMatrix | reflectedY () const |
| Returns the reflection of the covered region across the y-axis. | |
| BitMatrix | transposed () const |
| Returns the reflection of the covered region across the diagonal. | |
| BitMatrix | rotated90 (int k=1) const |
| Returns the rotation of the covered region about the origin. | |
| BitMatrix & | rotate90 (int k=1) |
| Rotates the covered region about the origin. | |
| BitMatrix | latticeReflected () const |
| Returns the reflection of the cells as lattice points, {-c}. | |
| BitMatrix | latticeReflectedX () const |
| Returns the reflection of the cells as lattice points, {(x, -y)}. | |
| BitMatrix | latticeReflectedY () const |
| Returns the reflection of the cells as lattice points, {(-x, y)}. | |
| BitMatrix | latticeTransposed () const |
| Returns {(y, x)}; the same as transposed, which the two readings agree on. | |
| BitMatrix | latticeRotated90 (int k=1) const |
| Returns the rotation of the cells as lattice points. | |
| BitMatrix & | latticeRotate90 (int k=1) |
| Rotates the cells as lattice points. | |
| BitMatrix | latticeMinkowskiSum (const BitMatrix &other) const |
| Returns the Minkowski sum {a + b : a in *this, b in other}. | |
| BitMatrix | minkowskiSum (const BitMatrix &other) const |
| Returns the Minkowski sum of the two covered regions. | |
| BitMatrix | operator+ (const BitMatrix &other) const |
| Returns the Minkowski sum of the regions; the same as minkowskiSum. | |
| BitMatrix | minkowskiErosion (const BitMatrix &other) const |
| Returns the regularized Minkowski erosion of the covered regions. | |
| BitMatrix | latticeMinkowskiErosion (const BitMatrix &other) const |
| Returns the Minkowski erosion {p : p + other is inside *this}. | |
| BitMatrix | latticeOpening (const BitMatrix &other) const |
Returns the opening, a lattice erosion by other followed by a lattice sum. | |
| BitMatrix | latticeClosing (const BitMatrix &other) const |
Returns the closing, a lattice sum with other followed by a lattice erosion. | |
| BitMatrix | interior (GridAdjacency adjacency=GridAdjacency::edge) const |
| Returns the set cells all of whose neighbors are set. | |
| BitMatrix | boundary (GridAdjacency adjacency=GridAdjacency::edge) const |
| Returns the set cells with at least one neighbor that is not set. | |
| std::vector< BitMatrix > | connectedComponents (GridAdjacency adjacency=GridAdjacency::edge) const |
| Returns one matrix per connected group of cells, each trimmed. | |
| std::size_t | componentCount (GridAdjacency adjacency=GridAdjacency::edge) const |
| Number of connected groups of cells. | |
| bool | isConnected (GridAdjacency adjacency=GridAdjacency::edge) const |
| Whether the set cells form exactly one connected group. | |
| BitMatrix | fillHoles (GridAdjacency adjacency=GridAdjacency::edge) const |
| Returns the cells together with every hole they enclose. | |
| std::size_t | holeCount (GridAdjacency adjacency=GridAdjacency::edge) const |
| Number of holes the set cells enclose. | |
| std::int64_t | eulerNumber (GridAdjacency adjacency=GridAdjacency::edge) const |
| Euler characteristic of the covered region: components minus holes. | |
| bool | fillRows () |
| Fills the gaps of every row. | |
| bool | fillColumns () |
| Fills the gaps of every column. | |
| std::size_t | makeHvConvex () |
| Fills every cell that has set cells on both sides in its row and in its column, until nothing changes. | |
| bool | isRowConvex () const |
| Whether every row meets the set cells in a single interval. | |
| bool | isColumnConvex () const |
| Whether every column meets the set cells in a single interval. | |
| bool | isHvConvex () const |
| Whether every row and every column meets the cells in one interval. | |
Friends | |
| Canvas & | operator<< (Canvas &canvas, const BitMatrix &matrix) |
| Draws the covered region to a canvas. | |
A bit per cell of a rectangular window of the integer grid.
Cell (x, y) is the unit square [x, x+1] x [y, y+1], named by the integer coordinates of its lower-left corner. The bits cover the window [origin, origin + (width, height)), which is fixed at construction and never grows: writing outside it is a no-op and reading outside it gives false. Sizing the window is the caller's job, and resized and trimmed move a matrix to another one.
Rows are packed into 64-bit words, which is what makes the bulk operations cheap: the whole set algebra, count, andCount, perimeter and eulerNumber run a word at a time, latticeMinkowskiSum costs one shifted or-assignment of a whole matrix per cell of the smaller operand, and the connectivity and boundary walks behind componentCount and asPolygonSet move a run of cells at a time rather than a cell at a time.
A matrix wears two hats, and which one an operation wears is stated in its documentation:
minkowskiSum and minkowskiErosion, without the prefix, are the region sum and the regularized region erosion the shapes compute, and both commute with asPolygonSet.
Two operations compute from the window rather than only from the cells, since a complement has to be taken relative to something bounded: operator~ and, through it, latticeMinkowskiErosion. Every other construction and every geometric predicate depends only on the cells.
The window is part of a matrix's value all the same. operator==, operator<=> and std::hash compare the window along with the cells, as they do for a shape's stored representation, so a != a.trimmed() whenever trimming moves anything. samePointSet is the geometric question of whether two matrices cover the same region, and ignores the window. A window covering no cell has one canonical form, so all such matrices compare equal whatever origin they were built with.
| TPointType | Point type naming a cell; its coordinates must be a signed integral type, since a cell of the grid is an integer position. |
| using pgl::BitMatrix< TPointType >::const_iterator = Iterator |
Iteration is read-only, so both iterator types are Iterator.
| using pgl::BitMatrix< TPointType >::ConvexType = Convex<PointType> |
Convex type convexHull produces.
| using pgl::BitMatrix< TPointType >::iterator = Iterator |
Iteration is read-only, so both iterator types are Iterator.
| using pgl::BitMatrix< TPointType >::NumberType = typename PointType::NumberType |
Coordinate type of a cell.
| using pgl::BitMatrix< TPointType >::PointType = TPointType |
Point type naming a cell by its lower-left corner.
| using pgl::BitMatrix< TPointType >::PolygonSetType = PolygonSet<PointType> |
Region-set type asPolygonSet produces.
| using pgl::BitMatrix< TPointType >::RectangleType = Rectangle<PointType> |
| using pgl::BitMatrix< TPointType >::RegionType = PolygonWithHoles<PointType> |
Region type asPolygonWithHoles produces.
| using pgl::BitMatrix< TPointType >::value_type = PointType |
Cell type the iterators yield.
|
default |
Creates a matrix whose window is empty, so no cell can be set.
|
inline |
Creates an empty matrix covering a window of the grid.
| origin | Lower-left cell of the window. |
| width | Number of cells per row; a non-positive value empties the window. |
| height | Number of rows; a non-positive value empties the window. |
|
inlineexplicit |
Creates an empty matrix over the cells a rectangle covers.
The window runs from box.min() to box.max(), so a rectangle of width w and height h gives w * h cells, the last of them named by box.max() - (1, 1). This is the inverse of window.
| box | Rectangle covering the window; it must have integer corners, which its point type guarantees. |
|
inlineexplicit |
Rasterizes a rectilinear region, one bit per covered cell.
Fills the cells whose interior lies inside the region, over a window that is exactly the region's bounding box. Crossing parity along each row does it: every ring contributes its vertical edges, and the cells between the first and second crossing, the third and fourth, and so on, are inside. The integer coordinates make it exact, since they keep every horizontal cross-section constant within a row of cells.
This is the fast path for the rectilinear case. innerRaster gives the same answer for such a region and also accepts every other shape, at the cost of one exact predicate per cell of the bounding box.
| region | Region to rasterize; every edge of it must be axis-parallel. |
| std::logic_error | If an edge of the region is not axis-parallel. |
|
inlineexplicit |
Rasterizes a rectilinear region given over another coordinate type.
A cell is an integer position, so a region whose coordinates are not integers – a Rational or a floating-point one – covers a set of cells only when every coordinate of it happens to be whole. That is checked rather than rounded: a coordinate that is not a whole number, or is one NumberType cannot hold, throws instead of moving a vertex.
| region | Region to rasterize; every edge of it must be axis-parallel and every coordinate a whole number this grid can hold. |
| std::logic_error | If an edge is not axis-parallel, or a coordinate is not a whole number of the grid. |
|
inlineexplicit |
Rasterizes a rectilinear polygon, one bit per covered cell.
The single-ring case of BitMatrix(const PolygonWithHoles<PointType, TLabel>&), with the same crossing parity over the same window, the polygon's bounding box. A self-intersecting polygon is filled by that parity rather than rejected.
| polygon | Polygon to rasterize; every edge of it must be axis-parallel. |
| std::logic_error | If an edge of the polygon is not axis-parallel. |
|
inlineexplicit |
Rasterizes a rectilinear polygon given over another coordinate type.
The single-ring case of BitMatrix(const PolygonWithHoles<OtherPointType, TLabel>&), with the same whole-number requirement on every coordinate.
| polygon | Polygon to rasterize; every edge of it must be axis-parallel and every coordinate a whole number this grid can hold. |
| std::logic_error | If an edge is not axis-parallel, or a coordinate is not a whole number of the grid. |
|
inlineexplicit |
Rasterizes a rectilinear set of regions, one bit per covered cell.
The many-component case of BitMatrix(const PolygonWithHoles<PointType, TLabel>&), over a window that is the bounding box of the whole set. Every ring of every component feeds the same parity pass, which the disjoint interiors keep exact: a row leaves one component before it enters the next, so the crossings pair up within a component.
| set | Set to rasterize; every edge of it must be axis-parallel. |
| std::logic_error | If an edge of the set is not axis-parallel. |
|
inlineexplicit |
Rasterizes a rectilinear set given over another coordinate type.
The many-component case of BitMatrix(const PolygonWithHoles<OtherPointType, TLabel>&), with the same whole-number requirement on every coordinate.
| set | Set to rasterize; every edge of it must be axis-parallel and every coordinate a whole number this grid can hold. |
| std::logic_error | If an edge is not axis-parallel, or a coordinate is not a whole number of the grid. |
|
inlineexplicit |
Sets one cell per point of a range, over the smallest window holding them.
This is the lattice-point reading of a matrix: every point names the cell it is, rather than a corner of a region to fill. The window is the smallest one holding every point, so the result has window() == bbox() and equals its own trimmed; an empty range gives an empty window. Repeated points set the same cell again, which changes nothing.
Any range of points does, except a shape or another matrix. A shape that happens to iterate over its vertices – a Polygon, a Convex, a Polyline – is a boundary and not a point cloud, and the shapes that rasterize have their own constructor above; a matrix carries a window that this would silently trim. Feed either one's points through lattice or a view to ask for this reading of it anyway.
The points may carry any coordinate type, checked rather than rounded exactly as the shape constructors check theirs.
| Range | Input range of points, defaulting to an initializer list so that a braced list of cells works. |
| points | Cells to set. |
| std::logic_error | If a coordinate is not a whole number this grid can hold, or the points span more cells than a window holds. |
|
inlinenodiscard |
Number of cells set in both matrices.
The two windows need not agree; only the cells they share can be set in both, so the count runs over the rows and words of the overlap, reading the other matrix a word at a time, shifted into this one's alignment.
|
inlinenodiscard |
Area the set cells cover, which is their number since each is a unit square.
| ResultNumber | Result type (default: NumberType). |
|
inlinenodiscard |
The covered region, as a set of regions with holes.
One component per edge-connected group of cells, so this has no precondition; two components touching only at a corner stay apart, and bbox() is exactly the bounding box of the result.
The cost is one pass over the words plus one over the boundary edges, not a union of unit squares: the loops are read straight off the words, which gives the outer ring and one ring per hole directly, with the vertices in the middle of a straight stretch dropped along the way. A window of w cells whose components carry b boundary edges and split into r runs of cells therefore costs O(w / 64 + b + r log r), against the arrangement a regularized union of unit squares would have to build.
|
inlinenodiscard |
The covered region, as one region with holes.
A matrix with no cell gives an empty region.
| std::logic_error | If the set cells do not form a single edge-connected polyomino, which is what a rasterized region and its Minkowski sums are. Use asPolygonSet when they need not. |
|
inlinenodiscard |
The rectangle the set cells cover, empty when no cell is set.
Exactly the box asPolygonSet would report, read off the first and last set word of every row rather than built from the regions.
|
inlinenodiscard |
Iterator over the set lattice points, in row-major order.
|
inlinenodiscard |
Returns the set cells with at least one neighbor that is not set.
| adjacency | Which cells count as neighbors. |
|
inlinenodiscard |
Whether the boundary of the covered region contains the other one.
The boundary is a curve and a nonempty matrix covers area, so this holds only for an empty other. It is here to answer the question rather than to leave it to a wrong guess.
|
inlinenodiscard |
The set cells as the unit squares they cover, in row-major order.
One rectangle per cell. rectangles instead merges each row's runs into as few rectangles as a row-major pass can, which is the cheaper covering to draw or to measure.
|
inlinenodiscard |
Returns a lazy view of the set cells as the unit squares they cover.
Builds each rectangle as it is reached, so nothing is allocated. Like latticeView it refers to this matrix; cells materializes the same squares into a vector.
|
inlinenodiscard |
Centroid of the covered region.
| ResultNumber | Coordinate type of the result; the default divides exactly, as every other pgl construction that divides does. |
| std::logic_error | If no cell is set, since there is no centroid. |
|
inline |
Clears every cell, keeping the window.
|
inlinenodiscard |
Number of connected groups of cells.
A scanline flood fill, so this costs one pass over the words and a constant per run of cells, and never materializes a group.
|
inlinenodiscard |
Returns one matrix per connected group of cells, each trimmed.
The groups come out ordered by their lowest, then leftmost cell.
| adjacency | Which cells count as neighbors. |
|
inlinenodiscard |
Whether the covered region contains the other one.
A cell the other matrix has and this one does not sticks out of this region, so this is exactly "every cell of @p other is a cell of this".
|
inlinenodiscard |
Convex hull of the covered region.
|
inlinenodiscard |
Number of set cells.
|
inlinenodiscard |
The cells this matrix has and the other does not, over this window.
|
inlinenodiscard |
Whether no cell is set, which an empty window always is.
|
inlinenodiscard |
Whether the window itself is degenerate, so no cell can be set.
|
inlinenodiscard |
End of the iteration over the set lattice points.
|
inlinenodiscard |
Euler characteristic of the covered region: components minus holes.
Counted from the sixteen patterns a two-by-two block of cells can show, so it costs one pass over the words and needs no flood fill.
| adjacency | Which cells count as neighbors of the foreground. |
|
inlinenodiscard |
A floating-point bounding box of the covered region.
| ResultNumber | Coordinate type of the result. |
|
inline |
Fills the gaps of every column.
|
inlinenodiscard |
Returns the cells together with every hole they enclose.
A hole is a group of unset cells that cannot reach outside the bounding box. The background is walked with the adjacency complementary to adjacency – 8 for a 4-connected foreground and the other way round – which is what keeps a diagonal chain of cells from both being connected and letting the background leak through it.
| adjacency | Which cells count as neighbors of the foreground. |
|
inline |
Fills the gaps of every row.
|
inline |
Flips the cell; a cell outside the window is silently dropped.
|
inline |
Flips the cell; a cell outside the window is silently dropped.
|
inline |
Flips one cell per point of a range; cells outside the window are dropped.
The plural of flip(const PointType&), taking the same ranges the range set does and reading their points the same way: every point names the cell it is, over the window the matrix already has. A repeated point flips the same cell twice and so leaves it as it was, unlike the range set and reset, which repetition does not affect.
| Range | Input range of points, defaulting to an initializer list so that a braced list of cells works. |
| points | Cells to flip. |
| std::logic_error | If a coordinate is not a whole number this grid can hold. |
|
inlinenodiscard |
Whether the cell is set; cells outside the window are not.
|
inlinenodiscard |
Whether the cell is set; cells outside the window are not.
|
inlinenodiscard |
Number of rows of the window.
|
inlinenodiscard |
Number of holes the set cells enclose.
| adjacency | Which cells count as neighbors of the foreground. |
|
inlinenodiscard |
Returns the set cells all of whose neighbors are set.
A cell on the border of the window has neighbors outside it, which count as unset, so it never belongs to the interior.
| adjacency | Which cells count as neighbors. |
|
inlinenodiscard |
Whether the interior of the covered region contains the other one.
A cell of other whose closure touches the boundary of this region is not inside its interior, and touching includes meeting at a corner, so this asks whether interior(GridAdjacency::vertex) contains other.
|
inlinenodiscard |
Whether the interiors of the two covered regions share a point.
Two distinct cells have disjoint interiors, so this holds exactly when the matrices share a cell.
|
inlinenodiscard |
Whether the two covered regions share a point.
The cells are closed unit squares, so two of them meeting along an edge or at a single corner already intersect: this holds as soon as a cell of one matrix is within Chebyshev distance one of a cell of the other. Use interiorsIntersect for the stricter question of a shared cell.
|
inlinenodiscard |
Whether a cell is inside the window, and so can be set.
|
inlinenodiscard |
Whether a cell is inside the window, and so can be set.
|
inlinenodiscard |
Whether every column meets the set cells in a single interval.
Read off the words rather than by filling a copy: sweeping the rows upwards, a column closes once a gap opens over a cell it has shown, and the answer is no as soon as a closed column shows another cell.
|
inlinenodiscard |
Whether the set cells form exactly one connected group.
|
inlinenodiscard |
Whether every row and every column meets the cells in one interval.
|
inlinenodiscard |
Whether every row meets the set cells in a single interval.
Read off the words rather than by filling a copy: a row is an interval exactly when it holds as many cells as lie between its first and its last.
|
inlinenodiscard |
The set cells as lattice points, in row-major order.
The reading every lattice-prefixed operation works in: a cell stands for the point at its lower-left corner, which is also the name get and set address it by, and what the iterators yield. cells is the same list read as the squares the cells cover.
|
inlinenodiscard |
Returns the closing, a lattice sum with other followed by a lattice erosion.
|
inlinenodiscard |
Returns the Minkowski erosion {p : p + other is inside *this}.
Like operator~, this reads the window: a cell outside it counts as unset, so the erosion is taken against this matrix as a bounded set. The window of the result is this window shrunk by the bounding box of other, which is the largest window a translate of other can land in. Eroding by a matrix with no cell is vacuously true everywhere, and fills the whole window.
|
inlinenodiscard |
Returns the Minkowski sum {a + b : a in *this, b in other}.
The window of the result is exactly the bounding box of the sum. The cost is one shifted or-assignment of the larger operand per cell of the smaller one, so summing a large region with a small structuring element is cheap.
|
inlinenodiscard |
Returns the opening, a lattice erosion by other followed by a lattice sum.
|
inlinenodiscard |
Returns the reflection of the cells as lattice points, {-c}.
The reflection latticeMinkowskiErosion is dual to: it is what makes ~(~a).latticeMinkowskiSum(b.latticeReflected()) and a.latticeMinkowskiErosion(b) the same question over a common window. It sits one cell from reflected, which reflects the squares instead.
|
inlinenodiscard |
Returns the reflection of the cells as lattice points, {(x, -y)}.
|
inlinenodiscard |
Returns the reflection of the cells as lattice points, {(-x, y)}.
|
inline |
Rotates the cells as lattice points.
| k | Number of counterclockwise quarter turns; may be negative. |
|
inlinenodiscard |
Returns the rotation of the cells as lattice points.
| k | Number of counterclockwise quarter turns; may be negative. |
|
inlinenodiscard |
Returns {(y, x)}; the same as transposed, which the two readings agree on.
|
inlinenodiscard |
Returns a lazy view of the set cells as lattice points.
The iteration range itself: it yields every set cell as a const reference to its lower-left corner, in row-major order, copying and allocating nothing. It refers to this matrix and is invalidated by anything that modifies it; lattice materializes the same cells into a vector.
|
inline |
Fills every cell that has set cells on both sides in its row and in its column, until nothing changes.
The result is the smallest hv-convex superset: every row and every column of it meets it in a single interval. Only cells strictly between set cells are added, so the window is never outgrown and the loop terminates.
|
inlinenodiscard |
Returns the regularized Minkowski erosion of the covered regions.
The erosion the shapes compute, regularized as PolygonSet regularizes its own, so this commutes with the conversion: a.minkowskiErosion(b).asPolygonSet() and a.asPolygonSet().minkowskiErosion(b.asPolygonSet()) agree.
Regularizing is what keeps the answer on the grid. Writing the operand as B = latB (+) U, the erosion splits into (A (-) latB) (-) U, and the first step is the lattice erosion, which is a cell region. For the second, a non-integer p has p + U inside a cell region exactly when the two-by-two block of cells it straddles is, so the interior of the result is a union of open cells and its closure is the lattice erosion by that block. What regularizing drops is the lower-dimensional part: eroding a single cell by a single cell leaves the one point p = 0, which the shapes report as a degenerate HalfplaneIntersection and this reports as empty.
The two steps compose into one, so the cost is a single lattice erosion by other dilated with the two-by-two block. Eroding by a matrix with no cell is the whole plane, which no window holds; this fills the window, as latticeMinkowskiErosion does.
|
inlinenodiscard |
Returns the Minkowski sum of the two covered regions.
The sum the shapes compute, so this commutes with the conversion: (a + b).asPolygonSet() and a.asPolygonSet() + b.asPolygonSet() agree. The unit square is not the identity of that sum – U (+) U is the two-by-two square [0,2]^2 – so this is latticeMinkowskiSum followed by a dilation with the two-by-two block of cells that the extra square covers, leaving the result one cell wider and one cell taller than the lattice sum. Reach for latticeMinkowskiSum in morphology, where a single cell has to be the identity.
|
inline |
The cells both matrices have, over the overlap of the windows.
|
inline |
Drops every cell the other matrix does not have.
|
inlinenodiscard |
Returns the Minkowski sum of the regions; the same as minkowskiSum.
|
inline |
Returns the same cells translated by a vector.
|
inline |
Translates the cells by a vector.
|
inlinenodiscard |
Returns the reflection of the covered region through the origin.
|
inline |
Returns the same cells translated by the opposite of a vector.
|
inline |
Translates the cells by the opposite of a vector.
|
inline |
Orders matrices lexicographically by (origin, width, height, bits).
A total order consistent with operator==, so a matrix can key a std::set or a std::map. It is an order on the representation and carries no geometric meaning: two matrices covering the same region over different windows are ordered by their windows.
|
inline |
Whether the two matrices have the same window and the same cells.
Compares the stored representation, as a shape's operator== does. Use samePointSet to ask whether they cover the same region regardless of the window.
|
inline |
The cells exactly one matrix has, over the hull of the windows.
|
inline |
Flips every cell the other matrix has and this window holds.
|
inline |
The cells either matrix has, over the hull of the windows.
|
inline |
Adds every cell of the other matrix that this window holds.
|
inline |
Returns the complement within the same window.
The window is unchanged, so this is the complement of the set cells inside it, not of the whole plane. Together with latticeMinkowskiErosion, which is built on it, this is the only operation that reads the window rather than only the cells.
|
inlinenodiscard |
Number of cells set in either matrix.
|
inlinenodiscard |
Lower-left cell of the window.
|
inlinenodiscard |
Length of the boundary of the covered region.
Counts the unit edges with a set cell on exactly one side, so a cell on the border of the window contributes the edges facing out of it. Runs a word at a time.
| ResultNumber | Result type (default: NumberType). |
|
inlinenodiscard |
A point in the interior of the covered region.
The center of the first set cell in row-major order.
| ResultNumber | Coordinate type of the result. |
| std::logic_error | If no cell is set, since there is no such point. |
|
inlinenodiscard |
The covered region as maximal horizontal runs of cells.
The rectangles are disjoint and cover exactly the set cells, one per maximal run, in row-major order. Streaming them into a Canvas draws the matrix: canvas << matrix.rectangles().
|
inlinenodiscard |
Returns the reflection of the covered region through the origin.
A symmetry of the plane, so it acts on the cells as the squares they are: the square of cell c reflects onto the square of cell -c - (1,1), and the result is what reflecting asPolygonSet() gives. latticeReflected is the reflection of the lattice points, which lands one cell away.
|
inlinenodiscard |
Returns the reflection of the covered region across the x-axis.
|
inlinenodiscard |
Returns the reflection of the covered region across the y-axis.
|
inline |
Clears the cell; a cell outside the window is silently dropped.
|
inline |
Clears the cell; a cell outside the window is silently dropped.
|
inline |
Clears one cell per point of a range; cells outside the window are dropped.
The plural of reset(const PointType&), taking the same ranges the range set does and reading their points the same way: every point names the cell it is, over the window the matrix already has. Repeated points clear the same cell again, which changes nothing.
| Range | Input range of points, defaulting to an initializer list so that a braced list of cells works. |
| points | Cells to clear. |
| std::logic_error | If a coordinate is not a whole number this grid can hold. |
|
inlinenodiscard |
Returns the same cells over another window, dropping those outside.
| box | Window of the result, read as BitMatrix(const RectangleType&) reads it. |
|
inline |
Rotates the covered region about the origin.
| k | Number of counterclockwise quarter turns; may be negative. |
|
inlinenodiscard |
Returns the rotation of the covered region about the origin.
| k | Number of counterclockwise quarter turns; may be negative. |
|
inlinenodiscard |
Whether the two matrices cover the same region.
Reads only the cells, so a matrix and its trimmed copy agree, unlike operator==, which compares the window too.
|
inlinenodiscard |
Whether two matrices cover the same window.
|
inline |
Sets the cell; a cell outside the window is silently dropped.
|
inline |
Sets the cell; a cell outside the window is silently dropped.
|
inline |
Sets or clears the cell; a cell outside the window is dropped.
|
inline |
Sets one cell per point of a range; cells outside the window are dropped.
Every point names the cell it is, the lattice-point reading the range constructor takes, except that the window here is the one the matrix already has. Repeated points set the same cell again, which changes nothing.
Any range of points does, except a shape or another matrix, exactly as for that constructor: a shape that iterates over its vertices is a boundary and not a point cloud. The points may carry any coordinate type, checked rather than rounded.
| Range | Input range of points, defaulting to an initializer list so that a braced list of cells works. |
| points | Cells to set. |
| std::logic_error | If a coordinate is not a whole number this grid can hold. |
|
inline |
Sets every cell of the window.
|
inlinenodiscard |
The cells exactly one matrix has; the same as operator^.
|
inlinenodiscard |
Returns the same cells translated by a vector.
|
inlinenodiscard |
Returns the reflection of the covered region across the diagonal.
Swapping the coordinates carries the square of cell (x, y) onto the square of cell (y, x), so this is the one symmetry the two readings agree on; latticeTransposed is the same operation under its lattice name.
|
inlinenodiscard |
|
inlinenodiscard |
Number of cells per row of the window.
|
inlinenodiscard |
The window, as the rectangle its cells cover.
|
inlinenodiscard |
Number of cells set in exactly one matrix.
|
friend |
Draws the covered region to a canvas.
Sends asPolygonSet with the current style, so the whole matrix is a single element however many components it has, with its holes as holes. Stream rectangles instead to draw the cells as separate elements.
| canvas | Destination canvas. |
| matrix | Matrix whose covered region is drawn. |