void OnlineHandwritingPicture::draw(int spatialSize) {
  std::vector<char> grid(spatialSize * spatialSize, ' ');
  for (int i = 0; i < ops.size(); i++) {
    arma::mat csp = constantSpeed(ops[i], 0.1);
    for (int j = 0; j < csp.n_rows; ++j) {
      int a0 = csp(j, 0) + spatialSize / 2.0,
          a1 = csp(j, 1) + spatialSize / 2.0;
      if (a0 >= 0 and a1 >= 0 and a0 < spatialSize and a1 < spatialSize) {
        int n = a0 * spatialSize + a1;
        grid[n] = 'x';
      }
    }
  }
  for (int x = 0; x < spatialSize; x++)
    std::cout << "--";
  std::cout << "|\n";
  for (int y = 0; y < spatialSize; y++) {
    for (int x = 0; x < spatialSize; x++)
      std::cout << grid[x * spatialSize + y] << grid[x * spatialSize + y];
    std::cout << "|\n";
  }
  for (int x = 0; x < spatialSize; x++)
    std::cout << "--";
  std::cout << "|\n";
}
void OnlineHandwritingPicture::codifyInputData(SparseGrid &grid, std::vector<float> &features, int &nSpatialSites, int spatialSize) {
  int nInputFeatures=OnlineHandwritingEncodingSize[enc];
  //Background feature
  grid.backgroundCol=nSpatialSites++;
  features.resize(nInputFeatures*nSpatialSites,0);
  //Render character
  switch(enc) {
  case Simple:
    for (int i=0; i<ops.size(); i++) {
      arma::mat csp=constantSpeed(ops[i],0.1);
      for (int j=0;j<csp.n_rows;++j) {
        int
          a0=csp(j,0)+spatialSize/2.0,
          a1=csp(j,1)+spatialSize/2.0;
        if (a0>=0 and a1>=0 and a0<spatialSize and a1<spatialSize) {
          int n= a0*spatialSize + a1;
          if (grid.mp.find(n)==grid.mp.end()) {
            grid.mp[n]=nSpatialSites++;
            features.resize(nInputFeatures*nSpatialSites,0);
          }
          ++features[grid.mp[n]];
          //          std::cout <<"."<<std::flush;
        } //else  std::cout <<"x"<<std::flush;
      }
    }
    break;
  case Octogram: {//todo: Test
    float piBy4=3.1415926536/4;
    for (int i=0; i<ops.size(); i++) {
      arma::mat csp=constantSpeed(ops[i],0.1);
      for (int j=0;j<csp.n_rows-1;++j) {
        int
          a0=csp(j,0)+spatialSize/2.0,
          a1=csp(j,1)+spatialSize/2.0;
        if (a0>=0 and a1>=0 and a0<spatialSize and a1<spatialSize) {
          int n= a0*spatialSize + a1;
          if (grid.mp.find(n)==grid.mp.end()) {
            grid.mp[n]=nSpatialSites++;
            features.resize(nInputFeatures*nSpatialSites,0);
          }
          int mpnnIF=nInputFeatures*grid.mp[n];
          features[mpnnIF]++;
          float dx=(csp(j+1,0)-csp(j,0));
          float dy=(csp(j+1,1)-csp(j,1));
          float m=powf(dx*dx+dy*dy,0.5);
          dx/=m;
          dy/=m;
          for (int k=0;k<8;k++) {
            float alpha=1-acosf(cosf(k*piBy4)*dx+sinf(k*piBy4)*dy)/piBy4;
            if (alpha>0)
              features[mpnnIF+k+1]+=alpha;
          }
        }
      }
    }
    break;
  }
  case LogSignature1:
    //Todo
    break;
  case LogSignature2:
    //Todo
    break;
  case LogSignature3:
    //Todo
    break;
  case LogSignature4:
    //Todo
    break;
  case SpaceTime3d: {
    std::vector<arma::mat> csp;
    int cspLengths=0;
    for (int i=0; i<ops.size(); i++) {
      csp.push_back(constantSpeed(ops[i],0.1));
      cspLengths+=csp[i].n_rows;
    }
    // if (cspLengths>maxLength) {
    //   std::cout <<cspLengths*penSpeed3d << " " << std::flush;
    //   maxLength=cspLengths;
    // }
    int z=0;
    for (int i=0; i<ops.size(); i++) {
      for (int j=0;j<csp[i].n_rows;++j) {
        int
          a0=csp[i](j,0)+spatialSize/2.0,
          a1=csp[i](j,1)+spatialSize/2.0,
          a2=renderSize*((z-cspLengths/2)*penSpeed3d+offset3d)+spatialSize/2;
        z++;
        if (a0>=0 and a1>=0 and a2>=0 and a0<spatialSize and a1<spatialSize and a2<spatialSize) {
          int n= a0*spatialSize*spatialSize + a1*spatialSize + a2;
          if (grid.mp.find(n)==grid.mp.end()) {
            grid.mp[n]=nSpatialSites++;
            features.resize(nInputFeatures*nSpatialSites,0);
          }
          ++features[grid.mp[n]];
        }
      }
    }
    break;
  }
  case VectorSpaceTime3d: {
    std::vector<arma::mat> csp;
    int cspLengths=0;
    for (int i=0; i<ops.size(); i++) {
      csp.push_back(constantSpeed(ops[i],0.1));
      cspLengths+=csp[i].n_rows;
    }
    // if (cspLengths>maxLength) {
    //   std::cout << cspLengths*penSpeed3d << " " << std::flush;
    //   maxLength=cspLengths;
    // }
    int z=0;
    for (int i=0; i<ops.size(); i++) {
      for (int j=0;j<csp[i].n_rows-1;++j) {
        int
          a0=csp[i](j,0)+spatialSize/2.0,
          a1=csp[i](j,1)+spatialSize/2.0,
          a2=renderSize*((z-cspLengths/2)*penSpeed3d+offset3d)+spatialSize/2;
        z++;
        if (a0>=0 and a1>=0 and a2>=0 and a0<spatialSize and a1<spatialSize and a2<spatialSize) {
          int n= a0*spatialSize*spatialSize + a1*spatialSize + a2;
          if (grid.mp.find(n)==grid.mp.end()) {
            grid.mp[n]=nSpatialSites++;
            features.resize(nInputFeatures*nSpatialSites,0);
          }
          int mpnnIF=nInputFeatures*grid.mp[n];
          features[mpnnIF]++;
          float dx=(csp[i](j+1,0)-csp[i](j,0));
          float dy=(csp[i](j+1,1)-csp[i](j,1));
          float m=powf(dx*dx+dy*dy,0.5);
          dx/=m;
          dy/=m;
          features[mpnnIF+1]+=dx;
          features[mpnnIF+2]+=dy;
        }
      }
    }
    break;
  }
  }
}