Still relatively new to vectors in C++, the aim of this function is to take 4 arguments, 3 of which define the (x , y , z) position of the data being written, and the 4th being the value that is to be written.
as Requested, a picture of the errors is listed:
Picture of code listed above
The issue is under the "push_back" code. the "." after yy.push and xx.push is giving the error "no instance of overloaded function".
If somebody could explain what this means and how to fix it I would greatly appreciate it! :)
double datawrite(vector<unsigned int> xx, vector<unsigned int> yy,
vector<unsigned int> zz, double val) {
//Writes data to the 3d Vector
//finds coordinates for data
vector< vector< vector<unsigned int > > > xx;
vector< vector<unsigned int> > yy;
vector<unsigned int> zz;
//Writes value at proper position
zz.push_back(val);
yy.push_back(zz);
xx.push_back(yy);
//outputs value from vector
return val;
}
So you want a 3d matrix of doubles? First you need to create it:
#include <vector>
std::vector<vector<vector<double>>> matrix;
This creates a 3d matrix, but with 0 size. Next, when you add data to the matrix, you need to make sure the matrix is big enough:
// Co-ords are integers
double datawrite(int x, int y, int z, double val)
{
// Make sure vectors are large enough
if (matrix.size() < x+1) matrix.resize(x+1);
if (matrix[x].size() < y+1) matrix[x].resize(y+1);
if (matrix[x][y].size() < z+1) matrix[x][y].resize(z+1);
// Store the value
matrix[x][y][z] = val;
return val;
}
However, this is a bit messy and leaves the matrix in an incomplete state. For example, if you call datawrite(2, 3, 4, 9.9); this may appear that all indexes < 2,3,4 would be valid, but they are not. For example trying to read matrix[0][0][0] will give you an error.
You could work around this with a dataread function that checks the sizes of the vectors before trying to read from them.
If you know ahead of time how large the matrix is, you can create the entire matrix at once like this:
vector<vector<vector<double>>> matrix(10, vector<vector<double>>(10, vector<double>(10)));
This creates a complete 10x10x10 matrix. This ensures all indexes < 10 will be valid. I prefer this method. Then your function becomes:
double datawrite(int x, int y, int z, double val)
{
// Make sure indexes are valid
if (x >= matrix.size() || y >= matrix[x].size() || z >= matrix[x][y].size()) {
// Up to you what to do here.
// Throw an error or resize the matrix to fit the new data
}
// Store the value
matrix[x][y][z] = val;
return val;
}
Related
I'm new to C++, and as an exercise I'm trying to reproduce what was done by Metropolis et al. (Metropolis Monte Carlo).
What I have done thus far - Made 2 classes: Vector and Atom
class Vector {
public:
double x;
double y;
Vector() {
}
Vector (double x_, double y_) {
x = x_;
y = y_;
}
double len() {
return sqrt(x*x + y*y);
}
double lenSqr() {
return x*x + y*y;
}
};
class Atom {
public:
Vector pos;
Vector vel;
Vector force;
Atom (double x_, double y_) {
pos = Vector(x_, y_);
vel = Vector(0, 0);
force = Vector(0, 0);
}
double KE() {
return .5 * vel.lenSqr();
}
};
I am not certain that the way I have defined the class Atom is... the best way to go about things since I will not be using a random number generator to place the atoms in the box.
My problem:
I need to initialize a box of length L (in my case L=1) and load it with 224 atoms/particles in an offset lattice (I have included a picture). I have done some reading and I was wondering if maybe an array would be appropriate here.
One thing that I am confused about is how I could normalize the array to get the appropriate distance between the particles and what would happen to the array once the particles begin to move. I am also not sure how an array could give me the x and y position of each and every atom in the box.
Metropolis offset (hexagonal) lattice
Well, It seems, that generally you don't need to use array to represent the lattice. In practice most often it may sense to represent lattice as array only if your atoms can naturally move only on the cells (for example as figures in chess). But seems that your atoms can move in any direction (already not practicle to use such rigid structure as array, because it has naturally 4 or 8 directions for move in 2D) by any step (it is bad for arrays too, because in this case you need almost countless cells in array to represent minimal distance step).
So basically what do you need is just use array as storage for your 224 atoms and set particular position in lattice via pos parameter.
std::vector<Atom> atoms;
// initialize atoms to be in trigonal lattice
const double x_shift = 1. / 14;
const double y_shift = 1. / 16;
double x_offset = 0;
for (double y = 0; y < 1; y += y_shift){
for (double x = x_offset; x < 1; x += x_shift){
// create atom in position (x, y)
// and store it in array of atoms
atoms.push_back(Atom(x, y));
}
// every new row flip offset 0 -> 1/28 -> 0 -> 1/28...
if (x_offset == 0){
x_offset = x_shift / 2;
}
else{
x_offset = 0;
}
}
Afterwards you just need to process this array of atoms and change their positions, velocities and what you need else according to algorithm.
I'm writing a code which calculates the optical flow with the iterative Lucas-Kanade method: calcOpticalFlowPyrLK().
I have a vector of an array that can hold two elements, see example below:
vector <Point2f> points[2];
The x and y coordinates are stored in the array and the array is stored in the vector. When outputting the array, for instance cout << points[0], the coordinates are currently displayed on the screen as follows:
Output example: [261.837, 65.093]
Now I want to extract the x- and y coordinate, separate them and store them in different variables. Already tried several ways with an iterator with no result. I would appreciate it if someone could help me with this, thanks.
The following example applies the PLK to a regular grid and shows how to read the x and y coordinates. The points are stored in a Point2f class using the vector class to store them in an array. The class has public x and y members you can use directly. This examples uses no iterator.
std::vector<cv::Point2f> prevPoints, currPoints;
std::vector<float> error; // stores the SSD error.
std::vector<uchar> status;// stores a flag of successful tracking / I recomend to ignore it.
cv::Mat prevGrayImg,currGrayImg;
// <- insert code for read the images
// initalize grid or the features you want to track
for( int r = 0; r < prevGrayImg.rows;r+=5){
for( int c = 0; c < prevGrayImg.cols;c+=5){
prevPoints.push_back(cv::Point2f(c,r));
}}
// apply pyramidal lucas kanade
cv::calcOpticalFlowPyrLK(prevGrayImg, currGrayImg, prevPoints, currPoints, status, error);
for( unsigned int i = 0; i < prevPoints.size(); i++){
float x0 = prevPoints[i].x;
float y0 = prevPoints[i].y;
float x1 = currPoints[i].x;
float y1 = currPoints[i].y;
}
With iterator it would be:
for( auto i = prevPoints.begin(); i != prevPoints.end(); ++i){
float x0 = i->x; ... a.s.o
I add one double value from a file to a variable and push it into a vector, with format "338620.3478" , then after that I get the value from the vector, it just gets "338620", as it could not get all the double value.
So how can I get a full double value like the original format?
The Code:
struct Point {
double x, y;
bool operator <(const Point &p) const {
return x < p.x || (x == p.x && y < p.y);
}
};
ifstream iFile("griddata.dat"); //read a file (grid)
string line;
Point Grid; /
while(getline(iFile,line))
{
unsigned pos = line.find(",");//the symbol is used to separate X and Y
std::string strs = line.substr(0,pos); // get X
std::string strs2 = line.substr(pos+1); // get Y
Grid.x = atof(strs.c_str()); // get the first cooordinate X
Grid.y = atof(strs2.c_str()); // get the second cooordinate Y
// A list of coordinates of grid is stored into the vector gridPoints
gridPoints.push_back(Grid); // adding the points of grid to vector
}
int j;
for(j=0;j<gridPoints.size();j++)
{
//here i cannot get the full double value for gridPoints[j].x;
//....it just gets "338620"
}
The format of file (griddata.dat):
338620.3478,6196150.566
Thank you!
Assuming that your Point class is in the windows framework, I'm pretty sure it's members are int types.
Either way, your values are being cast to a type that isn't floating point and is being truncated.
I think your problem is retrieving the values (maybe with cout?? -->then you can use: cout.precision(15))
see: How do I print a double value with full precision using cout?
I have a vector of vector of myObjects defined, creating essentially a 2D array. I would like to transpose this array such that rows become columns and columns become rows. Obviously I could do this in a double for-loop, but this seems massively inelegant and will be pretty slow. I was wondering if there's something clever in C++ or the STL that would let me swap the inner and outer vectors around quickly and efficiently, rather than writing...
for (int iRow = 0; iRow < nRows; ++iRow)
{
for (int iCol = 0; iCol < nCols; ++iCol)
{
myNew2DArray[iCol][iRow] = myOriginal2DArray[iRow][iCol];
}
}
Alternatively, you can store the matrix in a vector and have a flag that specifies whether the matrix is transposed or not. Then you simply calculate the index. Here is an example:
class Matrix {
private:
std::vector<int> matrix;
bool isTransposed = false;
int width, height;
public:
// ...
int getElement(int x, int y)
{
int w = width;
int h = height;
if(isTransposed) {
int z = x;
x = y;
y = x;
z = w;
w = h;
h = z;
}
return matrix[y * width + x];
}
// ...
};
This will reduce the cost of transposing the matrix, but increases the cost of actually accessing the elements.
My suggestion would be to make a class called Matrix that contains the matrix that you are talking about. Give the class a function transpose() that toggles a state flag for the state "transposed". Then, overload the [] operator to follow mwd's suggestion of inverting the indeces when the matrix is in the transposed state.
What you've coded already is pretty much the easiest way. Really you don't need a vector of vectors. You can just append each new 'row' to a single vector. Then what would have been element matrix[i][j] in your original vector of vectors is now matrix[(i*n)+j], when n is the 'width' of your matrix. The fiddly part is coming up with the algorithm to perform the transpose. I'm not saying this way is any better, but it's an alternative route, and what you've got already is fine.
Your best bet is using the Eigen matrix library, which stores the transposedness property in a parameter of the matrix class. If that is not an option, google for one of the numerous matrix transpose algorithms.
I'm pretty new to C++ so I'm not sure I'm going about this problem in the right way. I'm dealing with a 3D array of voxel data and I would like to create a parallel data structure to store isosurface normal vectors. Memory efficiency is an issue so I thought to use a 2D array of maps, which are indexed by an integer and contain a 3D vector.
The idea being the 2D array indexes every x and y coordinate and the maps index only the z coordinates containing a value (typically between 0 and 3 values dispersed along each row of the z axis).
Question 1: how do I create a 2D array of maps like std::map<int, Vector3f> surfaceNormals; ?
Question 2: My idea is declare the 2D array global then to populate it with a function which deals with it by pointer and creates a map for each array cell, is the code below on the right track? the ?????'s indicate where i'm not sure what to put given my uncertainty about Question 1.
In particular am I managing pointers/references/values correctly such as to actually end up storing all the data I need?
????? isoSurfaces1 [256][100];
????? *extractIS(float Threshold, ????? *pointy){
????? *surfacePointer = pointy;
for loop over x and y {
std::map<int, Vector3f> surfaceNormals;
for loop over z {
[ ... find surface voxels and their normal vectors ... ]
Vector3f newNormalVector(x,y,z);
surfaceNormals[zi] = newNormalVector;
}
surfacePointer[x][y] = surfaceNormals;
}
return surfacePointer;
}
extractIS(0.45, isoSurfaces1);
If i understood you correctly, you want to use the coordinate as a std::map key?
You could just create 1 dimensional std::map, and convert the XYZ coordinates into 1 dimensional coordinate system:
int pos1d = z*max_x*max_y+y*max_x+x;
and then just put that to the map key.
Edit: or you could just use a struct with x,y,z as integers as Space_C0wb0y showed, but that will of course take 3x more memory per std::map key, also note that the example i showed will have the maximum cube size: 1625x1625x1625 (if unsigned int), so if you need longer coordinates then use a struct, but note that with structs you have to write comparisor function for the std::map key datatype.
Edit3:
I think this is what you are looking for, as i noticed you used max 256 coordinate value, here is what i came up with:
// NOTE: max 256x256x256 cube coordinates with this struct. change unsigned char to short or int etc if you need larger values.
// also note that if you change to something else than unsigned char, you cant use nor compare the union: v1.Pos > v2.Pos anymore.
// (unless you use unsigned short for each coordinate, and unsigned __int64 for the union Pos value)
union PosXYZ {
struct {
unsigned char x, y, z, padding; // use full 32bits for better performance
};
unsigned __int32 Pos; // assure its 32bit even on 64bit machines
PosXYZ(unsigned char x, unsigned char y, unsigned char z) : x(x), y(y), z(z), padding(0) {} // initializer list, also set padding to zero so Pos can be compared correctly.
};
inline bool operator>(const PosXYZ &v1, const PosXYZ &v2){
return v1.Pos > v2.Pos;
}
typedef map<PosXYZ, Vector3f, greater<PosXYZ> > MyMap;
void extractIS(float Threshold, MyMap &surfacePointer){
for loop over x and y {
for loop over z {
// [ ... find surface voxels and their normal vectors ... ]
Vector3f newNormalVector(x,y,z);
surfacePointer[PosXYZ(x,y,z)] = newNormalVector;
}
}
}
MyMap isoSurfaces1;
extractIS(0.45, isoSurfaces1);
Another way to do this std::map key struct is to just use plain integer value, which you would generate via your own function similar to: ((x << 16) | (y << 8) | z), this will simplify things a little since you dont need the comparisor function for std::map anymore.
#define PosXYZ(x,y,z) (((x) << 16) | ((y) << 8) | (z)) // generates the std::map key for 256x256x256 max cube coords.
typedef map<unsigned __int32, Vector3f, greater<unsigned __int32> > MyMap;
void extractIS(float Threshold, MyMap &surfacePointer){
for loop over x and y {
for loop over z {
// [ ... find surface voxels and their normal vectors ... ]
Vector3f newNormalVector(x,y,z);
surfacePointer[PosXYZ(x,y,z)] = newNormalVector;
}
}
}
MyMap isoSurfaces1;
extractIS(0.45, isoSurfaces1);
First off, a map has a higher memory overhead than a vector. This brings up the question, how many elements are there? Is it feasible to have vectors that are partly empty? Consider the following implementation:
struct 3dvec {
3dvec(int x, int y, int z) : x(x), y(y), z(z) {}
int x;
int y;
int z;
};
std::vector<3dvec> empty_z_vector(4, 3dvec(0, 0, 0));
std::vector< std::vector<3dvec> > data(width*height, empty_z_vector);
You simply keep all values in memory, based on the assumption that only a few of them will be empty, and there will never be more than 4 z-values. You can access the 3dvec at position X, Y, Z like this:
data[X + Y*width][Z]
This is making a lot of assumptions, but in the end, you will have to compare possible solution, because the feasibility depends on the data.