How to access a variable defined in a struct - c++

struct POINT3DID
{
unsigned int newID;
float x, y, z;
};
typedef std::map<unsigned int, POINT3DID> ID2POINT3DID;
ID2POINT3DID m_i2pt3idVertices;
Can someone please tell me how can I access the variables x,y and z using m_i2pt3idVertices

m_i2pt3idVertices is a container for storing POINT3DID objects. Alone, it doesn't have member variables x, y, or z. You can put a POINT3DID inside of it though:
m_i2pt3idVertices[0] = POINT3DID(); // Put a POINT3DID into key 0
m_i2pt3idVertices[0].x = 1.0f; // Assign x for key 0
m_i2pt3idVertices[0].y = 2.0f; // Assign y for key 0
m_i2pt3idVertices[0].z = 3.0f; // Assign z for key 0

ID2POINT3DID is map container. You can access single element by some unsigned int key:
m_i2pt3idVertices[42].x
Or you can iterate over elements in container:
for(ID2POINT3DID::iterator it=m_i2pt3idVertices.begin();it!=m_i2pt3idVertices.end();++it) {
cout << it->second.x << " " << it->second.y << " " << it->second.z << endl;
}

You need to use iterator. Here is a sample:
std::map<unsigned int, POINT3DID>::iterator it;
it = m_i2pt2idVertices.find(5);
it->second.x = 0;
it->second.y = 1;
it->second.z = 2;

Related

C++ vectors of values returning a matrix

I have 4 integer variables - x,y,z,t which could get values from an interval of integer values [a,b] ) ( the interval is a,a+1,a+2,...,b ).
I want to set a vector of distinct {x,y,z,t} values with the following rule:
2 quartets (x and y) are not equal if there exists at least one quartet value for which : x.i != y.i (i is one of the {x,y,z,t} value positions).
My current solution is extremely time consuming:
struct gim
{
int xx;
int yy;
int zz;
int tt;
}
vector<gim> v;
x=a;y=a;z=a;t=a;
nr_quartet=0;
gim g;
while(x<=b)
{
while(y<=b)
{
while(z<=b)
{
while(t<=b)
{
if(at least one of x,y,z,t is different)
{
nr_quartet++;
g.xx=x;
g.yy=y;
g.zz=z;
g.tt=t;
v.push_back(g);
cout << x << " " << y << " " << z << " " << t << "\n";
}
t++;
}
z++;
}
y++;
}
x++;
}
You can try something like this:
int actual_t = t;
int actual_z = z;
int actual_y = y;
int actual_x = x;
while(t<=b && z <=b && y<=b && x<=b)
{
if(at least one of x,y,z,t is different)
{
nr_quartet++;
v.emplace_back(x, y, z, t);
//cout << x << " " << y << " " << z << " " << t << "\n";
}
// For t
if(t==b)
{
t = 0;
}
else
{
t++;
}
actual_t = t;
// For z
if(z==b)
{
z = 0;
}
else if(/* incrementation condition for z */)
{
z++;
}
actual_z = z;
/* the same for y and x */
}
If you only need the number of elements of the set {(x,y,z,t) | ¬(x = y = z = t)}, then compute (b-a)**4 - (b-a); i.e. no need to iterate through all of them.
If you really need to fill a vector with all the combinations, well, you will have to iterate to add them all. The longest part will be memory allocations inside the std::vector, so pre-reserve or pre-resize with the number of elements since you can know it in advance.
As far as I've done is something which is consuming much time
What do you mean it is consuming a lot of time? What is your [a, b] range?

Best data structure for point traversal

Looking for a C++ solution.
I had thoughts whether to ask this question over here or MathExchange etc. but since it's more of a programming based question thus posting here.
Real problem:
I have an XML with field as:
<part name='01' x='351' y='151'/>
Where x and y, I am storing as QPointf object. Also, I require the name=01 value which I am mapping together with the QPointf object to create a map.
Now there are certain operations that I need to do on this map :
First I need to get all the points(QPointf) and draw over an image.
Second, I will modify the x and y value of certain points getting the points from the GUI.
When I get the points from GUI, I need to check x and y value in each Qpointf inside map.
Problem in simpler form:
I am looking for a data structure such that instead of having a map of key and QPointf, it makes parsing and looking for x and y value of points(QPointf) easier. Just that the QPointf and key should form a unique pair with each other, so that parsing through the entire list of points to find certain (x,y) and modifying it is faster and even when x and y value of QPointf is modified the key attached to it is same.
PS: I hope I was clear with the problem, if there is anything unclear then please edit/comment so that the question can be improved.
My guess is here that your most important aspect is finding a certain set of x and y points when a user uses the UI. There are many acceleration structures possible, but I would probably recommend a point index grid. That is, you partition the indices of points into 2D buckets. When a user chooses a point in the UI, you can do a quick look-up on what bucket the point is in, and you can then iterate over only the points present in that bucket to find the actual point.
As for your data, I would store it in an array:
struct NamePoint {
int name, x, y;
};
std::vector<NamePoint> points;
Now you would create a point index grid that refers to the points array. Implementing one yourself might be worthwhile, but otherwise I know that there exists an OpenVDB version that works.
I made a small dirty implementation so you can see the principle. I have no checks for inputs, so if you're not careful you will access out of the bounds of the vector (e.g., calling pointIndexGrid.indicesForPoint(5, 5) gives segmentation fault).
#include <iostream>
#include <vector>
#include <limits>
struct NamePoint {
int name, x, y;
};
template <typename T> // Just so any array type can work
struct PointIndexGrid {
using ArrayType = T;
using size_type = typename ArrayType::size_type;
PointIndexGrid(const ArrayType& points, int gridSize)
: mGridSize(gridSize)
{
// Find the domain. We will create a 2D vector which will all contain another vector with indices.
maxX = maxY = std::numeric_limits<int>::min();
minX = minY = std::numeric_limits<int>::max();
for (const auto& p : points) {
maxX = p.x > maxX ? p.x : maxX;
maxY = p.y > maxY ? p.y : maxY;
minX = p.x < minX ? p.x : minX;
minY = p.x < minY ? p.x : minY;
}
// create buckets
int nbrXBuckets = (maxX - minX)/mGridSize + 1; // Due to integer arithmetics we round down -- lets add one extra just in case
int nbrYBuckets = (maxY - minY)/mGridSize + 1;
for (int n = 0; n < nbrXBuckets; ++n) {
mBuckets.emplace_back(std::vector<std::vector<size_type>>(nbrYBuckets));
}
// Partition points
for (size_type i = 0; i < points.size(); ++i) {
int xBucket = (points[i].x - minX)/mGridSize; // this is the method how to easily calculate the bucket. Pure arithmetics -- goes fast
int yBucket = (points[i].y - minY)/mGridSize;
mBuckets[xBucket][yBucket].emplace_back(i);
}
}
std::vector<size_type> indicesForPoint(int x, int y)
{
int xBucket = (x - minX)/mGridSize; // Same as above
int yBucket = (y - minY)/mGridSize;
return mBuckets[xBucket][yBucket];
}
private:
int mGridSize;
int maxX, minX;
int maxY, minY;
std::vector<std::vector<std::vector<size_type>>> mBuckets;
};
int main() {
std::vector<NamePoint> points;
points.emplace_back(NamePoint{1, 1, 1});
points.emplace_back(NamePoint{2, 1, 2});
points.emplace_back(NamePoint{3, 1, 2});
points.emplace_back(NamePoint{4, 2, 2});
points.emplace_back(NamePoint{5, 3, 3});
PointIndexGrid<std::vector<NamePoint>> pointIndexGrid(points, 2);
std::cout << "Indices for (1, 1): " << std::endl;
for (const auto& i : pointIndexGrid.indicesForPoint(1, 1)) {
std::cout << " " << i << std::endl;
}
std::cout << "Indices for (3, 3): " << std::endl;
for (const auto& i : pointIndexGrid.indicesForPoint(3, 3)) {
std::cout << " " << i << std::endl;
}
}
This prints out:
Indices for (1, 1):
0
1
2
3
Indices for (3, 3):
4
So to find a point at a specific (x, y):
Partition all points using the PointIndexGrid.
Use pointIndexGrid.indicesForPoint(x, y).
Iterate through all indices there (and look up the points in the points-array).
Grab the point that you want.
So if I understood correctly you just want an easy way to store your points data.
This isn't the best in terms of performance but if you are not planing on changing it every frame it will work no problem:
#include <map>
typedef std::map<int, std::pair<float, float>> PointContainer;
QPointf* fromPointContainer(PointContainer points)
{
QPointf array = new QPointf[points.size()];
for (size_t i; i < points.size(); i++)
array[i] = QPointf(points[i].first, points[i].second);
return array;
}
int main() {
PointContainer points;
points[0] = { 1.6f/*x*/, 5.8f/*y*/ };
QPointf* array = fromPointContainer(points);
//render here
delete array;//don't forget to delete the array allocated with new
return 0;
}

Access variables in a struct?

I'm building a small vector engine and I'm having some trouble accessing the variables I have made in my struct.
Here's my struct:
struct vectorVariables {
float v = 0, a = 0;
float u = 20;
float deltaT = 0.01;
float posNew = 0 , posOld = 0;
float gravity = -9.81;
};
All I want to be able to do for example, is print out one of these variables to the console.
Those variables are available if you create an object. With that declaration in scope, and with the appropriate headers included, try this:
int main() {
vectorVariables vv;
std::cout << vv.v << " " << vv.a << "\n";
}

Why does a map insert change the object member values?

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
class Car {
public:
Car( float costs, float speed) : costs(costs), speed(speed){};
float getSpeed() const {
return speed;
}
float getCosts() const {
return costs;
}
private:
float costs;
float speed;
};
class CarManager {
public:
CarManager(){};
void assignCars( std::vector<Car> &cars){
float costs = 1000.0;
float inc_costs = 700.0;
float inc_speed = 50.0;
for (size_t i = 0; i <= 10; ++i) {
float speed = 10.0;
std::vector<Car*> car_vec;
for (size_t j = 0; j < 5; ++j) {
if (j >= i) {
cars.push_back(Car(costs, speed));
car_vec.push_back(&cars.back());
}
speed += inc_speed;
}
car_storage.insert( {costs , car_vec } );
costs += inc_costs;
}
}
void print(){
for (const auto & p : car_storage) {
std::cout << "map[" << p.first << "] = ";
for (const auto & s : p.second) {
std::cout << "[" << s->getSpeed() <<", " << s->getCosts() << "] , ";
}
std::cout << std::endl;
}
}
private:
std::map<float, std::vector<Car*> > car_storage;
};
int main()
{
std::vector<Car> cars;
CarManager car_manager;
car_manager.assignCars(cars);
car_manager.print();
}
The printout somehow differs from what I expect. I push a Car with costs and speed into a vector [cars.push_back(Car(costs, speed))] and later push a pointer to this Car in a local vector of Car*: car_vec.push_back(&cars.back()). Next, I insert the key (costs) and the value (car_vec) into the map. When I print the map out, the values aren't correct anymore.
In the first case for example:
first loop i = 0, inner loop j, thus (j >= i) and I push_back a Car( 1000.0, 10.0). What's contained in the map, later on, is simply a Car(0,0). For the other cars, this applies as well, but they have some strange values.
map[1000] = [0, 0] , [0, 7.41086e-38] , [0, 7.41063e-38] , [0, 7.41064e-38] , [210, 1700] ,
map[1700] = [0, 7.41092e-38] , [0, 7.41094e-38] , [0, 7.41094e-38] , [210, 1700] ,
map[2400] = [110, 2400] , [160, 2400] , [210, 2400] ,
map[3100] = [160, 3100] , [210, 3100] ,
map[3800] = [210, 3800] ,
I have no clue what is going on. Debugging showed me, that the values have been ok until they get inserted into the map at car_storage.insert( {costs , car_vec } ).
What happens when you write this:
cars.push_back(Car(costs, speed))
car_vec.push_back(&cars.back())
? You create a Car and push it's copy to the cars vector. On the next line you push a pointer to the copy in this vector. Never do it! On any further operation with first vector's size change like push_back, clear and so on it may reallocate all it's content. I.e. it takes new memory fragment, copies values there, deletes the old one. Old pointers to it's content become invalid.

Jumping into C++ Chapter 13 Practice Prob No4 - Pointers

I've having trouble understanding the wording of this question and what it means by returning the second value through a pointer parameter?
The problem is:
Write a function that takes input arguments and provides two seperate results to the caller, one that is the result of multiplying the two argumentsm the other the result of adding them. Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter.
This is what I've done so far.
int do_math(int *x, int *y)
{
int i =*x + *y;
int u = *x * *y;
int *p_u = &u;
return i;
}
void caller()
{
int x = 10;
int y = 5;
std::cout << do_math(&x, &y);
//std::cout << *u;
}
I think all they're wanting you to do is to demonstrate your understanding of the difference between passing arguments by value and passing them by reference.
Here is a sample code that shows that although my function is only returning one value "i = X+Y", It is also changing the value of Y to (Y * X).
Of course if you do need Y's value to stay unchanged, you could use a third variable that is equal to Y's value and pass its reference as an extra argument to your function.
You could run the code bellow to see what's happening to X and Y before and after calling the function.
Hope this helps.
#include <iostream>
using namespace std;
int do_math(int value1, int *pointer_to_value2)
{
int i = value1 * *pointer_to_value2;
*pointer_to_value2 = *pointer_to_value2 + value1; // y changes here
return i;
}
int main( int argc, char ** argv ) {
int x = 10;
int y = 5;
cout << "X before function call " << x << endl;
cout << "Y before function call " << y << endl;
int product = do_math(x, &y);
cout << "X after function call " << x << endl;
cout << "Y after function call " << y << endl;
cout << "What the function returns " << product << endl;
return 0;
}
In the assignment there is written
Write a function that takes input arguments ...
So there is no any need to declare these input parameters as pointers.
The function could look like
int do_math( int x, int y, int &sum )
{
sum = x + y;
return x * y;
}
or
int do_math( int x, int y, int *sum )
{
*sum = x + y;
return x * y;
}
In these function definitions the sum and the product can be exchanged as the parameter and return value
As for me the I would write the function either as
void do_math( int x, int y, long long &sum, long long &product )
{
sum = x + y;
product = x * y;
}
or
#include <utility>
//...
std::pair<long long, long long> do_math( int x, int y )
{
return std::pair<long long, long long>( x + y, x * y );
}
void caller()
{
int x = 10;
int y = 5;
std::pair<long long, long long> result = do_math( x, y );
std::cout << "Sum is equal to " << result.first
<< " and product is equal to " << result.second
<< std::endl;
}
Edit: I would like to explain why this statement
std::cout << "sum is " << do_math(x, y, result) << " and result is " << result;
is wrong.
The order of evaluation of subexpressions and function argument is unspecified. So in the statement above some compilers can output value of result before evaluation function call do_math(x, y, result)
So the behaviour of the program will be unpredictable because you can get different results depending on using the compiler.
Edit: As for your code from a comment then it should look like
#include <iostream>
int do_math( int x, int y, int *p_u )
{
int i = x + y;
*p_u = x * y;
return i;
}
int main()
{
int x = 10;
int y = 5;
int u;
int i = do_math( x, y, &u );
std::cout << i << std::endl;
std::cout << u << std::endl;
}
Also take into account that in general case it is better to define variables i and u as having type long long because for example the product of two big integers can not fit in an object of type int.
The wording is kind of contrived but I believe the task asks you to
return the multiplication as the return value of the function, and
since you can't return two types at once (except if you wrap them up somehow), you should use a third parameter as a storage area for the sum:
#include <iostream>
/* Multiplication in here */ int do_math(int x, int y, int& result/* Addition in here */)
{
result = x + y;
return x*y;
}
int main() {
int x = 10;
int y = 5;
int addition = 0;
int multiplication = do_math(x, y, addition);
std::cout << "multiplication is " << multiplication << " and sum is " << addition;
}
Example
It's not specifically asking you to use two parameters for the function.
A typical solution to the intent of the exercise text…
” Write a function that takes input arguments and provides two seperate results to the caller, one that is the result of multiplying the two argumentsm the other the result of adding them. Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter
… is
auto product_and_sum( double& sum, double const a, double const b )
-> double
{
sum = a + b;
return a*b;
}
#include <iostream>
using namespace std;
auto main() -> int
{
double product;
double sum;
product = product_and_sum( sum, 2, 3 );
cout << product << ", " << sum << endl;
}
This code is unnatural in that one result is returned while the other is an out-argument.
It's done that way because the exercise text indicates that one should do it that way.
A more natural way to do the same is to return both, as e.g. a std::pair:
#include <utility> // std::pair, std::make_pair
using namespace std;
auto product_and_sum( double const a, double const b )
-> pair<double, double>
{
return make_pair( a*b, a+b );
}
#include <iostream>
#include <tuple> // std::tie
auto main() -> int
{
double product;
double sum;
tie( product, sum ) = product_and_sum( 2, 3 );
cout << product << ", " << sum << endl;
}
As the second program illustrates, the last sentence of the exercise text,
” Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter
… is just not true. I suspect the author had meant the word “directly” to clarify that this excluded the case of a non-basic type. But even so the conclusion is incorrect.
What you need to do is provide another parameter to the function - the pointer or the reference to the variable where you want to store your other result:
int do_math(int *x, int *y, int &res) //or int *res
{
...
res = *x * *y;
...
}
Then make a result variable in main and pass it to the function