I understand as Set size of vector of vectors at run time
describes, one can declare vector of vector as
vector<vector<int> > ref;
then resize the first level by
ref.resize(i);
and push element at the 2nd level:
ref[i].push_back(23);
But how are vector of vector aligned in memory?
For simple vector, it's a container and align its element continuously, like an array; but in the case of vector of vector, I couldn't see the picture.
As the size of each inner vector (the vector in vector of vector) size might change, does the outer vector of vector (the vector in vector of vector) align inner vectors continously? Does the outer vector researve memeory space for each inner vector? what if one vector overshoot?
The size of the vector<int> struct that is stored in ref is constant. Common implementations has this as three pointers, or around 12 bytes on 32-bit architectures, or 24 bytes on shiny new 64-bit architectures.
So ref manages roughly ref.capacity() * 12 bytes of continuous storage.
Each element/vector<int> in ref manages its own integers independent of the elements ref manages. In the artistic rendering below ref.size() == ref.capacity() for the sake of simplicity.
So your
ref.resize(i);
only affects the top row. Your
ref[i].push_back(23);
only affects the i-th column.
vector<vector <int>> m;
The inner vector or rows are implemented as independent
objects on the free store.
Elements in each row are compactly stored, capable of performing dynamic allocation through push_back and resizing.
It is not necessary for each inner vector in the vector< vector<int> > to have the same size. So, the inner-vectors (not their elements) are not stored contiguously. That means, the first element of m[i] is not stored in the address immediately next to the last element of m[i-1].
does the outer vector of vector (the vector in vector of vector) align inner vectors continously?
No. See point#2
Does the outer vector researve memeory space for each inner vector?
No. See point#1. you need to resize or do push_back into inner vector.
how are vector of vector aligned in memory?
vector<T> vec;
consumes this much memory
sizeof(vector<T>) + (vec.size() ∗ sizeof(T))
where,
sizeof(vector<T>) = 12 bytes
and T is vector<int> for a vector of vector.
So, the memory consumed for a 3-by-4 vector<vector<int>> would be.
= sizeof(vector<vector<int>>) + (vec.size() * sizeof(vector<int>))
= 12 + 3 * 12
= 48
what if one vector overshoot?
vector.resize function corrupting memory when size is too large
A vector<vector<int>> could look like this in memory:
+-+-+-+
|b|e|c| vector<vector<int>
+-+-+-+
| | |
| | +-------------------+
| | |
| +---------------+ |
| | |
V V V
+-+-+-+-+-+-+-+-+-+
|b|e|c|b|e|c|b|e|c| 3x vector<int>
+-+-+-+-+-+-+-+-+-+
| | | | | | | | |
| | | | | | | | +-------------+
| | | | | | | | |
| | | | | | | +-------+ |
| | | | | | | | |
| | | | | | V V V
| | | | | |+-+-+-+-+-+
| | | | | ||i|i|i|i|i| 5x int
| | | | | |+-+-+-+-+-+
| | | | | |
| | | | +-+---+
| | | | |
| | | V V
| | |+-+-+-+-+
| | ||i|i|i|i| 4x int
| | |+-+-+-+-+
| | |
| +-+-----------+
| |
V V
+-+-+-+-+-+-+-+-+
|i|i|i|i|i|i|i|i| 8x int
+-+-+-+-+-+-+-+-+
Here b denotes the begin() poiner, e denotes the end() pointer and c denotes the capacity() pointer.
You see, that the rows are not contiguous in memory as you would expect from a matrix structure. Every vector (inner and outer vectors) takes care of it's own memory allocations. The outer vector does not care about what it's elements are doing.
I am trying to find the bounding polygon of a set of adjacent cells(row,col) ( convertable to rectangles) in a 2d tiled world.
Processing the cells in a for loop and using the neighbourhood property of the adjacent cells I could eliminate all internal edges and store the rest of the edges.
The edges are stored in std::vector;
Now I need to merge the edges where there is a common vertex and slope is the same.
After merging the edges I need to make the bounding polygon, starting from a vertex going counter clockwise.
Please help to find a method to make it possible.
I think this is a simple algorithm to achieve that.
Consider we have this as input:
| | | | | |
-+---+---+---+---+---+-
| | | | | |
-+---+---+---+---+---+-
| | | a | | |
-+---+---+---+---+---+-
| | b | c | d | |
-+---+---+---+---+---+-
| | | e | | |
-+---+---+---+---+---+-
| | | | | |
Where a, b, c, d, and e are our input tiles stored as a vector of pairs (Coordinates):
std::vector<std::pair<unsigned,unsigned>> tiles;
What we want is this:
| | | | | |
-+---+---+---+---+---+-
| | | | | |
-+---+---*---*---+---+-
| | | | | |
-+---*---* *---*---+-
| | | |
-+---*---* *---*---+-
| | | | | |
-+---+---*---*---+---+-
| | | | | |
The algorithm works as follows:
Build an array of booleans enclosing the entire set of tiles. You have to trasverse the set to find the bounds of that rectangle. Set as true the positions of the array which represent a tile of the set, and as false otherwise.
The output in the example will be (T is true and f is false):
+---+---+---+
| f | T | f |
+---+---+---+
| T | T | T |
+---+---+---+
| f | T | f ]
+---+---+---+
Now you have to traverse the border of the hull polygon. Start at the first element marked as true in the flag array and trasverse the vertices in the same direction until you reach the first vertex again, using this rules:
If the two tiles in front of the current direction/position are false, turn clockwise and add the vertex to the output list (polygon):
(* are vertices added to the polygon, X the current vertex, the arrow the current direction)
+---+---+---+
| f | f | f |
*---+---X---+ --->
| T | T | f |
*---+---+---+
| f | T | f ]
+---+---+---+
goes to
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---X---+
| f | T | f ]
+---+---+---+
If one tile is false and one true, go in the same direction (Note that true-false or false-true means you are in a border):
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---X---+
| f | T | f ]
+---+---+---+
goes to
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---+---+
| f | T | f ]
+---+---X---+
If both tiles are true, turn counter-clockwise and add the vertex to the output list (Note that true-true means you have reached part of the set of tiles, a "wall"):
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---X---+
| f | T | T ]
+---+---+---+
goes to
+---+---+---+
| f | f | f |
+---+---*---+
| T | T | f | --->
+---+---*---X
| f | T | T ]
+---+---+---+
Considerations:
tilemap coordinates vs flag-array coordinates
The flag-array represents the rectangle region of the tilemap where the tiles are placed. So the tilemap-coordinates of its first element (tile) is (left,top) where left is the minimum x-coordinate of the selected set of tiles, and top is the minimum y-coordinate of the selected set of tiles.
In the second step of the agorithm, you trasverse the frontier (border) of the set of tiles, using the array as a guide. Note that what you really trasverse is that array, so you have to translate the coordinates from flag-coordinates (logical coordinates) to tilemap-coordinates (physical coordinates) to store the vertices of the polygon. Of course thats easy.
Also note that the algorithm abstract steps trasverse vertices of edges (physical tile coordinates), not logical-coordinates. You have to be sure what "I'm in that vertex" means and what "advance" and "turn" mean in terms of flag-array coordinates.
Border conditions and the front-tiles check
We have defined three rules to advance along the border of the set of tiles. We have used the flag-array as a guide to decide what to do (Advance, turn clockwise, or turn counter-clockwise). Note that when the current vertex is in the border of the array, you could (you should) consider that it have neighbour tiles with a false value.
For example:
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---+---+
| f | T | f ]
+---+---X---+
goes to
+---+---+---+
| f | f | f |
*---+---*---+ <--
| T | T | f |
*---+---+---+
| f | T | f ]
+---X---*---+
exactly as if it was this:
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---+---+
| f | T | f ]
+---+---X---+
| f | f | f |
*---*---*---+
Possible optimisations
The first step computes the flag array because the algorithm takes the set of tiles selected as a vector. If your tile engine supports it, you could add a property to the tiles (bool selected) and pass the tilemap directly, avoiding the computation and the vertex cooordinates transformations.
Example
Given this flag-array:
+---+---+---+
| T | f | f |
+---+---+---+
| T | T | T |
+---+---+---+
| f | T | T |
+---+---+---+
The execution works as follows (Note that the drawings are the state AFTER the execution of the step):
Find the first true tile. In this case (0,0). So we start at one of its vertex (bottom-left vertex, looking upwards, for example. Note that because its the first true tile, you could use that vertex being sure that it belongs to the polygon. So add that first vertex to the polygon):
Current position: (0,1)
Polygon: {(0,1)}
+---+---+---+ ^
| T | f | f | |
X---+---+---+ |
| T | T | T |
+---+---+---+
| f | T | T |
+---+---+---+
Start the trasverse. In this case, the front tiles are false-true, so advance:
Current position: (0,0)
Polygon: {(0,1)}
X---+---+---+ ^
| T | f | f | |
*---+---+---+ |
| T | T | T |
+---+---+---+
| f | T | T |
+---+---+---+
The front tiles are false-false (We are in a border), so turn clockwise and add the vertex:
Current position: (1,0)
Polygon: {(0,1),(0,0)}
*---X---+---+
| T | f | f |
*---+---+---+
| T | T | T | --->
+---+---+---+
| f | T | T |
+---+---+---+
Now the fron-tiles are false-false (One is out of the array, and the other is false). turn clockwise and add the vertex:
Current position: (1,1)
Polygon: {(0,1),(0,0),(1,0)}
*---*---+---+
| T | f | f | |
*---X---+---+ |
| T | T | T | v
+---+---+---+
| f | T | T |
+---+---+---+
The two front-tiles are true: Turn counter-clockwise and add the vertex:
Current position: (1,2)
Polygon: {(0,1),(0,0),(1,0),(1,1)}
*---*---+---+
| T | f | f |
*---*---X---+
| T | T | T | --->
+---+---+---+
| f | T | T |
+---+---+---+
One tile is false and the other is true: Advance:
Current position: (1,3)
Polygon: {(0,1),(0,0),(1,0),(1,1)}
*---*---+---+
| T | f | f |
*---*---+---X
| T | T | T | --->
+---+---+---+
| f | T | T |
+---+---+---+
Two false tiles (Both out of array): Turn clockwise and add the vertex:
Current position: (2,3)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1)}
*---*---+---+
| T | f | f | |
*---*---+---* |
| T | T | T | v
+---+---+---X
| f | T | T |
+---+---+---+
One true and one false(Out of array): Advance:
Current position: (3,3)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1)}
*---*---+---+
| T | f | f | |
*---*---+---* |
| T | T | T | v
+---+---+---+
| f | T | T |
+---+---+---X
Two false(Out of array) front-tiles: Turn clockwise and add the vertex:
Current position: (2,3)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3)}
*---*---+---+
| T | f | f |
*---*---+---*
| T | T | T | <---
+---+---+---+
| f | T | T |
+---+---X---*
true-false (One true and one out of bounds): Advance:
Current position: (1,3)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3)}
*---*---+---+
| T | f | f |
*---*---+---*
| T | T | T | <---
+---+---+---+
| f | T | T |
+---X---+---*
false-false (One false and one out of bounds): Turn clockwise and add the vertex:
Current position: (1,2)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3)}
*---*---+---+
| T | f | f | ^
*---*---+---* |
| T | T | T | |
+---X---+---+
| f | T | T |
+---*---+---*
true-true front-tiles: Turn counter-clockwise and add the vertex:
Current position: (0,2)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3),(1,2)}
*---*---+---+
| T | f | f |
*---*---+---*
| T | T | T | <---
X---*---+---+
| f | T | T |
+---*---+---*
false-false front-tiles: Turn clockwise and add the vertex:
Current position: (0,1)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3),(1,2),(0,2)}
*---*---+---+
| T | f | f | ^
X---*---+---* |
| T | T | T | |
*---*---+---+
| f | T | T |
+---*---+---*
The current vertex is the first vertex of the polygon: The execution have finished. The result is as follows:
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3),(1,2),(0,2)}
*---*
| |
* *-------*
| |
*---* |
| |
*-------*
Because of tiles, this is a 'special case' of finding boundary polygon. I would go with some simple approach.
Tile (x,y) consist of vertices [(x,y), (x+1,y), (x+1,y+1), (x,y+1)]. Vertex is a part of boundary polygon if it is in 1, 2 or 3 tiles. To find vertices on boundary it is enough to count number of tiles it is in. For that it is enough to pass through tiles and increment vertex appearance count for tile 4 vertices. Vertices with tile count 1, 2 or 3 are on the boundary polygon.
To order vertices it is enough to start from some vertex on a boundary and look for a neighbouring vertex that is also on a boundary. To traverse vertices in same direction it is important to take a care of direction order of neighbouring vertices to check. E.g. if last vertex is on -x, than order of directions to check is +y, +x, -y.
Since direction of last edge is known, if next edge is in the same direction than that vertex is for a removal. If region is simple connected, than removal can be known also from tile count. If tile count of a vertex is 2 than vertex is for removal.
For now we don't have guarantee that order is clockwise. That can be check by checking (some of) upper-most edge(s) is it in clockwise direction. If it is not, than reverse polygon.
how can i use tree.hh: an STL-like C++ tree class to populate my tree and obtain the tree below. some help would be appreciate. A and G are root node
thank's
A G
______|____ |
/ | \ |
B C D H
| | | |
| E | |
\_____/ | |
| | |
F | |
|_________|______|
|
I
|
J
In then code above, i'm using depth first search to enumarate item in the list. i have few data formated like this
typedef tree<std::string> TreeNode;
typedef struct
{
int nBases;
char * name;
} BASES;
BASES rgbases[] =
{
{0xB, "J"},
{0xA, "I"},
{0x1, "H"},{0x0, "G"},
{0x5, "F"},{0x2, "E"},{0x1, "C"},{0x0, "A"},
{0x1, "D"},{0x0, "A"},
{0x1, "B"},{0x0, "A"}
};
//here i'm trying to populate my tree
void populateTree(TreeNode &tr, BASES *pBaseArray, int numBase)
{
int n = 0;
while ( n < numBase )
{
BASES *pBase = &pBaseArray[n];
if ( pBase->nBases > 0) // Check for children of the new node
populateTree(tr, pBaseArray + (n + 1),pBase->nBases);
// i suppose i need to insert tree code part here
n += pBase->nBases + 1;
}
}
void BuildTree(TreeNode &tr)
{
populateTree(tr, rgBases, _countof(rgBases));
}
A tree, spanning the original graph presented, could be obtained in removing the edges linking node A with B and D(or possibly the edges linking node A with C and D). The tree class would then be applicable:
A G A G
| | ______| |
| | / |
B C D H B C D H
| | | | | | | |
| E | | | E | |
\______/ | | \______/ | |
| | | | | |
F | | F | |
|_________|______| |__________|______|
| |
I I
| |
J J
Edges in the above tree giving rise to loops, could be recorded separately, that is AB and AD, could be noted in a structure, apart from the tree class. Merging the tree with such a structure would recover the original graph.