RandomGridFiller.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. //
  2. // RandomGridFiller.hpp
  3. // auto_fill_jewel_v3
  4. //
  5. // Created by Red on 2024/11/26.
  6. // 随机矩形填充
  7. // 1. 每个宝石使用其外接矩形。
  8. // 2. 采用随机点位填充到盘子中,不考虑宝石之间重叠率问题,但是宝石必须要在盘子内部。
  9. // 3. 尝试5次,最后选择一组重叠率最小的。
  10. // 4. 要求效率尽量高,2帧完成一关宝石填充(?)
  11. #ifndef RandomGridFiller_hpp
  12. #define RandomGridFiller_hpp
  13. #include <vector>
  14. #include <stdio.h>
  15. #include "FillResult.hpp"
  16. #include "contourdata.h"
  17. #include <unordered_map>
  18. #include "BoostGeometryTools.hpp"
  19. using std::unordered_map;
  20. using std::vector;
  21. struct RandomGridFiller {
  22. //输入数据的结构 宝石的外接矩形
  23. struct JewelBox {
  24. inline JewelBox():_cnt(0),_width(0),_height(0),_jewelTypeId(-1){}
  25. int _cnt ;//宝石个数
  26. float _width; //外接矩形宽度(像素)
  27. float _height ;//外接矩形高度(像素)
  28. int _jewelTypeId ;
  29. } ;
  30. int _seed ;
  31. //对外接口
  32. void fill( vector<JewelBox>& jewelsArray , //需要填充的宝石
  33. float bottomLeftX,float bottomLeftY,//盘子有效区域
  34. float topRightX,float topRightY, //盘子有效区域
  35. vector<FillResult>& results //尝试五组只选择一个覆盖度最小的填充结果
  36. );
  37. private:
  38. //潜在的点位
  39. struct DistancePosition {
  40. bool _isTaken ;
  41. float _distance ;
  42. ContourData::Point _point ;
  43. } ;
  44. //格点占用数据
  45. struct GridData {
  46. inline void reset(float blx,float bly,float sx,float sy,int nrows,int ncols){
  47. _bottomLeftX = blx;
  48. _bottomLeftY = bly;
  49. _stepX = sx ;
  50. _stepY = sy ;
  51. _rows.resize(nrows);
  52. for(auto it=_rows.begin();it!=_rows.end();++it)it->resize(ncols,false);
  53. }
  54. inline void clearValues(){for(auto it=_rows.begin();it!=_rows.end();++it)it->resize(it->size(),false); }
  55. vector< vector<bool> > _rows ;
  56. float _bottomLeftX, _bottomLeftY ;//左下角原点坐标
  57. float _stepX,_stepY ;//格点间隔
  58. } ;
  59. // 返回未填进去的宝石数量,目前看没有填进去已经表示本次填充失败了
  60. int randomFillOneRound( vector<JewelBox>& jewelsArray,
  61. float bottomLeftX,float bottomLeftY,//盘子有效区域
  62. float topRightX,float topRightY, //盘子有效区域
  63. vector<ContourData::Point> potPositions, //潜在的点位
  64. vector<FillResult>& results,
  65. float& jewDistanceSum //宝石间距离求和,用于衡量宝石间的分散程度
  66. ,const float gridWid //盘子子网格宽度
  67. ,const float gridhei //盘子子网格高度
  68. ,int& resultTotCov //返回全部宝石格点叠盖度之和
  69. ) ;
  70. //随机排序索引值
  71. vector<int> randIndices(const int count0 );
  72. //假定每个网格覆盖一次宝石其对应的int值加一,下面函数用于统计某个点位(x,y)(盘子内部坐标,与subGrid对齐)周边半径个网格覆盖值的求和。
  73. //最优条件是求和值为0。虽然宝石一般使用矩形描述,这里为了将点坐标覆盖的一个区域换算到 subGrid 格子数方便,使用圆形进行计算。
  74. [[deprecated]]
  75. int sumOfSubGridTakenCounts(const int x,const int y,const int radius,const float gridwid,const float gridhei,const vector<vector<int>>& rowColSubGrid);
  76. //为中心点位x,y,半径radius的覆盖范围的subgrid占用数加1。
  77. [[deprecated]]
  78. void subGridTakenCountsAddOne(const int x,const int y,const int radius,const float gridwid,const float gridhei,vector<vector<int>>& rowColSubGrid);
  79. //多边形盖住的格点数量
  80. int coverageGridCount( BoostGeometryTools::BoostPolygon& box, const GridData& grid ) ;
  81. //全部覆盖求和,excludeIndex 不做比较的索引值
  82. int totalCoverageGridCount(BoostGeometryTools::BoostPolygon& box, const vector<GridData>& grids , int excludeIndex=-1 ) ;
  83. //将覆盖的格点数据赋值
  84. void setGridCoverageByBox( BoostGeometryTools::BoostPolygon& box, GridData& grid ) ;
  85. //按距离从外到内构建随机点位
  86. void generateDistanceRandomSlotPositions(const float centerx,const float centery,const vector<ContourData::Point>& points, vector<DistancePosition>& results ) ;
  87. } ;
  88. #endif /* RandomGridFiller_hpp */