1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
#include <iostream>
#include <iomanip>
#include <cmath>
#include <list>
struct Coord
{
double x;
double y;
};
template<typename ostream>
ostream& operator <<(ostream& os, const Coord& coord_)
{
os<<std::left;
os<<" [x: "<<std::setw(5)<<coord_.x<<" , y: "<<std::setw(5)<<coord_.y<<std::right<<"] \n";
return os;
}
/* assumes that the {x,y} coordnates of the square increase downwards and right
* |---------------------------> x increases this way
* | point A|----------- point B
* | | |
* | | |
* | point C|___________|point D
* \/
* y increases donwards
* such that if point A=(0,0) then B=(0,1) , C=(1,0), D=(1,1)
*
* Requires: for a square to be divided into smaller squares where N = number of squares then
* N must be a perfect square such that sqroot(N) == whole number
* N can be numbers like 1,4,9,16,25,36,64,81 ...
* if N isn't a perfect square then the result would be rectangles.
*/
class Square
{
private:
Coord top_left;
double side_length;
public:
Square()=default;
Square(const Coord& point_,double side_len)
:top_left(point_),side_length(side_len){}
Square(const Square&)=default;
Square& operator=(const Square&)=default;
virtual ~Square(){}
inline Coord get_top_left()const {return top_left;}
inline Coord get_top_right()const {return {top_left.x+side_length,top_left.y};}
inline Coord get_lower_left()const {return {top_left.x,top_left.y+side_length};}
inline Coord get_lower_right()const {return {top_left.x+side_length, top_left.y+side_length};}
inline double get_area()const {return side_length*side_length;}
inline double get_side_length()const{return side_length;}
};
class Sub_square : public Square
{
private:
std::size_t identifier;
public:
Sub_square(): Square(),identifier(0){}
Sub_square(const Coord& point_,double side_len,std::size_t id_)
:Square(point_,side_len),identifier(id_){}
inline std::size_t get_id()const{return identifier;}
void print_detail()const
{
std::cout<<"\nsub Square id : "<<identifier<<"\n";
std::cout<<" length : "<<get_side_length()<<"\n";
std::cout<<" area : "<<get_area()<<"\n";
std::cout<<"----------------------------------------\n";
std::cout<<"top left : "<<get_top_left();
std::cout<<"top right : "<<get_top_right();
std::cout<<"lower left : "<<get_lower_left();
std::cout<<"lower right : "<<get_lower_right();
std::cout<<"----------------------------------------\n";
}
///other members
};
class Square_grid
{
private:
Square source_square;
std::size_t total_squares;
std::list<std::list<Sub_square>> sub_sqr_list;
bool populated;
static bool is_perfect_square(std::size_t x)
{
//!cant use use std::sqrt() because of floating point rounding errors
//Let n be the number, a=5n and b=5.
//While a>=b, a=a−b and add 10 to b.
//When you get a<b, then n is a square if and only if a=0.
std::size_t checkr =(x*5);
std::size_t bound = 5;
std::size_t increment =10;
while(checkr >= bound)
{
checkr -= bound;
bound += increment;
}
if(checkr==0)
return true;
return false;
}
/*square_: original square to be divided
*nom_of_squares: (>0) number of squares it should be divided into.
* : this number must be a perfect square e.g 4,9,16,25,36 such that sqrt(num_of_squares) = whole number
* otherwise you will be dividing into rectangles
*/
void grid_init(const Square& square_,std::size_t num_squares)
{
if(is_perfect_square(num_squares))
{
source_square = square_;
total_squares = num_squares;
populated = true;
std::size_t sqr_id_=1;
std::size_t div_per_side = (std::size_t)std::sqrt(num_squares);
double sub_sqr_len = (square_.get_side_length()/div_per_side);
///dividing the square
double x_coord = square_.get_top_left().x;
double y_coord = square_.get_top_left().y;
for(std::size_t x =0; x < div_per_side; x++, x_coord += sub_sqr_len)
{
std::list<Sub_square> column{};
for(std::size_t y = 0; y < div_per_side; y++, y_coord += sub_sqr_len)
{
Coord sqr_coord={x_coord,y_coord};
Sub_square this_square(sqr_coord,sub_sqr_len,sqr_id_);
column.push_back(this_square);
++sqr_id_;
}
sub_sqr_list.push_back(column);
y_coord = square_.get_top_left().y;
}
}
}
void reset(){source_square= Square(); total_squares=0;sub_sqr_list={}; populated=false;}
public:
Square_grid() :source_square(),total_squares(0),sub_sqr_list({}), populated(false){}
Square_grid(const Square& square_, std::size_t num_squares)
:source_square(),total_squares(0),sub_sqr_list({}), populated(false)
{
grid_init(square_,num_squares);
}
inline std::list<std::list<Sub_square>> get_all_sub_squares() const{return sub_sqr_list;}
inline std::size_t get_square_count() const{return total_squares;}
inline Square get_original_square()const {return source_square;}
inline bool valid_grid() const{return populated;}
void construct_from(const Square& square_, std::size_t num_squares)
{
reset();
grid_init(square_,num_squares);
}
///return pointer to sub square containing the coordinates point;
Sub_square* get_coord_owner(Coord& point)///new function
{
if(coord_within_grid(point))
{
Coord point_of_origin = source_square.get_top_left();
double dist_x_from_orig = point.x - point_of_origin.x;
double dist_y_from_orig = point.y - point_of_origin.y;
int column_num = (int)(dist_x_from_orig/sub_sqr_length);
int row_num = (int)(dist_y_from_orig/sub_sqr_length);
return &sub_sqr_vector[column_num][row_num];
}
return nullptr; ///coordinates outside the grid
}
void print_grid() const
{
if(sub_sqr_list.empty())
{
std::cout<<"ERROR: Failed to divide your square: \nthe number of squares to be divided into\nshould be sqrt(num_square)==whole number\n\n";
return;
}
int col = 1;
for(auto& column : sub_sqr_list)
{
std::cout<<"\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
std::cout<<"grid column : "<<col<<"\n";
std::cout<<"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
for(auto& coord : column)
{
coord.print_detail();
}
++col;
}
}
};
///driver prog
int main()
{
Coord coord={47,95};///top left x,y coordinates for the main square
std::size_t sub_squares_to_divide = 25, main_sq_side_length=73;
Square big_sq(coord,main_sq_side_length);
Square_grid grid(big_sq,sub_squares_to_divide);
grid.print_grid();
}
|