Visual Servoing Platform  version 3.0.0
vpArray2D.h
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 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  else {
324  if (!binary) {
325  char c='0';
326  std::string h;
327  while ((c != '\0') && (c != '\n')) {
328  file.read(&c,1);
329  h+=c;
330  }
331  if (header != NULL)
332  strncpy(header, h.c_str(), h.size() + 1);
333 
334  unsigned int rows, cols;
335  file >> rows;
336  file >> cols;
337 
338  if (rows > (std::numeric_limits<unsigned int>::max)()
339  || cols > (std::numeric_limits<unsigned int>::max)())
340  throw vpException(vpException::badValue, "Array exceed the max size.");
341 
342  A.resize(rows,cols);
343 
344  Type value;
345  for(unsigned int i = 0; i < rows; i++) {
346  for(unsigned int j = 0; j < cols; j++) {
347  file >> value;
348  A[i][j] = value;
349  }
350  }
351  }
352  else {
353  char c='0';
354  std::string h;
355  while ((c != '\0') && (c != '\n')) {
356  file.read(&c,1);
357  h+=c;
358  }
359  if (header != NULL)
360  strncpy(header, h.c_str(), h.size() + 1);
361 
362  unsigned int rows, cols;
363  file.read((char*)&rows,sizeof(unsigned int));
364  file.read((char*)&cols,sizeof(unsigned int));
365  A.resize(rows,cols);
366 
367  Type value;
368  for(unsigned int i = 0; i < rows; i++) {
369  for(unsigned int j = 0; j < cols; j++) {
370  file.read((char*)&value,sizeof(Type));
371  A[i][j] = value;
372  }
373  }
374  }
375  }
376 
377  file.close();
378  return true;
379  }
392  static bool loadYAML(const std::string &filename, vpArray2D<Type> &A, char *header = NULL)
393  {
394  std::fstream file;
395 
396  file.open(filename.c_str(), std::fstream::in);
397 
398  if(!file) {
399  file.close();
400  return false;
401  }
402 
403  unsigned int rows = 0,cols = 0;
404  std::string h;
405  std::string line,subs;
406  bool inheader = true;
407  unsigned int i=0, j;
408  unsigned int lineStart = 0;
409 
410  while ( getline (file,line) ) {
411  if(inheader) {
412  if(rows == 0 && line.compare(0,5,"rows:") == 0) {
413  std::stringstream ss(line);
414  ss >> subs;
415  ss >> rows;
416  }
417  else if (cols == 0 && line.compare(0,5,"cols:") == 0) {
418  std::stringstream ss(line);
419  ss >> subs;
420  ss >> cols;
421  }
422  else if (line.compare(0,5,"data:") == 0)
423  inheader = false;
424  else
425  h += line + "\n";
426  }
427  else {
428  // if i == 0, we just got out of the header: initialize matrix dimensions
429  if(i == 0) {
430  if(rows == 0 || cols == 0) {
431  file.close();
432  return false;
433  }
434  A.resize(rows, cols);
435  // get indentation level which is common to all lines
436  lineStart = (unsigned int)line.find("[") + 1;
437  }
438  std::stringstream ss(line.substr(lineStart, line.find("]") - lineStart));
439  j = 0;
440  while(getline(ss, subs, ','))
441  A[i][j++] = atof(subs.c_str());
442  i++;
443  }
444  }
445 
446  if (header != NULL)
447  strncpy(header, h.substr(0,h.length()-1).c_str(), h.size());
448 
449  file.close();
450  return true;
451  }
452 
468  static bool save(const std::string &filename, const vpArray2D<Type> &A,
469  const bool binary = false, const char *header = "")
470  {
471  std::fstream file;
472 
473  if (!binary)
474  file.open(filename.c_str(), std::fstream::out);
475  else
476  file.open(filename.c_str(), std::fstream::out|std::fstream::binary);
477 
478  if(!file) {
479  file.close();
480  return false;
481  }
482 
483  else {
484  if (!binary) {
485  unsigned int i = 0;
486  file << "# ";
487  while (header[i] != '\0') {
488  file << header[i];
489  if (header[i] == '\n')
490  file << "# ";
491  i++;
492  }
493  file << '\0';
494  file << std::endl;
495  file << A.getRows() << "\t" << A.getCols() << std::endl;
496  file << A << std::endl;
497  }
498  else {
499  int headerSize = 0;
500  while (header[headerSize] != '\0') headerSize++;
501  file.write(header,headerSize+1);
502  unsigned int matrixSize;
503  matrixSize = A.getRows();
504  file.write((char*)&matrixSize,sizeof(int));
505  matrixSize = A.getCols();
506  file.write((char*)&matrixSize,sizeof(int));
507  Type value;
508  for(unsigned int i = 0; i < A.getRows(); i++) {
509  for(unsigned int j = 0; j < A.getCols(); j++) {
510  value = A[i][j];
511  file.write((char*)&value,sizeof(Type));
512  }
513  }
514  }
515  }
516 
517  file.close();
518  return true;
519  }
560  static bool saveYAML(const std::string &filename, const vpArray2D<Type> &A, const char *header = "")
561  {
562  std::fstream file;
563 
564  file.open(filename.c_str(), std::fstream::out);
565 
566  if(!file) {
567  file.close();
568  return false;
569  }
570 
571  unsigned int i = 0;
572  bool inIndent = false;
573  std::string indent = "";
574  bool checkIndent = true;
575  while (header[i] != '\0') {
576  file << header[i];
577  if(checkIndent) {
578  if (inIndent) {
579  if(header[i] == ' ')
580  indent += " ";
581  else if (indent.length() > 0)
582  checkIndent = false;
583  }
584  if (header[i] == '\n' || (inIndent && header[i] == ' '))
585  inIndent = true;
586  else
587  inIndent = false;
588  }
589  i++;
590  }
591 
592  if(i != 0)
593  file << std::endl;
594  file << "rows: " << A.getRows() << std::endl;
595  file << "cols: " << A.getCols() << std::endl;
596 
597  if(indent.length() == 0)
598  indent = " ";
599 
600  file << "data: " << std::endl;
601  unsigned int j;
602  for(i=0;i<A.getRows();++i)
603  {
604  file << indent << "- [";
605  for(j=0;j<A.getCols()-1;++j)
606  file << A[i][j] << ", ";
607  file << A[i][j] << "]" << std::endl;
608  }
609 
610  file.close();
611  return true;
612  }
614 };
615 
619 template<class Type>
620 Type
622 {
623  Type *dataptr = data;
624  Type min = *dataptr;
625  dataptr++;
626  for (unsigned int i = 0; i < dsize-1; i++)
627  {
628  if (*dataptr < min) min = *dataptr;
629  dataptr++;
630  }
631  return min;
632 }
633 
637 template<class Type>
638 Type
640 {
641  Type *dataptr = data;
642  Type max = *dataptr;
643  dataptr++;
644  for (unsigned int i = 0; i < dsize-1; i++)
645  {
646  if (*dataptr > max) max = *dataptr;
647  dataptr++;
648  }
649  return max;
650 }
651 
652 #endif
static bool save(const std::string &filename, const vpArray2D< Type > &A, const bool binary=false, const char *header="")
Definition: vpArray2D.h:468
static bool saveYAML(const std::string &filename, const vpArray2D< Type > &A, const char *header="")
Definition: vpArray2D.h:560
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:392
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:639
Type getMinValue() const
Definition: vpArray2D.h:621
Type ** rowPtrs
Address of the first element of each rows.
Definition: vpArray2D.h:78