src/stats/ConnectedComponentsByCellBorder.js

  1.  
  2. import Stat from "./Stat.js"
  3. import BorderPixelsByCell from "./BorderPixelsByCell.js"
  4.  
  5. /** This Stat creates an object with the connected components of each cell's border on the grid.
  6. Keys are the {@link CellId} of all cells on the grid, corresponding values are objects
  7. where each element is a connected component. Each element of that array contains
  8. the {@link ArrayCoordinate} for that pixel.
  9. @example
  10. * let CPM = require( "path/to/build" )
  11. *
  12. * // Make a CPM, seed a cell, and get the ConnectedComponentsByCellBorder
  13. * let C = new CPM.CPM( [100,100], {
  14. * T:20,
  15. * J:[[0,20],[20,10]],
  16. * V:[0,200],
  17. * LAMBDA_V:[0,2]
  18. * } )
  19. * let gm = new CPM.GridManipulator( C )
  20. * gm.seedCell(1)
  21. * gm.seedCell(1)
  22. * for( let t = 0; t < 100; t++ ){ C.timeStep() }
  23. * C.getStat( CPM.ConnectedComponentsByCellBorder )
  24. */
  25. class ConnectedComponentsByCellBorder extends Stat {
  26.  
  27. /** This method computes the connected components of the border of a specific cell.
  28. @param {CellId} cellid the unique cell id of the cell to get the border's connected components of.
  29. @returns {object} object of cell border connected components. These components in turn consist of the pixels
  30. (specified by {@link ArrayCoordinate}) belonging to that cell border.
  31. */
  32. connectedComponentsOfCellBorder( cellid ){
  33. /* Note that to get connected components, we only need to look at cellborderpixels. */
  34. let cbp = this.M.getStat( BorderPixelsByCell )
  35. cbpi = cbp[cellid]
  36. let visited = {}, k=0, pixels = []
  37. let labelComponent = function(seed, k){
  38. let q = [seed]
  39. visited[q[0]] = 1
  40. pixels[k] = []
  41. while( q.length > 0 ){
  42. let e = q.pop()
  43. pixels[k].push( this.M.grid.i2p(e) )
  44. let ne = this.M.grid.neighi( e )
  45. for( let i = 0 ; i < ne.length ; i ++ ){
  46. if( this.M.pixti( ne[i] ) == t &&
  47. !(ne[i] in visited) ){
  48. q.push(ne[i])
  49. visited[ne[i]]=1
  50. }
  51. }
  52. }
  53. }
  54. for( let i = 0 ; i < cbpi.length ; i ++ ){
  55. let pi = this.M.grid.p2i( cbpi[i] )
  56. if( !(pi in visited) ){
  57. labelComponent( pi, k )
  58. k++
  59. }
  60. }
  61. return pixels
  62. }
  63.  
  64. /** The compute method of ConnectedComponentsByCellBorder creates an object with
  65. connected components of the border of each cell on the grid.
  66. @return {CellObject} object with for each cell on the grid
  67. an object of components. These components in turn consist of the pixels
  68. (specified by {@link ArrayCoordinate}) belonging to that cell.
  69. */
  70. compute(){
  71. // initialize the object
  72. let components = { }
  73. // The this.M.pixels() iterator returns coordinates and cellid for all
  74. // non-background pixels on the grid. See the appropriate Grid class for
  75. // its implementation.
  76. for( let ci of this.M.cellIDs() ){
  77. components[ci] = this.connectedComponentsOfCellBorder( ci )
  78. }
  79. return components
  80. }
  81. }
  82.  
  83. export default ConnectedComponentsByCellBorder