pass a pointer as a memory address and make it permanent - c++

i've just begin to approach in cpp. so mayebe it is a simple problem, mayebe it is a structural problem and i have to change my design.
i have 3 facts and 1 problem.
fact 1:
i have a Gesture class with a vector of Point inside
vector<Point> Gesture::getPoints();
the Gesture instances recive the vector in the constructor so i think it could be normal vector (no pointer). vectors are not shared between gestures neither a gesture change its own points (aside normalization).
fact 2:
Gesture class has a static method that normalize all points between [0:w]. normalize take a memory address to normalize in-place. i think that normalization in place could be a nice thing. this normalization method is used by widgets to visualize the path in vector for normalize point between 0 and width-of-the-widget
static void Gesture::normalize(vectot<Point> &pts, int w);
fact 3:
i have a widget that visualize points:
void MyWidget::setGestures(vector <Gesture *> gs)
because the gesture is produced by another widget dinamically i thought that it has been handy to work with a vector of pointer and can do some new Gesture calls.
problem:
i have several widget that visualize gesture. each one with a different width (== different normalization).
the first time i use:
Gesture::rescale(this->w, this->points);
Gesture * g = new Gesture(getPoints(), centroids);
and it's everything ok
the second time i have:
vector<Gesture* > gs = foo();
int num_gesture = gs.size();
for (int i = 0; i < num_gesture; ++i) {
vector<Point> pts = gs.at(i)->getPoints();
Gesture::rescale( widget->getWidth(), pts );
}
widget->setGestures(gs);
and here there are problem because this widget is drawing not normalized points.
i have tried some crazyness with pointers but if the program does not crash.. anyway it not normalized. and it get some error like: pointer to a temporary.
i don't knwo what to think, now.

Although your question is a little confusing, the problem seems to be that Gesture::getPoints() returns a vector and not a reference to a vector, so it actually returns a copy to the internal vector, and so changing it does not modify the gesture object itself.

Related

Does Fixed_alpha_shape_3() destroy or modify original triangulation?

Does Fixed_alpha_shape_3() destroy or modify the underlying triangulation? The doc says "this operation destroys the triangulation" but does it replace it with the alpha shape triangulation? The source code suggests it is modifying the underlying delaunay triangulation since it is removing vertices. Further, the fact that the triangulation object is passed as a reference also makes me think alpha shape is modifying the underlying triangulation. If it is true, it means we can continue using the original triangulation object naturally throughout the remainder of our code. If the triangulation is not modified, instead it is truly destroyed and no longer exists, can we simply use the Fixed_alpha_shape_3 object as a triangulation object since it inherits from the Triangulation class?
The ultimate goal is to make sure cell neighbors are updated in a new triangulation object after alpha shape removes cells on the boundary. Most importantly, the new triangulation object needs to contain the correct cell->neighbor(i)->is_inifinite status at the boundaries.
For example, construction of the original triangulation follows as usual:
RTriangulation T(points.begin(),points.end());
followed by the creation of the Fixed_alpha_shape_3:
Fixed_alpha_shape_3 as(T);
I know we can access the alphaShape INTERIOR and EXTERIOR cells with various methods including as.get_alpha_shape_cells(), but if Fixed_alpha_shape_3 is simply modifying the original triangulation, T, then we should be able to continue using T as such:
const RTriangulation::Finite_cells_iterator cellEnd = T.finite_cells_end();
for (RTriangulation::Finite_cells_iterator cell = T.finite_cells_begin(); cell != cellEnd; cell++) {
for (int i=0;i<4;i++) {
if (cell->neighbor(i)->is_infinite) cell->info().p = 1;
}
}
Or can I simply start using the alpha shape object instead:
const RTriangulation::Finite_cells_iterator cellEnd = as.finite_cells_end();
for (RTriangulation::Finite_cells_iterator cell = as.finite_cells_begin(); cell != cellEnd; cell++) {
for (int i=0;i<4;i++) {
if (cell->neighbor(i)->is_infinite) cell->info().p = 1;
}
}
The least ideal solution would be to create new lists of cells with as.get_alpha_shape_cells(), because that would mean a major rehaul of our code with many logical splits. I suspect that is not necessary, which is why I am clarifying the action of Fixed_alpha_shape_3().
Thank you for your assistance.
The word "destroys" is an unlucky choice. As you noticed the class Fixed_alpha_shape_3 is derived from the triangulation class. The constructor that takes the reference to a triangulation dt as input, swaps it with dt. So afterwards in dt you find the default constructed, that is empty triangulation.

Passing pointer to single item in Vector of Multidimensional Array to Function c++

I'm working on a program using SDL. I have the following variable instantiated outside of my main function:
std::vector<SDL_Rect[TOTAL_ACTIVITIES][TOTAL_DIRECTIONS][ANIMATION_FRAMES]> gPersonSpriteClips;
(where the all-caps items are constant integers). It's a vector of arrays, because I intend to do a lot of sprite development later. For now, I just have a few placeholder sprites. So, the 3D array captures all aspects of a single human body-type spritesheet, and when I pull in the sheet I'll have the code split it up into multiple body types...
I have a class, "Character", which makes use of the array when it is preparing to render. Here is the call to render myCharacter in main:
myCharacter.render(bodySpritesheetTexture, &*gPersonSpriteClips[myCharacter.getBody()]);
Character.getBody() returns the vector index for the body type used by this instance of character. Here is the function declaration in Character.h:
void render(LTexture& characterSpriteSheetTexture, SDL_Rect spriteClips[TOTAL_ACTIVITIES][TOTAL_DIRECTIONS][ANIMATION_FRAMES]);
Here is the function itself in Character.cpp:
void Character::render(LTexture& characterSpriteSheetTexture, SDL_Rect spriteClips[TOTAL_PERSON_ACTIVITIES][TOTAL_CARDINAL_DIRECTIONS][PERSON_ANIMATION_FRAMES])
{
characterSpriteSheetTexture.render( mPosition.x, mPosition.y, &spriteClips[mActivity][mDirection][mAnimations[mActivity][mCurrentFrame]] );
}
mActivity is the enum for "which activity is presently being performed" by the character. mDirection is which direction he's facing. mAnimations lists frame orders (because some of these animations use the same sprites several times in various orders).
Finally, the render function for LTexture is taken right out of LazyFoo's SDL tutorials.
characterSpriteSheetTexture.render() is calling a function with the following declaration (in LTexture.h):
void render( int x, int y, SDL_Rect* clip = NULL, int targetHeight = NULL, int targetWidth = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE );
So it's expecting an argument of type SDL_Rect* clip. That function makes a call to:
SDL_RenderCopyEx( gRenderer, mTexture, clip, &renderQuad, angle, center, flip );
I get an error when I compile the code, pointing me to a place inside the SDL libraries. I've successfully employed LTexture's render function by passing indexes from one-dimensional arrays of SDL_Rect into it, so I'm very confident that the problem exists in my vector argument.
Ignoring disagreements about naming conventions...... what am I doing wrong here, and what's the proper way to achieve what I'm trying to do?
Granted, I'll probably simplify my scheme for animating things significantly in the future; this is my first shot at generating a player character. Anyway, I'd like to know the mechanics of what's going wrong in this case.
Last thing, please don't suggest that I use boost. I'd really like to avoid boost for this program.
ETA:
Here is the declaration of mAnimations in Character.h:
std::vector<int> mAnimations[TOTAL_ACTIVITIES];
Here is the initialization of it in the default constructor:
for (int i = 0; i < TOTAL_ACTIVITIES; i++)
{
mAnimations[i].resize(ANIMATION_FRAMES);
for (int j = 0; j < ANIMATION_FRAMES; j++)
{
mAnimations[i][j] = j;
}
}
Change your global array definition like this:
using SdlRectArray = std::array<std::array<std::array<SDL_Rect, ANIMATION_FRAMES>, TOTAL_DIRECTIONS>, TOTAL_ACTIVITIES>;
std::vector<SdlRectArray> gPersonSpriteClips;
See here for why not to store arrays in a std::vector or any other container.
Accordingly, define your Character::render() method like this:
void render(LTexture& characterSpriteSheetTexture, SdlRectArray& spriteClips)
{
characterSpriteSheetTexture.render( mPosition.x, mPosition.y, &spriteClips[mActivity][mDirection][mAnimations[mActivity][mCurrentFrame]] );
}
And then you can call it like this:
myCharacter.render(bodySpritesheetTexture, gPersonSpriteClips[myCharacter.getBody()]);
as there's no need for doing &*.
It is difficult to tell from your question what the exact error is, but it seems likely that the root cause is "array decay".
In C++ (and in C), array arguments are almost always treated as pointers to the start of the array. For a multidimensional array, this means that the multiple-indexing you expect can't work, because the language has stripped away the size and shape information necessary.
The sole exception is that reference parameters do not decay in this way. However, if you rely on this, you (and anyone else who works on your code) will need to remember to use that exact reference parameter every time they pass the multidimensional array to another function.
In modern C++, this issue is typically fixed using std::array<>, which was designed for the purpose. In your case, that would be very verbose, so I'd suggest a type alias:
typedef std::array< std::array< std::array<SDL_Rect,
ANIMATION_FRAMES>, TOTAL_DIRECTIONS>, TOTAL_ACTIVITIES> SpriteClip;
std::vector<SpriteClip> gSpriteClips;
Alternatively, you could write a short class:
class SpriteClip {
SDL_Rect m_data[TOTAL_ACTIVITIES][TOTAL_DIRECTIONS][ANIMATION_FRAMES];
public:
SDL_Rect& get(activity, direction, frame) {
return m_data[activity][direction][frame];
}
};
This would let you change the representation easily -- for example, if you decided that you wanted different sprites to have different numbers of activities and frames.

How to properly manage a vector of void pointers

First, some background:
I'm working on a project which requires me to simulate interactions between objects that can be thought of as polygons (usually triangles or quadrilaterals, almost certainly fewer than seven sides), each side of which is composed of the radius of two circles with a variable (and possibly zero) number of 'rivers' of various constant widths passing between them, and out of the polygon through some other side. As these rivers and circles and their widths (and the positions of the circles) are specified at runtime, one of these polygons with N sides and M rivers running through it can be completely described by an array of N+2M pointers, each referring to the relevant rivers/circles, starting from an arbitrary corner of the polygon and passing around (in principal, since rivers can't overlap, they should be specifiable with less data, but in practice I'm not sure how to implement that).
I was originally programming this in Python, but quickly found that for more complex arrangements performance was unacceptably slow. In porting this over to C++ (chosen because of its portability and compatibility with SDL, which I'm using to render the result once optimization is complete) I am at somewhat of a loss as to how to deal with the polygon structure.
The obvious thing to do is to make a class for them, but as C++ lacks even runtime-sized arrays or multi-type arrays, the only way to do this would be with a ludicrously cumbersome set of vectors describing the list of circles, rivers, and their relative placement, or else an even more cumbersome 'edge' class of some kind. Rather than this, it seems like the better option is to use a much simpler, though still annoying, vector of void pointers, each pointing to the rivers/circles as described above.
Now, the question:
If I am correct, the proper way to handle the relevant memory allocations here with the minimum amount of confusion (not saying much...) is something like this:
int doStuffWithPolygons(){
std::vector<std::vector<void *>> polygons;
while(/*some circles aren't assigned a polygon*/){
std::vector<void *> polygon;
void *start = &/*next circle that has not yet been assigned a polygon*/;
void *lastcircle = start;
void *nextcircle;
nextcircle = &/*next circle to put into the polygon*/;
while(nextcircle != start){
polygon.push_back(lastcircle);
std::vector<River *> rivers = /*list of rivers between last circle and next circle*/;
for(unsigned i = 0; i < rivers.size(); i++){
polygon.push_back(rivers[i]);
}
lastcircle = nextcircle;
nextcircle = &/*next circle to put into the polygon*/;
}
polygons.push_back(polygon);
}
int score = 0;
//do whatever you're going to do to evaluate the polygons here
return score;
}
int main(){
int bestscore = 0;
std::vector<int> bestarrangement; //contains position of each circle
std::vector<int> currentarrangement = /*whatever arbitrary starting arrangement is appropriate*/;
while(/*not done evaluating polygon configurations*/){
//fiddle with current arrangement a bit
int currentscore = doStuffWithPolygons();
if(currentscore > bestscore){
bestscore = currentscore;
bestarrangement = currentarrangement;
}
}
//somehow report what the best arrangement is
return 0;
}
If I properly understand how this stuff is handled, I shouldn't need any delete or .clear() calls because everything goes out of scope after the function call. Am I correct about this? Also, is there any part of the above that is needlessly complex, or else is insufficiently complex? Am I right in thinking that this is as simple as C++ will let me make it, or is there some way to avoid some of the roundabout construction?
And if you're response is going to be something like 'don't use void pointers' or 'just make a polygon class', unless you can explain how it will make the problem simpler, save yourself the trouble. I am the only one who will ever see this code, so I don't care about adhering to best practices. If I forget how/why I did something and it causes me problems later, that's my own fault for insufficiently documenting it, not a reason to have written it differently.
edit
Since at least one person asked, here's my original python, handling the polygon creation/evaluation part of the process:
#lots of setup stuff, such as the Circle and River classes
def evaluateArrangement(circles, rivers, tree, arrangement): #circles, rivers contain all the circles, rivers to be placed. tree is a class describing which rivers go between which circles, unrelated to the problem at hand. arrangement contains (x,y) position of the circles in the current arrangement.
polygons = []
unassignedCircles = range(len(circles))
while unassignedCircles:
polygon = []
start = unassignedCircles[0]
lastcircle = start
lastlastcircle = start
nextcircle = getNearest(start,arrangement)
unassignedCircles.pop(start)
unassignedCircles.pop(nextcircle)
while(not nextcircle = start):
polygon += [lastcircle]
polygon += getRiversBetween(tree, lastcircle,nextcircle)
lastlastcircle = lastcircle
lastcircle = nextcircle;
nextcircle = getNearest(lastcircle,arrangement,lastlastcircle) #the last argument here guarantees that the new nextcircle is not the same as the last lastcircle, which it otherwise would have been guaranteed to be.
unassignedCircles.pop(nextcircle)
polygons += [polygon]
return EvaluatePolygons(polygons,circles,rivers) #defined outside.
Void as template argument must be lower case. Other than that it should work, but I also recommend using a base class for that. With a smart pointer you can let the system handle all the memory management.

C++ I'm having some problems with arrays/dynamic memory

so I'm making a lame little snowboarding game (which is what all my questions have been about) and I'm having some issues.
I have a Biome class, which has a dynamic array to store the possible obstacles for that biome (obstsInBiome). Here is the constructor:
Biome::Biome(Obstacle obsts[], int amountOfObsts)
{
maxObstAmount = 10; // Max amount of obstacles to spawn in each biome
obstAmount = amountOfObsts; // The amount of obstacles passed in in the obsts parameter
// This part copys the array passed in to the obstsInBiome array (Class member to store obstacles)
// I think this is where the error may be
obstsInBiome = new Obstacle [amountOfObsts]; // Creating array to hold the possible obstacles in this biome
for (int x = 0; x < amountOfObsts; x++) // Filling the obstacle array with the obstacles passed in
{
obstsInBiome[x] = obsts[x];
}
}
Then to create a new biome, i use this:
Obstacle villageObsts[] = {tree, rock, cabin, log}; // tree, rock, and cabin are all Obstacles
Biome village(villageObsts, 4);
Somewhere within this code, the first element of obstsInBiome is not getting set properly.
village.obstsInBiome[0] is what I mean.
When i try to draw that to the screen, it doesn't appear and invisible collisions happen with the player as if they hit the obstacle. The rest of the array (rock, cabin, and log) all work perfectly. village.obstsInBiome[1 through 3] all work fine.
Can someone point out the error in this code?
At first glance, in particular at where you say you think the error is, it could be in the implementation of the copy constructor for the tree. I don't know what exactly an "Obstacle" is, nor do I know what the specific characteristics of those 4 instances are. Perhaps the tree instance has some kind of data that doesn't copy cleanly, whereas the other 3 do.
If you aren't sure what I mean by the copy constructor, that is probably a good thing to learn about.
http://en.wikipedia.org/wiki/Copy_constructor

Trying to figure out Vec2 class from Cinder

So I have a Node class that contains a member variable "center" that is a Vec2float*. The reason for this is because I want to use the drawSolidCircle function, and I need a Vec2float variable to represent the center. One of the questions I have is, is a Vec2float a vector, or a point in space? A lot of the member functions make it sound like some kind of vector class, yet the set() function only takes in two arguments which makes it seem like a point in space, and in order to draw a circle, you would need a point and a radius, not a vector. Also another problem I am having, is that if someone gives me 2 doubles, how can I convert them to Vec2float properly and set the x and y of center (if it even has an x and y). So for example in the function below, I am given an array of Entries and the length of it, 'n'. An entry has two member variables 'x' & 'y' which are both doubles. I want to create an array of Nodes and copy over that data to use it to draw circles.
cinder::Vec2<float>* center;//in my Node class
void function::build(Entry* c, int n) {
Node* nd = new Node[n];
for(int i = 0;i<n;i++) {
nd[i].center = //what goes here if c[i].x and c[i].y are doubles?
}
references:
Vec2 class: http://libcinder.org/docs/v0.8.4/classcinder_1_1_vec2.html
list of functions that draw shapes, im using drawSolidCircle: http://libcinder.org/docs/v0.8.4/namespacecinder_1_1gl.html
Any suggestions?
To make your life easy, you can use the cinder namespace. Add the following line after the includes at the top of your file.
using namespace ci;
which then enables you to simply write, for example:
Vec2f center(1.5f, 1.5f);
std::cout << center << std::endl;
Indeed, Vec2<float> is typedef'ed as Vec2f in Cinder.
Also, you shouldn't have to cast doubles into floats because they are casted implicitly, just pass them in!
Lastly, you really have to be careful with pointers. Most of the time, if I want an array of objects, I would use a std::vector, and use shared_ptr. Here's where I learned how to do just that: https://forum.libcinder.org/topic/efficiency-vector-of-pointers
I won't cover the whole theory behind vectors. Here's a good reference (using the Processing language): http://natureofcode.com/book/chapter-1-vectors/ In short, yes you should use them to store positions, but mathematically they are still vectors (you can think of a position vector as an arrow from the origin (0,0) to your current position).
I also suggest you have a look at the numerous samples provided with the library.
well i figured something out, it compiles for now, whether it will work for my program in the future is debatable. But here is what i did:
float f1 = (float)(c[i].x);
float f2 = (float)(c[i].y);
cinder::Vec2<float>* p = new cinder::Vec2<float>(f1,f2);
nd[i].center = p;
i casted the doubles to floats separately, then made a variable p using the Vec2 constructor, and then set center equal to that. like i said it compiles, we shall see if it works :D