Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpArray2D.h
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * This class implements an 2D array as a template class.
32  *
33  * Authors:
34  * Fabien Spindler
35  *
36  *****************************************************************************/
37 #ifndef __vpArray2D_h_
38 #define __vpArray2D_h_
39 
40 #include <iostream>
41 #include <ostream>
42 #include <math.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <fstream>
46 #include <sstream>
47 #include <limits>
48 
49 #include <visp3/core/vpConfig.h>
50 #include <visp3/core/vpException.h>
51 
69 template<class Type>
70 class vpArray2D
71 {
72 protected:
74  unsigned int rowNum;
76  unsigned int colNum;
78  Type **rowPtrs;
80  unsigned int dsize;
81 
82 public:
84  Type *data;
85 
86 public:
92  : rowNum(0), colNum(0), rowPtrs(NULL), dsize(0), data(NULL)
93  {}
98  : rowNum(0), colNum(0), rowPtrs(NULL), dsize(0), data(NULL)
99  {
100  resize(A.rowNum, A.colNum);
101  memcpy(data, A.data, rowNum*colNum*sizeof(Type));
102  }
109  vpArray2D<Type>(unsigned int r, unsigned int c)
110  : rowNum(0), colNum(0), rowPtrs(NULL), dsize(0), data(NULL)
111  {
112  resize(r, c);
113  }
121  vpArray2D<Type>(unsigned int r, unsigned int c, Type val)
122  : rowNum(0), colNum(0), rowPtrs(NULL), dsize(0), data(NULL)
123  {
124  resize(r, c);
125  *this = val;
126  }
130  virtual ~vpArray2D<Type>()
131  {
132  if (data != NULL ) {
133  free(data);
134  data=NULL;
135  }
136 
137  if (rowPtrs!=NULL) {
138  free(rowPtrs);
139  rowPtrs=NULL ;
140  }
141  rowNum = colNum = dsize = 0;
142  }
143 
146 
147  Type getMinValue() const;
148 
149  Type getMaxValue() const;
150 
152  inline unsigned int getRows() const { return rowNum ;}
154  inline unsigned int getCols() const { return colNum; }
156  inline unsigned int size() const { return colNum*rowNum; }
167  void resize(const unsigned int nrows, const unsigned int ncols,
168  const bool flagNullify = true)
169  {
170  if ((nrows == rowNum) && (ncols == colNum)) {
171  if (flagNullify && this->data != NULL) {
172  memset(this->data, 0, this->dsize*sizeof(Type));
173  }
174  }
175  else {
176  const bool recopyNeeded = (ncols != this ->colNum);
177  Type * copyTmp = NULL;
178  unsigned int rowTmp = 0, colTmp=0;
179 
180  // Recopy case per case is required if number of cols has changed;
181  // structure of Type array is not the same in this case.
182  if (recopyNeeded && this->data != NULL) {
183  copyTmp = new Type[this->dsize];
184  memcpy (copyTmp, this ->data, sizeof(Type)*this->dsize);
185  rowTmp=this->rowNum; colTmp=this->colNum;
186  }
187 
188  // Reallocation of this->data array
189  this->dsize = nrows*ncols;
190  this->data = (Type*)realloc(this->data, this->dsize*sizeof(Type));
191  if ((NULL == this->data) && (0 != this->dsize)) {
192  if (copyTmp != NULL) delete [] copyTmp;
194  "Memory allocation error when allocating 2D array data")) ;
195  }
196 
197  this->rowPtrs = (Type**)realloc (this->rowPtrs, nrows*sizeof(Type*));
198  if ((NULL == this->rowPtrs) && (0 != this->dsize)) {
199  if (copyTmp != NULL) delete [] copyTmp;
201  "Memory allocation error when allocating 2D array rowPtrs")) ;
202  }
203 
204  // Update rowPtrs
205  {
206  Type **t_= rowPtrs;
207  for (unsigned int i=0; i<dsize; i+=ncols) {
208  *t_++ = this->data + i;
209  }
210  }
211 
212  this->rowNum = nrows; this->colNum = ncols;
213 
214  // Recopy of this->data array values or nullify
215  if (flagNullify) {
216  memset(this->data,0,this->dsize*sizeof(Type));
217  }
218  else if (recopyNeeded && this->rowPtrs != NULL) {
219  // Recopy...
220  const unsigned int minRow = (this->rowNum<rowTmp)?this->rowNum:rowTmp;
221  const unsigned int minCol = (this->colNum<colTmp)?this->colNum:colTmp;
222  for (unsigned int i=0; i<this->rowNum; ++i) {
223  for (unsigned int j=0; j<this->colNum; ++j) {
224  if ((minRow > i) && (minCol > j)) {
225  (*this)[i][j] = copyTmp [i*colTmp+j];
226  }
227  else {
228  (*this)[i][j] = 0;
229  }
230  }
231  }
232  }
233 
234  if (copyTmp != NULL)
235  delete [] copyTmp;
236  }
237  }
240  {
241  for (unsigned int i=0;i<rowNum;i++)
242  for(unsigned int j=0;j<colNum;j++)
243  rowPtrs[i][j] = x;
244 
245  return *this;
246  }
247 
252  {
253  resize(A.rowNum, A.colNum);
254  memcpy(data, A.data, rowNum*colNum*sizeof(Type));
255  return *this;
256  }
257 
259  inline Type *operator[](unsigned int i) { return rowPtrs[i]; }
261  inline Type *operator[](unsigned int i) const {return rowPtrs[i];}
262 
267  friend std::ostream &operator<<(std::ostream &s, const vpArray2D<Type> &A)
268  {
269  if (A.data == NULL)
270  return s;
271  std::ios_base::fmtflags original_flags = s.flags();
272 
273  s.precision(10) ;
274  for (unsigned int i=0;i<A.getRows();i++) {
275  for (unsigned int j=0;j<A.getCols() -1;j++){
276  s << A[i][j] << " ";
277  }
278  // We don't add " " after the last row element
279  s << A[i][A.getCols() -1];
280  // We don't add a \n char on the end of the last array line
281  if (i < A.getRows()-1)
282  s << std::endl;
283  }
284 
285  s.flags(original_flags); // restore s to standard state
286 
287  return s;
288  }
290 
291  //---------------------------------
292  // Inherited array I/O Static Public Member Functions
293  //---------------------------------
308  static bool load(const std::string &filename, vpArray2D<Type> &A,
309  const bool binary = false, char *header = NULL)
310  {
311  std::fstream file;
312 
313  if (!binary)
314  file.open(filename.c_str(), std::fstream::in);
315  else
316  file.open(filename.c_str(), std::fstream::in|std::fstream::binary);
317 
318  if(!file) {
319  file.close();
320  return false;
321  }
322 
323  if (!binary) {
324  std::string h;
325  bool headerIsDecoded = false;
326  do {
327  std::streampos pos = file.tellg();
328  char line[256];
329  file.getline(line, 256);
330  std::string prefix("# ");
331  std::string line_(line);
332  if (line_.compare(0, 2, "# ") == 0) {
333  // Line is a comment
334  // If we are not on the first line, we should add "\n" to the end of the previous line
335  if (pos)
336  h += "\n";
337  h += line_.substr(2); // Remove "# "
338  }
339  else {
340  // rewind before the line
341  file.seekg (pos, file.beg);
342  headerIsDecoded = true;
343  }
344  } while(! headerIsDecoded);
345 
346  if (header != NULL) {
347 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
348  sprintf(header, "%s", h.c_str());
349 #else
350  _snprintf_s(header, h.size()+1, _TRUNCATE, "%s", h.c_str());
351 #endif
352  }
353 
354  unsigned int rows, cols;
355  file >> rows;
356  file >> cols;
357 
358  if (rows >= (std::numeric_limits<unsigned int>::max)()
359  || cols >= (std::numeric_limits<unsigned int>::max)())
360  throw vpException(vpException::badValue, "Array exceed the max size.");
361 
362  A.resize(rows,cols);
363 
364  Type value;
365  for(unsigned int i = 0; i < rows; i++) {
366  for(unsigned int j = 0; j < cols; j++) {
367  file >> value;
368  A[i][j] = value;
369  }
370  }
371  }
372  else {
373  char c='0';
374  std::string h;
375  // Decode header until '\0' char that ends the header string
376  while ((c != '\0')) {
377  file.read(&c,1);
378  h+=c;
379  }
380  if (header != NULL) {
381 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
382  sprintf(header, "%s", h.c_str());
383 #else
384  _snprintf_s(header, h.size()+1, _TRUNCATE, "%s", h.c_str());
385 #endif
386  }
387 
388  unsigned int rows, cols;
389  file.read((char*)&rows, sizeof(unsigned int));
390  file.read((char*)&cols, sizeof(unsigned int));
391  A.resize(rows,cols);
392 
393  Type value;
394  for(unsigned int i = 0; i < rows; i++) {
395  for(unsigned int j = 0; j < cols; j++) {
396  file.read((char*)&value, sizeof(Type));
397  A[i][j] = value;
398  }
399  }
400  }
401 
402  file.close();
403  return true;
404  }
417  static bool loadYAML(const std::string &filename, vpArray2D<Type> &A, char *header = NULL)
418  {
419  std::fstream file;
420 
421  file.open(filename.c_str(), std::fstream::in);
422 
423  if(!file) {
424  file.close();
425  return false;
426  }
427 
428  unsigned int rows = 0,cols = 0;
429  std::string h;
430  std::string line,subs;
431  bool inheader = true;
432  unsigned int i=0, j;
433  unsigned int lineStart = 0;
434 
435  while ( getline (file,line) ) {
436  if(inheader) {
437  if(rows == 0 && line.compare(0,5,"rows:") == 0) {
438  std::stringstream ss(line);
439  ss >> subs;
440  ss >> rows;
441  }
442  else if (cols == 0 && line.compare(0,5,"cols:") == 0) {
443  std::stringstream ss(line);
444  ss >> subs;
445  ss >> cols;
446  }
447  else if (line.compare(0,5,"data:") == 0)
448  inheader = false;
449  else
450  h += line + "\n";
451  }
452  else {
453  // if i == 0, we just got out of the header: initialize matrix dimensions
454  if(i == 0) {
455  if(rows == 0 || cols == 0) {
456  file.close();
457  return false;
458  }
459  A.resize(rows, cols);
460  // get indentation level which is common to all lines
461  lineStart = (unsigned int)line.find("[") + 1;
462  }
463  std::stringstream ss(line.substr(lineStart, line.find("]") - lineStart));
464  j = 0;
465  while(getline(ss, subs, ','))
466  A[i][j++] = atof(subs.c_str());
467  i++;
468  }
469  }
470 
471  if (header != NULL) {
472  std::string h_ = h.substr(0, h.size() - 1); // Remove last '\n' char
473 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
474  sprintf(header, "%s", h_.c_str());
475 #else
476  _snprintf_s(header, h_.size()+1, _TRUNCATE, "%s", h_.c_str());
477 #endif
478  }
479 
480  file.close();
481  return true;
482  }
483 
499  static bool save(const std::string &filename, const vpArray2D<Type> &A,
500  const bool binary = false, const char *header = "")
501  {
502  std::fstream file;
503 
504  if (!binary)
505  file.open(filename.c_str(), std::fstream::out);
506  else
507  file.open(filename.c_str(), std::fstream::out|std::fstream::binary);
508 
509  if(!file) {
510  file.close();
511  return false;
512  }
513 
514  if (!binary) {
515  unsigned int i = 0;
516  file << "# ";
517  while (header[i] != '\0') {
518  file << header[i];
519  if (header[i] == '\n')
520  file << "# ";
521  i++;
522  }
523  file << std::endl;
524  file << A.getRows() << "\t" << A.getCols() << std::endl;
525  file << A << std::endl;
526  }
527  else {
528  int headerSize = 0;
529  while (header[headerSize] != '\0') headerSize++;
530  file.write(header, headerSize+1);
531  unsigned int matrixSize;
532  matrixSize = A.getRows();
533  file.write((char*)&matrixSize, sizeof(unsigned int));
534  matrixSize = A.getCols();
535  file.write((char*)&matrixSize, sizeof(unsigned int));
536  Type value;
537  for(unsigned int i = 0; i < A.getRows(); i++) {
538  for(unsigned int j = 0; j < A.getCols(); j++) {
539  value = A[i][j];
540  file.write((char*)&value, sizeof(Type));
541  }
542  }
543  }
544 
545  file.close();
546  return true;
547  }
588  static bool saveYAML(const std::string &filename, const vpArray2D<Type> &A, const char *header = "")
589  {
590  std::fstream file;
591 
592  file.open(filename.c_str(), std::fstream::out);
593 
594  if(!file) {
595  file.close();
596  return false;
597  }
598 
599  unsigned int i = 0;
600  bool inIndent = false;
601  std::string indent = "";
602  bool checkIndent = true;
603  while (header[i] != '\0') {
604  file << header[i];
605  if(checkIndent) {
606  if (inIndent) {
607  if(header[i] == ' ')
608  indent += " ";
609  else if (indent.length() > 0)
610  checkIndent = false;
611  }
612  if (header[i] == '\n' || (inIndent && header[i] == ' '))
613  inIndent = true;
614  else
615  inIndent = false;
616  }
617  i++;
618  }
619 
620  if(i != 0)
621  file << std::endl;
622  file << "rows: " << A.getRows() << std::endl;
623  file << "cols: " << A.getCols() << std::endl;
624 
625  if(indent.length() == 0)
626  indent = " ";
627 
628  file << "data: " << std::endl;
629  unsigned int j;
630  for(i=0;i<A.getRows();++i)
631  {
632  file << indent << "- [";
633  for(j=0;j<A.getCols()-1;++j)
634  file << A[i][j] << ", ";
635  file << A[i][j] << "]" << std::endl;
636  }
637 
638  file.close();
639  return true;
640  }
642 };
643 
647 template<class Type>
648 Type
650 {
651  Type *dataptr = data;
652  Type min = *dataptr;
653  dataptr++;
654  for (unsigned int i = 0; i < dsize-1; i++)
655  {
656  if (*dataptr < min) min = *dataptr;
657  dataptr++;
658  }
659  return min;
660 }
661 
665 template<class Type>
666 Type
668 {
669  Type *dataptr = data;
670  Type max = *dataptr;
671  dataptr++;
672  for (unsigned int i = 0; i < dsize-1; i++)
673  {
674  if (*dataptr > max) max = *dataptr;
675  dataptr++;
676  }
677  return max;
678 }
679 
680 #endif
static bool save(const std::string &filename, const vpArray2D< Type > &A, const bool binary=false, const char *header="")
Definition: vpArray2D.h:499
static bool saveYAML(const std::string &filename, const vpArray2D< Type > &A, const char *header="")
Definition: vpArray2D.h:588
vpArray2D< Type > & operator=(Type x)
Set all the elements of the array to x.
Definition: vpArray2D.h:239
static bool loadYAML(const std::string &filename, vpArray2D< Type > &A, char *header=NULL)
Definition: vpArray2D.h:417
void resize(const unsigned int nrows, const unsigned int ncols, const bool flagNullify=true)
Definition: vpArray2D.h:167
error that can be emited by ViSP classes.
Definition: vpException.h:73
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:84
Implementation of a generic 2D array used as vase class of matrices and vectors.
Definition: vpArray2D.h:70
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:156
unsigned int getCols() const
Return the number of columns of the 2D array.
Definition: vpArray2D.h:154
unsigned int rowNum
Number of rows in the array.
Definition: vpArray2D.h:74
vpArray2D< Type > & operator=(const vpArray2D< Type > &A)
Definition: vpArray2D.h:251
static bool load(const std::string &filename, vpArray2D< Type > &A, const bool binary=false, char *header=NULL)
Definition: vpArray2D.h:308
unsigned int getRows() const
Return the number of rows of the 2D array.
Definition: vpArray2D.h:152
unsigned int colNum
Number of columns in the array.
Definition: vpArray2D.h:76
Type * operator[](unsigned int i)
Set element using A[i][j] = x.
Definition: vpArray2D.h:259
Type * operator[](unsigned int i) const
Get element using x = A[i][j].
Definition: vpArray2D.h:261
unsigned int dsize
Current array size (rowNum * colNum)
Definition: vpArray2D.h:80
Type getMaxValue() const
Definition: vpArray2D.h:667
Type getMinValue() const
Definition: vpArray2D.h:649
Type ** rowPtrs
Address of the first element of each rows.
Definition: vpArray2D.h:78