MRPT  1.9.9
CCanvas.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "img-precomp.h" // Precompiled headers
11 
12 #include <mrpt/core/bit_cast.h>
13 #include <mrpt/core/round.h>
14 #include <mrpt/img/CCanvas.h>
15 #include <mrpt/img/CImage.h>
16 #include <mrpt/io/zip.h>
17 #include <mrpt/math/CMatrixFixed.h>
18 #include <mrpt/system/os.h>
20 #include <Eigen/Dense>
21 #include <map>
22 
23 // Include the MRPT bitmap fonts:
24 #include "mrpt_font_10x20.h"
25 #include "mrpt_font_5x7.h"
26 #include "mrpt_font_6x13.h"
27 #include "mrpt_font_6x13B.h"
28 #include "mrpt_font_6x13O.h"
29 #include "mrpt_font_9x15.h"
30 #include "mrpt_font_9x15B.h"
31 
32 // Japanese fonts?
33 #if MRPT_HAS_ASIAN_FONTS
34 #include "mrpt_font_18x18ja.h"
35 #endif
36 
37 // Each font has a block a data with this header (It's actually zip-compressed
38 // since mrpt >0.6.5)
39 // const uint32_t mrpt_font_9x15B [] = {
40 // 9,15, /* width, height */
41 // 0x0000,0x00FF, /* UNICODE characters range: */
42 
43 using namespace mrpt;
44 using namespace mrpt::img;
45 using namespace std;
46 
47 // map<string,const uint32_t*> list_registered_fonts;
48 map<string, std::vector<uint8_t>>
49  list_registered_fonts; // Each vector is the target
50 // place where to uncompress
51 // each font.
52 bool list_fonts_init = false;
53 
55 {
56  if (!list_fonts_init)
57  {
58  list_registered_fonts.clear();
59 
60 // This was used only once
61 #if 0
62 #define SAVE_COMPRESSED(ARR) \
63  { \
64  list_registered_fonts[#ARR].resize(sizeof(mrpt_font_##ARR)); \
65  memcpy( \
66  &list_registered_fonts[#ARR][0], mrpt_font_##ARR, \
67  sizeof(mrpt_font_##ARR)); \
68  cout << #ARR << " -> " << sizeof(mrpt_font_##ARR) << endl; \
69  CFileGZOutputStream f( \
70  string("mrpt_font_") + string(#ARR) + string(".gz")); \
71  f.WriteBuffer(mrpt_font_##ARR, sizeof(mrpt_font_##ARR)); \
72  /*mrpt::compress::zip::compress( list_registered_fonts[#ARR], f ); */ \
73  }
74 
75  SAVE_COMPRESSED(5x7)
76 // SAVE_COMPRESSED(6x13)
77 // SAVE_COMPRESSED(6x13B)
78 // SAVE_COMPRESSED(6x13O)
79 // SAVE_COMPRESSED(9x15)
80 // SAVE_COMPRESSED(9x15B)
81 // SAVE_COMPRESSED(10x20)
82 
83 #if MRPT_HAS_ASIAN_FONTS
84 // SAVE_COMPRESSED(18x18ja)
85 #endif
86 
87 #endif
88 
89 #if 1 // Normal operation: Load fonts and uncompress them:
90 
91 #define LOAD_FONT(FONTNAME) \
92  { \
93  std::vector<uint8_t> tmpBuf(sizeof(mrpt_font_gz_##FONTNAME)); \
94  memcpy( \
95  &tmpBuf[0], mrpt_font_gz_##FONTNAME, \
96  sizeof(mrpt_font_gz_##FONTNAME)); \
97  mrpt::io::zip::decompress_gz_data_block( \
98  tmpBuf, list_registered_fonts[#FONTNAME]); \
99  }
100 
101  LOAD_FONT(5x7)
102  LOAD_FONT(6x13)
103  LOAD_FONT(6x13B)
104  LOAD_FONT(6x13O)
105  LOAD_FONT(9x15)
106  LOAD_FONT(9x15B)
107  LOAD_FONT(10x20)
108 #if MRPT_HAS_ASIAN_FONTS
109  LOAD_FONT(18x18ja)
110 #endif
111 
112 #endif
113 
114  list_fonts_init = true;
115  }
116 }
117 
118 /*---------------------------------------------------------------
119  line
120 ---------------------------------------------------------------*/
122  int x0, int y0, int x1, int y1, const mrpt::img::TColor color,
123  unsigned int width, TPenStyle penStyle)
124 {
126  MRPT_UNUSED_PARAM(penStyle);
127 
128  /* // JL: worthy annoying so much?
129  static bool warningFirst = true;
130  if (warningFirst)
131  {
132  warningFirst=false;
133  printf("[CCanvas::line] WARNING: Using default drawing method,
134  ignoring 'width' and 'penStyle'!!\n");
135  }*/
136 
137  float x, y;
138 
139  auto Ax = (float)(x1 - x0);
140  auto Ay = (float)(y1 - y0);
141 
142  // In this cases, there is nothing to do!
143  if (Ax == 0 && Ay == 0) return;
144  if (x0 < 0 && x1 < 0) return;
145  if (y0 < 0 && y1 < 0) return;
146  if (x0 >= (int)getWidth() && x1 >= (int)getWidth()) return;
147  if (y0 >= (int)getHeight() && y1 >= (int)getHeight()) return;
148 
149  float dist = sqrt(square(Ax) + square(Ay));
150  int i, N = (int)ceil(dist);
151 
152  // The N steps to perform next:
153  Ax /= N;
154  Ay /= N;
155  x = (float)x0;
156  y = (float)y0;
157 
158  for (i = 0; i < N; i++)
159  {
160  x += Ax;
161  y += Ay;
162  setPixel((int)x, (int)y, color);
163  } // end for i
164 }
165 
166 /*---------------------------------------------------------------
167  rectangle
168 ---------------------------------------------------------------*/
170  int x0, int y0, int x1, int y1, const mrpt::img::TColor color,
171  unsigned int width)
172 {
173  int w_min = (int)-ceil(((float)width) / 2);
174  int w_max = (int)floor(((float)width) / 2);
175  // Draw "width" rectangles one into another:
176  for (int w = w_min; w <= w_max; w++)
177  {
178  line(x0 - w, y0 - w, x1 + w, y0 - w, color);
179  line(x1 + w, y0 - w, x1 + w, y1 + w, color);
180  line(x1 + w, y1 + w, x0 - w, y1 + w, color);
181  line(x0 - w, y1 + w, x0 - w, y0 - w, color);
182  } // end for "w"
183 }
184 
185 /*****************************************************AJOGD***************************************************/
186 /*---------------------------------------------------------------
187  triangle
188 ---------------------------------------------------------------*/
190  int x0, int y0, int size, const mrpt::img::TColor color, bool inferior,
191  unsigned int width)
192 {
193  int ts = round(0.866 * size);
194  int tc = round(0.5 * size);
195  if (inferior)
196  {
197  line(x0, y0 + size, x0 + ts, y0 - tc, color, width);
198  line(x0, y0 + size, x0 - ts, y0 - tc, color, width);
199  line(x0 + ts, y0 - tc, x0 - ts, y0 - tc, color, width);
200  }
201  else
202  {
203  line(x0, y0 - size, x0 + ts, y0 + tc, color, width);
204  line(x0, y0 - size, x0 - ts, y0 + tc, color, width);
205  line(x0 + ts, y0 + tc, x0 - ts, y0 + tc, color, width);
206  }
207 }
208 /************************************************************************************************************/
209 
210 /*---------------------------------------------------------------
211  filledRectangle
212 ---------------------------------------------------------------*/
214  int x0, int y0, int x1, int y1, const mrpt::img::TColor color)
215 {
216  int x_min = max(x0, 0);
217  int x_max = min(x1, (int)getWidth() - 1);
218  int y_min = max(y0, 0);
219  int y_max = min(y1, (int)getHeight() - 1);
220 
221  for (int y = y_min; y <= y_max; y++)
222  for (int x = x_min; x <= x_max; x++) setPixel(x, y, color);
223 }
224 
225 /*---------------------------------------------------------------
226  selectTextFont
227 ---------------------------------------------------------------*/
229 {
230  init_fonts_list();
231 
232  // Assure list name is in the list:
233  auto it = list_registered_fonts.find(fontName);
234  if (it == list_registered_fonts.end())
235  {
236  // Error
237  cerr << "[CCanvas::selectTextFont] Warning: Unknown font: " << fontName
238  << endl;
239  return;
240  }
241  else
242  {
243  m_selectedFontBitmaps =
244  reinterpret_cast<const uint32_t*>(&it->second[0]);
245  m_selectedFont = fontName;
246  }
247 }
248 
249 /*---------------------------------------------------------------
250  drawImage
251 ---------------------------------------------------------------*/
253 {
254  MRPT_START
255  ASSERT_(img.getPixelDepth() == mrpt::img::PixelDepth::D8U);
256 
257  int img_lx = img.getWidth();
258  int img_ly = img.getHeight();
259 
260  if (img.isColor())
261  {
262  for (int xx = 0; xx < img_lx; xx++)
263  for (int yy = 0; yy < img_ly; yy++)
264  {
265  auto ptr = img(xx, yy);
266  const int p = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
267  setPixel(x + xx, y + yy, p);
268  }
269  }
270  else
271  {
272  unsigned char c;
273  int col;
274  for (int xx = 0; xx < img_lx; xx++)
275  for (int yy = 0; yy < img_ly; yy++)
276  {
277  c = *((unsigned char*)img(xx, yy));
278  col = c | (c << 8) | (c << 16);
279  setPixel(x + xx, y + yy, col);
280  }
281  }
282 
283  MRPT_END
284 }
285 
286 /*---------------------------------------------------------------
287  drawImage
288 ---------------------------------------------------------------*/
290  int x, int y, const mrpt::img::CImage& img, float rotation, float scale)
291 {
295  MRPT_UNUSED_PARAM(rotation);
297 
298  MRPT_START
299 
300  THROW_EXCEPTION("Not implemented yet!! Try yourself! ;-)");
301 
302  MRPT_END
303 }
304 
306  int x0, int y0, const mrpt::img::TColor color, char type, int size,
307  unsigned int width)
308 {
309  switch (type)
310  {
311  case '+':
312  line(x0 - size, y0, x0 + size, y0, color, width);
313  line(x0, y0 - size, x0, y0 + size, color, width);
314  break;
315  case 's':
316  line(x0 - size, y0 - size, x0 + size, y0 - size, color, width);
317  line(x0 + size, y0 - size, x0 + size, y0 + size, color, width);
318  line(x0 - size, y0 + size, x0 + size, y0 + size, color, width);
319  line(x0 - size, y0 - size, x0 - size, y0 + size, color, width);
320  break;
321  case 'x':
322  line(x0 - size, y0 - size, x0 + size, y0 + size, color, width);
323  line(x0 + size, y0 - size, x0 - size, y0 + size, color, width);
324  break;
325  case ':':
326  line(x0 - size, y0, x0 - 2, y0, color, width);
327  line(x0 + 2, y0, x0 + size, y0, color, width);
328  line(x0, y0 - size, x0, y0 - 2, color, width);
329  line(x0, y0 + 2, x0, y0 + size, color, width);
330  break;
331  default:
332  THROW_EXCEPTION("Unexpected 'type' of cross to be drawn");
333  }
334 }
335 
336 /*---------------------------------------------------------------
337  drawCircle
338 ---------------------------------------------------------------*/
340  int x, int y, int radius, const mrpt::img::TColor& color,
341  unsigned int width)
342 {
343  if (radius < 0) radius = -radius;
344 
345  int nSegments;
346 
347  if (radius == 0)
348  {
349  nSegments = 2;
350  }
351  else
352  {
353  nSegments = int(M_2PI * radius);
354  }
355 
356  int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
357  double ang, Aa = M_2PI / (nSegments - 1);
358  int i;
359 
360  for (i = 0, ang = 0; i < nSegments; i++, ang += Aa)
361  {
362  x2 = round(x + radius * cos(ang));
363  y2 = round(y + radius * sin(ang));
364 
365  if (i > 0) line(x1, y1, x2, y2, color, width);
366 
367  x1 = x2;
368  y1 = y2;
369  } // end for points on ellipse
370 }
371 
372 /*---------------------------------------------------------------
373  textOut
374 ---------------------------------------------------------------*/
376  int x0, int y0, const std::string& str, const mrpt::img::TColor color)
377 {
378  MRPT_START
379 
380  if (!m_selectedFontBitmaps) // First call: load fonts
381  this->selectTextFont("9x15");
382 
383  // Am I an image?
384  bool y_axis_reversed = false;
385  auto* im_image = dynamic_cast<CImage*>(this);
386  if (im_image) y_axis_reversed = !im_image->isOriginTopLeft();
387 
388  // Decode UNICODE string:
389  std::vector<uint16_t> uniStr;
390  mrpt::system::decodeUTF8(str, uniStr);
391 
392  int px = x0;
393  int py = y0;
394 
395  // Char size:
396  uint32_t char_w = m_selectedFontBitmaps[0];
397  uint32_t char_h = m_selectedFontBitmaps[1];
398 
399  for (unsigned short unichar : uniStr)
400  {
401  // look for the character in the table:
402  const uint32_t* table_ptr = m_selectedFontBitmaps + 2;
403  uint32_t charset_ini = table_ptr[0];
404  uint32_t charset_end = table_ptr[1];
405 
406  while (charset_end)
407  {
408  // Is in this range?
409  if (unichar <= charset_end && unichar >= charset_ini)
410  {
411  // Draw this character:
412  unsigned pyy = y_axis_reversed ? (py + char_h - 1) : py;
413  unsigned pxx;
414 
415  const uint32_t* char_bitmap =
416  table_ptr + 2 + char_h * (unichar - charset_ini);
417 
418  for (unsigned y = 0; y < char_h;
419  y++, pyy += y_axis_reversed ? -1 : 1)
420  {
421  pxx = px;
422  const uint32_t& row = *char_bitmap++;
423  for (unsigned x = 0; x < char_w; x++, pxx++)
424  if (row & (1 << x)) setPixel(pxx, pyy, color);
425  }
426 
427  // Advance the raster cursor:
428  px += char_w;
429 
430  // Next char!
431  break;
432  }
433  else
434  {
435  // No: Move to the next block and keep searching:
436  uint32_t n_chars = charset_end - charset_ini + 1;
437  table_ptr += 2 /* Header */ + n_chars * char_h;
438 
439  // get new block header:
440  charset_ini = table_ptr[0];
441  charset_end = table_ptr[1];
442  }
443  }
444  // Char not in the font!
445  }
446 
447  MRPT_END
448 }
449 
451  const mrpt::math::CMatrixFixed<double, 2, 2>& cov2D, const double mean_x,
452  const double mean_y, double confIntervalStds,
453  const mrpt::img::TColor& color, unsigned int width, int nEllipsePoints)
454 {
455  MRPT_START
456  int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
457  double ang;
459  std::vector<double> eVals;
460  int i;
461 
462  // Compute the eigen-vectors & values:
463  cov2D.eig(eigVec, eVals);
464  eigVals.setDiagonal(eVals);
465 
466  eigVals.asEigen() = eigVals.array().sqrt().matrix();
467 
469  M.asEigen() = eigVals.asEigen() * eigVec.transpose();
470 
471  // Compute the points of the 2D ellipse:
472  for (i = 0, ang = 0; i < nEllipsePoints;
473  i++, ang += (M_2PI / (nEllipsePoints - 1)))
474  {
475  double ccos = cos(ang);
476  double ssin = sin(ang);
477 
478  x2 = round(
479  mean_x + confIntervalStds * (ccos * M(0, 0) + ssin * M(1, 0)));
480  y2 = round(
481  mean_y + confIntervalStds * (ccos * M(0, 1) + ssin * M(1, 1)));
482 
483  if (i > 0) line(x1, y1, x2, y2, color, width);
484 
485  x1 = x2;
486  y1 = y2;
487  } // end for points on ellipse
488 
489  MRPT_END_WITH_CLEAN_UP(std::cout << "Covariance matrix leading to error is:"
490  << std::endl
491  << cov2D << std::endl;);
492 }
bool eig(CMatrixFixed< T, ROWS, COLS > &eVecs, std::vector< T > &eVals, bool sorted=true) const
Computes the eigenvectors and eigenvalues for a square, general matrix.
virtual void drawCircle(int x, int y, int radius, const mrpt::img::TColor &color=mrpt::img::TColor(255, 255, 255), unsigned int width=1)
Draws a circle of a given radius.
Definition: CCanvas.cpp:339
A compile-time fixed-size numeric matrix container.
Definition: CMatrixFixed.h:33
#define MRPT_START
Definition: exceptions.h:241
TPenStyle
Definition of pen styles.
Definition: CCanvas.h:55
#define M_2PI
Definition: common.h:58
virtual void line(int x0, int y0, int x1, int y1, const mrpt::img::TColor color, unsigned int width=1, TPenStyle penStyle=psSolid)
Draws a line.
Definition: CCanvas.cpp:121
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:6604
bool list_fonts_init
Definition: CCanvas.cpp:52
void decodeUTF8(const std::string &strUTF8, std::vector< uint16_t > &out_uniStr)
Decodes a UTF-8 string into an UNICODE string.
STL namespace.
#define MRPT_END_WITH_CLEAN_UP(stuff)
Definition: exceptions.h:247
void triangle(int x0, int y0, int size, const mrpt::img::TColor color, bool inferior=true, unsigned int width=1)
Draws a triangle.
Definition: CCanvas.cpp:189
GLenum GLsizei width
Definition: glext.h:3535
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4199
T square(const T x)
Inline function for the square of a number.
GLuint color
Definition: glext.h:8459
#define LOAD_FONT(FONTNAME)
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:120
const GLfloat * tc
Definition: glext.h:6459
virtual void selectTextFont(const std::string &fontName)
Select the current font used when drawing text.
Definition: CCanvas.cpp:228
virtual void filledRectangle(int x0, int y0, int x1, int y1, const mrpt::img::TColor color)
Draws a filled rectangle.
Definition: CCanvas.cpp:213
const GLubyte * c
Definition: glext.h:6406
GLint GLvoid * img
Definition: glext.h:3769
void rectangle(int x0, int y0, int x1, int y1, const mrpt::img::TColor color, unsigned int width=1)
Draws a rectangle (an empty rectangle, without filling)
Definition: CCanvas.cpp:169
GLsizei const GLchar ** string
Definition: glext.h:4116
void ellipseGaussian(const mrpt::math::CMatrixFixed< double, 2, 2 > &cov2D, const double mean_x, const double mean_y, double confIntervalStds=2, const mrpt::img::TColor &color=mrpt::img::TColor(255, 255, 255), unsigned int width=1, int nEllipsePoints=20)
Draws an ellipse representing a given confidence interval of a 2D Gaussian distribution.
Definition: CCanvas.cpp:450
map< string, std::vector< uint8_t > > list_registered_fonts
Definition: CCanvas.cpp:49
void drawMark(int x0, int y0, const mrpt::img::TColor color, char type, int size=5, unsigned int width=1)
Draw a mark.
Definition: CCanvas.cpp:305
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
bool isOriginTopLeft() const
Returns true (as of MRPT v2.0.0, it&#39;s fixed)
Definition: CImage.cpp:916
void init_fonts_list()
Definition: CCanvas.cpp:54
GLenum GLenum GLvoid * row
Definition: glext.h:3580
#define MRPT_END
Definition: exceptions.h:245
EIGEN_MAP asEigen()
Get as an Eigen-compatible Eigen::Map object.
Definition: CMatrixFixed.h:251
GLenum GLint GLint y
Definition: glext.h:3542
virtual void textOut(int x0, int y0, const std::string &str, const mrpt::img::TColor color)
Renders 2D text using bitmap fonts.
Definition: CCanvas.cpp:375
virtual void drawImage(int x, int y, const mrpt::img::CImage &img)
Draws an image as a bitmap at a given position.
Definition: CCanvas.cpp:252
GLsizeiptr size
Definition: glext.h:3934
A RGB color - 8bit.
Definition: TColor.h:20
GLenum GLint x
Definition: glext.h:3542
double getHeight(const TPolygon3D &p, const TPoint3D &c)
GLfloat GLfloat p
Definition: glext.h:6398
GLuint GLuint GLsizei GLenum type
Definition: glext.h:3532
void setDiagonal(const std::size_t N, const T value)
Resize to NxN, set all entries to zero, except the main diagonal which is set to value ...
Definition: MatrixBase.h:34
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:147
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
Definition: common.h:186
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:23



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: dad381fd7 Sun Oct 20 13:36:46 2019 +0200 at dom oct 20 13:40:10 CEST 2019