24 #ifndef COM_DAFER45_TBTK_CANVAS
25 #define COM_DAFER45_TBTK_CANVAS
30 #include <initializer_list>
32 #include <opencv2/core/core.hpp>
33 #include <opencv2/highgui/highgui.hpp>
37 template<
typename CoordinateType>
43 RGBA(
char r,
char g,
char b,
char a = 0);
54 Pixel(
unsigned int x,
unsigned int y);
61 Canvas(
unsigned int width,
unsigned int height);
67 void setOrigin(CoordinateType x, CoordinateType y);
71 std::initializer_list<std::initializer_list<CoordinateType>> basisVectors
75 void drawPixel(
const RGBA &rgba, CoordinateType x, CoordinateType y);
78 void drawCircle(
const RGBA &rgba, CoordinateType x, CoordinateType y, CoordinateType radius);
81 void save(std::string filename)
const;
87 CoordinateType origin[2];
90 CoordinateType basisVectors[2][2];
96 Pixel getPixel(CoordinateType x, CoordinateType y);
99 void calculateNorms();
102 template<
typename CoordinateType>
103 Canvas<CoordinateType>::~Canvas(){
106 template<
typename CoordinateType>
107 void Canvas<CoordinateType>::setOrigin(CoordinateType x, CoordinateType y){
113 inline void Canvas<unsigned int>::drawPixel(
118 if(x < (
unsigned int)data.cols && y < (
unsigned int)data.rows){
119 data.at<cv::Vec3b>(y, x)[0] = rgba.b;
120 data.at<cv::Vec3b>(y, x)[1] = rgba.g;
121 data.at<cv::Vec3b>(y, x)[2] = rgba.r;
126 inline void Canvas<double>::drawPixel(
131 Pixel p = getPixel(x, y);
133 && p.x < (
unsigned int)data.cols
135 && p.y < (
unsigned int)data.rows
137 data.at<cv::Vec3b>(p.y, p.x)[0] = rgba.b;
138 data.at<cv::Vec3b>(p.y, p.x)[1] = rgba.g;
139 data.at<cv::Vec3b>(p.y, p.x)[2] = rgba.r;
144 inline void Canvas<unsigned int>::drawCircle(
151 cv::circle(data, cv::Point(x, y), radius, cv::Scalar(rgba.r, rgba.g, rgba.b), CV_FILLED, 8, 0);
156 inline void Canvas<double>::drawCircle(
162 Pixel p = getPixel(x, y);
168 cv::circle(data, cv::Point(p.x, p.y), (
int)radius, cv::Scalar(rgba.r, rgba.g, rgba.b));
172 template<
typename CoordinateType>
173 inline typename Canvas<CoordinateType>::Pixel Canvas<CoordinateType>::getPixel(
177 double projections[2];
178 for(
unsigned int n = 0; n < 2; n++){
180 = ((double)x - (
double)origin[0])*((
double)basisVectors[n][0])
181 + ((
double)y - (double)origin[1])*((double)basisVectors[n][1]);
182 projections[n] /= norms[n]*norms[n];
185 return Pixel(data.cols*projections[0], data.rows*projections[1]);
188 template<
typename CoordinateType>
189 inline void Canvas<CoordinateType>::setBasisVectors(
190 std::initializer_list<std::initializer_list<CoordinateType>> basisVectors
193 basisVectors.size() == 2,
194 "Canvas::setBasisVectors()",
195 "'basisVectors' must contain two vectors.",
198 for(
unsigned int n = 0; n < 2; n++){
200 (basisVectors.begin() + n)->size() == 2,
201 "Canvas::setBasisVectors",
202 "Each basis vector must have two components, but basis"
203 <<
" vector " << n <<
" has "
204 << (basisVectors.begin() + n)->size()
210 for(
unsigned int n = 0; n < 2; n++)
211 for(
unsigned int c = 0; c < 2; c++)
212 this->basisVectors[n][c] = *((basisVectors.begin() + n)->begin() + c);
217 template<
typename CoordinateType>
218 inline void Canvas<CoordinateType>::save(std::string filename)
const{
219 imwrite(filename, data);
222 template<
typename CoordinateType>
223 inline Canvas<CoordinateType>::RGBA::RGBA(
char r,
char g,
char b,
char a){
230 template<
typename CoordinateType>
231 inline Canvas<CoordinateType>::Pixel::Pixel(
unsigned int x,
unsigned int y){
236 template<
typename CoordinateType>
237 inline void Canvas<CoordinateType>::calculateNorms(){
238 for(
unsigned int n = 0; n < 2; n++){
240 for(
unsigned int c = 0; c < 2; c++)
241 norms[n] += basisVectors[n][c]*basisVectors[n][c];
242 norms[n] =
sqrt(norms[n]);