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 
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 <cstring> // memcpy
22 #include <map>
23 
24 // Include the MRPT bitmap fonts:
25 #include "mrpt_font_10x20.h"
26 #include "mrpt_font_5x7.h"
27 #include "mrpt_font_6x13.h"
28 #include "mrpt_font_6x13B.h"
29 #include "mrpt_font_6x13O.h"
30 #include "mrpt_font_9x15.h"
31 #include "mrpt_font_9x15B.h"
32 
33 // Japanese fonts?
34 #if MRPT_HAS_ASIAN_FONTS
35 #include "mrpt_font_18x18ja.h"
36 #endif
37 
38 // Each font has a block a data with this header (It's actually zip-compressed
39 // since mrpt >0.6.5)
40 // const uint32_t mrpt_font_9x15B [] = {
41 // 9,15, /* width, height */
42 // 0x0000,0x00FF, /* UNICODE characters range: */
43 
44 using namespace mrpt;
45 using namespace mrpt::img;
46 using namespace std;
47 
48 struct FontData
49 {
50  std::vector<uint8_t> data;
51  bool prepared_to_big_endian = false;
52 };
53 
54 // Each vector is the target place where to uncompress each font.
55 map<string, FontData> list_registered_fonts;
56 bool list_fonts_init = false;
57 
59 {
60  if (!list_fonts_init)
61  {
62  list_registered_fonts.clear();
63 
64 // This was used only once
65 #if 0
66 #define SAVE_COMPRESSED(ARR) \
67  { \
68  list_registered_fonts[#ARR].resize(sizeof(mrpt_font_##ARR)); \
69  memcpy( \
70  &list_registered_fonts[#ARR][0], mrpt_font_##ARR, \
71  sizeof(mrpt_font_##ARR)); \
72  cout << #ARR << " -> " << sizeof(mrpt_font_##ARR) << endl; \
73  CFileGZOutputStream f( \
74  string("mrpt_font_") + string(#ARR) + string(".gz")); \
75  f.WriteBuffer(mrpt_font_##ARR, sizeof(mrpt_font_##ARR)); \
76  /*mrpt::compress::zip::compress( list_registered_fonts[#ARR], f ); */ \
77  }
78 
79  SAVE_COMPRESSED(5x7)
80 // SAVE_COMPRESSED(6x13)
81 // SAVE_COMPRESSED(6x13B)
82 // SAVE_COMPRESSED(6x13O)
83 // SAVE_COMPRESSED(9x15)
84 // SAVE_COMPRESSED(9x15B)
85 // SAVE_COMPRESSED(10x20)
86 
87 #if MRPT_HAS_ASIAN_FONTS
88 // SAVE_COMPRESSED(18x18ja)
89 #endif
90 
91 #endif
92 
93 #if 1 // Normal operation: Load fonts and uncompress them:
94 
95 #define LOAD_FONT(FONTNAME) \
96  { \
97  std::vector<uint8_t> tmpBuf(sizeof(mrpt_font_gz_##FONTNAME)); \
98  memcpy( \
99  &tmpBuf[0], mrpt_font_gz_##FONTNAME, \
100  sizeof(mrpt_font_gz_##FONTNAME)); \
101  mrpt::io::zip::decompress_gz_data_block( \
102  tmpBuf, list_registered_fonts[#FONTNAME].data); \
103  }
104 
105  LOAD_FONT(5x7)
106  LOAD_FONT(6x13)
107  LOAD_FONT(6x13B)
108  LOAD_FONT(6x13O)
109  LOAD_FONT(9x15)
110  LOAD_FONT(9x15B)
111  LOAD_FONT(10x20)
112 #if MRPT_HAS_ASIAN_FONTS
113  LOAD_FONT(18x18ja)
114 #endif
115 
116 #endif
117 
118  list_fonts_init = true;
119  }
120 }
121 
122 /*---------------------------------------------------------------
123  line
124 ---------------------------------------------------------------*/
126  int x0, int y0, int x1, int y1, const mrpt::img::TColor color,
127  unsigned int width, TPenStyle penStyle)
128 {
130  MRPT_UNUSED_PARAM(penStyle);
131 
132  /* // JL: worthy annoying so much?
133  static bool warningFirst = true;
134  if (warningFirst)
135  {
136  warningFirst=false;
137  printf("[CCanvas::line] WARNING: Using default drawing method,
138  ignoring 'width' and 'penStyle'!!\n");
139  }*/
140 
141  float x, y;
142 
143  auto Ax = (float)(x1 - x0);
144  auto Ay = (float)(y1 - y0);
145 
146  // In this cases, there is nothing to do!
147  if (Ax == 0 && Ay == 0) return;
148  if (x0 < 0 && x1 < 0) return;
149  if (y0 < 0 && y1 < 0) return;
150  if (x0 >= (int)getWidth() && x1 >= (int)getWidth()) return;
151  if (y0 >= (int)getHeight() && y1 >= (int)getHeight()) return;
152 
153  float dist = sqrt(square(Ax) + square(Ay));
154  int i, N = (int)ceil(dist);
155 
156  // The N steps to perform next:
157  Ax /= N;
158  Ay /= N;
159  x = (float)x0;
160  y = (float)y0;
161 
162  for (i = 0; i < N; i++)
163  {
164  x += Ax;
165  y += Ay;
166  setPixel((int)x, (int)y, color);
167  } // end for i
168 }
169 
170 /*---------------------------------------------------------------
171  rectangle
172 ---------------------------------------------------------------*/
174  int x0, int y0, int x1, int y1, const mrpt::img::TColor color,
175  unsigned int width)
176 {
177  int w_min = (int)-ceil(((float)width) / 2);
178  int w_max = (int)floor(((float)width) / 2);
179  // Draw "width" rectangles one into another:
180  for (int w = w_min; w <= w_max; w++)
181  {
182  line(x0 - w, y0 - w, x1 + w, y0 - w, color);
183  line(x1 + w, y0 - w, x1 + w, y1 + w, color);
184  line(x1 + w, y1 + w, x0 - w, y1 + w, color);
185  line(x0 - w, y1 + w, x0 - w, y0 - w, color);
186  } // end for "w"
187 }
188 
189 /*****************************************************AJOGD***************************************************/
190 /*---------------------------------------------------------------
191  triangle
192 ---------------------------------------------------------------*/
194  int x0, int y0, int size, const mrpt::img::TColor color, bool inferior,
195  unsigned int width)
196 {
197  int ts = round(0.866 * size);
198  int tc = round(0.5 * size);
199  if (inferior)
200  {
201  line(x0, y0 + size, x0 + ts, y0 - tc, color, width);
202  line(x0, y0 + size, x0 - ts, y0 - tc, color, width);
203  line(x0 + ts, y0 - tc, x0 - ts, y0 - tc, color, width);
204  }
205  else
206  {
207  line(x0, y0 - size, x0 + ts, y0 + tc, color, width);
208  line(x0, y0 - size, x0 - ts, y0 + tc, color, width);
209  line(x0 + ts, y0 + tc, x0 - ts, y0 + tc, color, width);
210  }
211 }
212 /************************************************************************************************************/
213 
214 /*---------------------------------------------------------------
215  filledRectangle
216 ---------------------------------------------------------------*/
218  int x0, int y0, int x1, int y1, const mrpt::img::TColor color)
219 {
220  int x_min = max(x0, 0);
221  int x_max = min(x1, (int)getWidth() - 1);
222  int y_min = max(y0, 0);
223  int y_max = min(y1, (int)getHeight() - 1);
224 
225  for (int y = y_min; y <= y_max; y++)
226  for (int x = x_min; x <= x_max; x++) setPixel(x, y, color);
227 }
228 
229 /*---------------------------------------------------------------
230  selectTextFont
231 ---------------------------------------------------------------*/
233 {
234  init_fonts_list();
235 
236  // Assure list name is in the list:
237  auto it = list_registered_fonts.find(fontName);
238  if (it == list_registered_fonts.end())
239  {
240  // Error
241  cerr << "[CCanvas::selectTextFont] Warning: Unknown font: " << fontName
242  << endl;
243  return;
244  }
245  else
246  {
247  FontData& fd = it->second;
248  m_selectedFontBitmaps = reinterpret_cast<const uint32_t*>(&fd.data[0]);
249  m_selectedFont = fontName;
250 
251 #if MRPT_IS_BIG_ENDIAN
252  // Fix endianness of char tables:
253  if (!fd.prepared_to_big_endian)
254  {
255  fd.prepared_to_big_endian = true; // Only do once
256  uint32_t* ptr = reinterpret_cast<uint32_t*>(&fd.data[0]);
257  for (size_t i = 0; i < fd.data.size() / sizeof(uint32_t); i++)
259  }
260 #endif
261  }
262 }
263 
264 /*---------------------------------------------------------------
265  drawImage
266 ---------------------------------------------------------------*/
268 {
269  MRPT_START
270  ASSERT_(img.getPixelDepth() == mrpt::img::PixelDepth::D8U);
271 
272  int img_lx = img.getWidth();
273  int img_ly = img.getHeight();
274 
275  if (img.isColor())
276  {
277  for (int xx = 0; xx < img_lx; xx++)
278  for (int yy = 0; yy < img_ly; yy++)
279  {
280  auto ptr = img(xx, yy);
281  const int p = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
282  setPixel(x + xx, y + yy, p);
283  }
284  }
285  else
286  {
287  unsigned char c;
288  int col;
289  for (int xx = 0; xx < img_lx; xx++)
290  for (int yy = 0; yy < img_ly; yy++)
291  {
292  c = *((unsigned char*)img(xx, yy));
293  col = c | (c << 8) | (c << 16);
294  setPixel(x + xx, y + yy, col);
295  }
296  }
297 
298  MRPT_END
299 }
300 
301 /*---------------------------------------------------------------
302  drawImage
303 ---------------------------------------------------------------*/
305  int x, int y, const mrpt::img::CImage& img, float rotation, float scale)
306 {
310  MRPT_UNUSED_PARAM(rotation);
312 
313  MRPT_START
314 
315  THROW_EXCEPTION("Not implemented yet!! Try yourself! ;-)");
316 
317  MRPT_END
318 }
319 
321  int x0, int y0, const mrpt::img::TColor color, char type, int size,
322  unsigned int width)
323 {
324  switch (type)
325  {
326  case '+':
327  line(x0 - size, y0, x0 + size, y0, color, width);
328  line(x0, y0 - size, x0, y0 + size, color, width);
329  break;
330  case 's':
331  line(x0 - size, y0 - size, x0 + size, y0 - size, color, width);
332  line(x0 + size, y0 - size, x0 + size, y0 + size, color, width);
333  line(x0 - size, y0 + size, x0 + size, y0 + size, color, width);
334  line(x0 - size, y0 - size, x0 - size, y0 + size, color, width);
335  break;
336  case 'x':
337  line(x0 - size, y0 - size, x0 + size, y0 + size, color, width);
338  line(x0 + size, y0 - size, x0 - size, y0 + size, color, width);
339  break;
340  case ':':
341  line(x0 - size, y0, x0 - 2, y0, color, width);
342  line(x0 + 2, y0, x0 + size, y0, color, width);
343  line(x0, y0 - size, x0, y0 - 2, color, width);
344  line(x0, y0 + 2, x0, y0 + size, color, width);
345  break;
346  default:
347  THROW_EXCEPTION("Unexpected 'type' of cross to be drawn");
348  }
349 }
350 
351 /*---------------------------------------------------------------
352  drawCircle
353 ---------------------------------------------------------------*/
355  int x, int y, int radius, const mrpt::img::TColor& color,
356  unsigned int width)
357 {
358  if (radius < 0) radius = -radius;
359 
360  int nSegments;
361 
362  if (radius == 0)
363  {
364  nSegments = 2;
365  }
366  else
367  {
368  nSegments = int(M_2PI * radius);
369  }
370 
371  int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
372  double ang, Aa = M_2PI / (nSegments - 1);
373  int i;
374 
375  for (i = 0, ang = 0; i < nSegments; i++, ang += Aa)
376  {
377  x2 = round(x + radius * cos(ang));
378  y2 = round(y + radius * sin(ang));
379 
380  if (i > 0) line(x1, y1, x2, y2, color, width);
381 
382  x1 = x2;
383  y1 = y2;
384  } // end for points on ellipse
385 }
386 
387 /*---------------------------------------------------------------
388  textOut
389 ---------------------------------------------------------------*/
391  int x0, int y0, const std::string& str, const mrpt::img::TColor color)
392 {
393  MRPT_START
394 
395  if (!m_selectedFontBitmaps) // First call: load fonts
396  this->selectTextFont("9x15");
397 
398  // Am I an image?
399  bool y_axis_reversed = false;
400  auto* im_image = dynamic_cast<CImage*>(this);
401  if (im_image) y_axis_reversed = !im_image->isOriginTopLeft();
402 
403  // Decode UNICODE string:
404  std::vector<uint16_t> uniStr;
405  mrpt::system::decodeUTF8(str, uniStr);
406 
407  int px = x0;
408  int py = y0;
409 
410  // Char size:
411  int char_w = m_selectedFontBitmaps[0];
412  int char_h = m_selectedFontBitmaps[1];
413 
414  for (unsigned short unichar : uniStr)
415  {
416  // look for the character in the table:
417  const uint32_t* table_ptr = m_selectedFontBitmaps + 2;
418  uint32_t charset_ini = table_ptr[0];
419  uint32_t charset_end = table_ptr[1];
420 
421  while (charset_end)
422  {
423  // Is in this range?
424  if (unichar <= charset_end && unichar >= charset_ini)
425  {
426  // Draw this character:
427  int pyy = y_axis_reversed ? (py + char_h - 1) : py;
428 
429  const uint32_t* char_bitmap =
430  table_ptr + 2 + char_h * (unichar - charset_ini);
431 
432  for (int y = 0; y < char_h;
433  y++, pyy += y_axis_reversed ? -1 : 1)
434  {
435  // Use memcpy() here since directly dereferencing is an
436  // invalid operation in architectures (S390X) where
437  // unaligned accesses are forbiden:
438  uint32_t row;
439  memcpy(&row, char_bitmap, sizeof(row));
440  char_bitmap++;
441  for (int x = 0, pxx = px; x < char_w; x++, pxx++)
442  if (!!(row & (1 << x))) setPixel(pxx, pyy, color);
443  }
444 
445  // Advance the raster cursor:
446  px += char_w;
447 
448  // Next char!
449  break;
450  }
451  else
452  {
453  // No: Move to the next block and keep searching:
454  uint32_t n_chars = charset_end - charset_ini + 1;
455  table_ptr += 2 /* Header */ + n_chars * char_h;
456 
457  // get new block header:
458  charset_ini = table_ptr[0];
459  charset_end = table_ptr[1];
460  }
461  }
462  // Char not in the font!
463  }
464 
465  MRPT_END
466 }
467 
469  const mrpt::math::CMatrixFixed<double, 2, 2>& cov2D, const double mean_x,
470  const double mean_y, double confIntervalStds,
471  const mrpt::img::TColor& color, unsigned int width, int nEllipsePoints)
472 {
473  MRPT_START
474  int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
475  double ang;
477  std::vector<double> eVals;
478  int i;
479 
480  // Compute the eigen-vectors & values:
481  cov2D.eig(eigVec, eVals);
482  eigVals.setDiagonal(eVals);
483 
484  eigVals.asEigen() = eigVals.array().sqrt().matrix();
485 
487  M.asEigen() = eigVals.asEigen() * eigVec.transpose();
488 
489  // Compute the points of the 2D ellipse:
490  for (i = 0, ang = 0; i < nEllipsePoints;
491  i++, ang += (M_2PI / (nEllipsePoints - 1)))
492  {
493  double ccos = cos(ang);
494  double ssin = sin(ang);
495 
496  x2 = round(
497  mean_x + confIntervalStds * (ccos * M(0, 0) + ssin * M(1, 0)));
498  y2 = round(
499  mean_y + confIntervalStds * (ccos * M(0, 1) + ssin * M(1, 1)));
500 
501  if (i > 0) line(x1, y1, x2, y2, color, width);
502 
503  x1 = x2;
504  y1 = y2;
505  } // end for points on ellipse
506 
507  MRPT_END_WITH_CLEAN_UP(std::cout << "Covariance matrix leading to error is:"
508  << std::endl
509  << cov2D << std::endl;);
510 }
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:354
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:125
#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:56
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:193
void reverseBytesInPlace(bool &v_in_out)
Reverse the order of the bytes of a given type (useful for transforming btw little/big endian) ...
GLenum GLsizei width
Definition: glext.h:3535
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4199
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:232
T square(const T x)
Inline function for the square of a number.
virtual void filledRectangle(int x0, int y0, int x1, int y1, const mrpt::img::TColor color)
Draws a filled rectangle.
Definition: CCanvas.cpp:217
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:173
map< string, FontData > list_registered_fonts
Definition: CCanvas.cpp:55
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:468
std::vector< uint8_t > data
Definition: CCanvas.cpp:50
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:320
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:884
void init_fonts_list()
Definition: CCanvas.cpp:58
bool prepared_to_big_endian
Definition: CCanvas.cpp:51
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:390
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:267
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
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
Definition: os.cpp:358
#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:24



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 45d659fbb Tue Dec 10 18:21:14 2019 +0100 at mar dic 10 18:30:09 CET 2019