I need a spatial index in C - c

I'm working on my gEDA fork and want to get rid of the existing simple tile-based system1 in favour of a real spatial index2.
An algorithm that efficiently finds points is not enough: I need to find objects with non-zero extent. Think in terms of objects having bounding rectangles, that pretty much captures the level of detail I need in the index. Given a search rectangle, I need to be able to efficiently find all objects whose bounding rectangles are inside, or that intersect, the search rectangle.
The index can't be read-only: gschem is a schematic capture program, and the whole point of it is to move things around the schematic diagram. So things are going to be a'changing. So while I can afford insertion to be a bit more expensive than searching, it can't be too much more expensive, and deleting must also be both possible and reasonably cheap. But the most important requirement is the asymptotic behaviour: searching should be O(log n) if it can't be O(1). Insertion / deletion should preferably be O(log n), but O(n) would be okay. I definitely don't want anything > O(n) (per action; obviously O(n log n) is expected for an all-objects operation).
What are my options? I don't feel clever enough to evaluate the various options. Ideally there'd be some C library that will do all the clever stuff for me, but I'll mechanically implement an algorithm I may or may not fully understand if I have to. gEDA uses glib by the way, if that helps to make a recommendation.
Footnotes:
1 Standard gEDA divides a schematic diagram into a fixed number (currently 100) of "tiles" which serve to speed up searches for objects in a bounding rectangle. This is obviously good enough to make most schematics fast enough to search, but the way it's done causes other problems: far too many functions require a pointer to a de-facto global object. The tiles geometry is also fixed: it would be possible to defeat this tiling system completely simply by panning (and possibly zooming) to an area covered by only one tile.
2 A legitimate answer would be to keep elements of the tiling system, but to fix its weaknesses: teaching it to span the entire space, and to sub-divide when necessary. But I'd like others to add their two cents before I autocratically decide that this is the best way.

A nice data structure for a mix of points and lines would be an R-tree or one of its derivatives (e.g. R*-Tree or a Hilbert R-Tree). Given you want this index to be dynamic and serializable, I think using SQLite's R*-Tree module would be a reasonable approach.
If you can tolerate C++, libspatialindex has a mature and flexible R-tree implementation which supports dynamic inserts/deletes and serialization.

Your needs sound very similar to what is used in collision detection algorithms for games and physics simulations. There are several open source C++ libraries that handle this in 2-D (Box2D) or 3-D (Bullet physics). Although your question is for C, you may find their documentation and implementations useful.
Usually this is split into a two phases:
A fast broad phase that approximates objects by their axis-aligned bounding box (AABB), and determines pairs of AABBs that touch or overlap.
A slower narrow phase that calculates the points of geometric overlap for pairs of objects whose AABBs touch or overlap.
Physics engines also use spatial coherence to further reduce the pairs of objects that are compared, but this optimization probably won't help your application.
The broadphase is usually implemented with an O(N log N) algorithm like Sweep and prune. You may be able to accelerate this by using it in conjunction with the current tile approach (one of Nvidia's GPUGems describes this hybrid approach). The narrow phase is quite costly for each pair, and may be overkill for your needs. The GJK algorithm is often used for convex objects in this step, although faster algorithms exist for more specialized cases (e.g.: box/circle and box/sphere collisions).

This sounds to like an application well-suited to a quadtree (assuming you are interested only in 2D.) The quadtree is hierarchical (good for searching) and it's spatial resolution is dynamic (allowing higher resolution in areas that need it).
I've always rolled my own quadtrees, but here is a library that appears reasonable: http://www.codeproject.com/Articles/30535/A-Simple-QuadTree-Implementation-in-C

It is easy to do. It's hard to do fast. Sounds like a problem I worked on where there was a vast list of min,max values and given a value it had to return how many min,max pairs overlapped that value. You just have it in two dimensions. So you do it with two trees for each direction. Then do a intersection on the results. This is really fast.
#include <iostream>
#include <fstream>
#include <map>
using namespace std;
typedef unsigned int UInt;
class payLoad {
public:
UInt starts;
UInt finishes;
bool isStart;
bool isFinish;
payLoad ()
{
starts = 0;
finishes = 0;
isStart = false;
isFinish = false;
}
};
typedef map<UInt,payLoad> ExtentMap;
//==============================================================================
class Extents
{
ExtentMap myExtentMap;
public:
void ReadAndInsertExtents ( const char* fileName )
{
UInt start, finish;
ExtentMap::iterator EMStart;
ExtentMap::iterator EMFinish;
ifstream efile ( fileName);
cout << fileName << " filename" << endl;
while (!efile.eof()) {
efile >> start >> finish;
//cout << start << " start " << finish << " finish" << endl;
EMStart = myExtentMap.find(start);
if (EMStart==myExtentMap.end()) {
payLoad pay;
pay.isStart = true;
myExtentMap[start] = pay;
EMStart = myExtentMap.find(start);
}
EMFinish = myExtentMap.find(finish);
if (EMFinish==myExtentMap.end()) {
payLoad pay;
pay.isFinish = true;
myExtentMap[finish] = pay;
EMFinish = myExtentMap.find(finish);
}
EMStart->second.starts++;
EMFinish->second.finishes++;
EMStart->second.isStart = true;
EMFinish->second.isFinish = true;
// for (EMStart=myExtentMap.begin(); EMStart!=myExtentMap.end(); EMStart++)
// cout << "| key " << EMStart->first << " count " << EMStart->second.value << " S " << EMStart->second.isStart << " F " << EMStart->second.isFinish << endl;
}
efile.close();
UInt count = 0;
for (EMStart=myExtentMap.begin(); EMStart!=myExtentMap.end(); EMStart++)
{
count += EMStart->second.starts - EMStart->second.finishes;
EMStart->second.starts = count + EMStart->second.finishes;
}
// for (EMStart=myExtentMap.begin(); EMStart!=myExtentMap.end(); EMStart++)
// cout << "||| key " << EMStart->first << " count " << EMStart->second.starts << " S " << EMStart->second.isStart << " F " << EMStart->second.isFinish << endl;
}
void ReadAndCountNumbers ( const char* fileName )
{
UInt number, count;
ExtentMap::iterator EMStart;
ExtentMap::iterator EMTemp;
if (myExtentMap.empty()) return;
ifstream nfile ( fileName);
cout << fileName << " filename" << endl;
while (!nfile.eof())
{
count = 0;
nfile >> number;
//cout << number << " number ";
EMStart = myExtentMap.find(number);
EMTemp = myExtentMap.end();
if (EMStart==myExtentMap.end()) { // if we don't find the number then create one so we can find the nearest number.
payLoad pay;
myExtentMap[ number ] = pay;
EMStart = EMTemp = myExtentMap.find(number);
if ((EMStart!=myExtentMap.begin()) && (!EMStart->second.isStart))
{
EMStart--;
}
}
if (EMStart->first < number) {
while (!EMStart->second.isFinish) {
//cout << "stepped through looking for end - key" << EMStart->first << endl;
EMStart++;
}
if (EMStart->first >= number) {
count = EMStart->second.starts;
//cout << "found " << count << endl;
}
}
else if (EMStart->first==number) {
count = EMStart->second.starts;
}
cout << count << endl;
//cout << "| count " << count << " key " << EMStart->first << " S " << EMStart->second.isStart << " F " << EMStart->second.isFinish<< " V " << EMStart->second.value << endl;
if (EMTemp != myExtentMap.end())
{
myExtentMap.erase(EMTemp->first);
}
}
nfile.close();
}
};
//==============================================================================
int main (int argc, char* argv[]) {
Extents exts;
exts.ReadAndInsertExtents ( "..//..//extents.txt" );
exts.ReadAndCountNumbers ( "..//../numbers.txt" );
return 0;
}
the extents test file was 1.5mb of:
0 200000
1 199999
2 199998
3 199997
4 199996
5 199995
....
99995 100005
99996 100004
99997 100003
99998 100002
99999 100001
The numbers file was like:
102731
104279
109316
104859
102165
105762
101464
100755
101068
108442
107777
101193
104299
107080
100958
.....
Even reading the two files from disk, extents were 1.5mb and numbers were 780k and the really large number of values and lookups, this runs in a fraction of a second. If in memory it would lightning quick.

Related

What's a performant and clean way to parse a binary file in C?

I'm parsing a custom binary file structure for which I know the format.
The general idea is that each file is broken up into blocks of sequential bytes, which I want to separate and decode in parallel.
I'm looking for a readable, performant alternative to decode_block()
Here's what I'm currently working with:
#include <stdio.h>
int decode_block(uint8_t buffer[]);
int main(){
FILE *ptr;
ptr = fopen("example_file.bin", "rb");
if (!ptr){
printf("can't open.\n");
return 1;
}
int block1_size = 2404;
uint8_t block1_buffer[block1_size];
fread(block1_buffer, sizeof(char), block1_size, ptr);
int block2_size = 3422;
uint8_t block2_buffer[block2_size];
fread(block2_buffer, sizeof(char), block2_size, ptr);
fclose(ptr);
//Do these in parallel
decode_block(block1_buffer);
decode_block(block2_buffer);
return 0;
}
int decode_block(uint8_t buffer[]){
unsigned int size_of_block = (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0];
unsigned int format_version = buffer[4];
unsigned int number_of_values = (buffer[8] << 24) + (buffer[7] << 16) + (buffer[6] << 8) + buffer[5];
unsigned int first_value = (buffer[10] << 8) + buffer[9];
// On and on and on
int ptr = first_value
int values[number_of_values];
for(int i = 0; i < number_of_values; i++){
values[i] = (buffer[ptr + 3] << 24) + (buffer[ptr + 2] << 16) + (buffer[ptr + 1] << 8) + buffer[ptr];
ptr += 4
}
// On and on and on
return 0
}
It feels a little redundant to be reading the entire file into a byte array and then interpreting the array byte by byte. Also it makes for very bulky code.
But since I need to operate on multiple parts of the file in parallel I can't think of another way to do this. Also, is there a simpler or faster way to convert the early bytes in buffer into their respected metadata values?
I'd:
use "memory mapped files" to avoid loading the raw data (e.g. mmap() in POSIX systems). Note that this is not portable "plain C", but almost every OS supports a way to do this.
make sure that the file format specification requires that the values are aligned to a 4-byte boundary in the file and (if you actually do need to support signed integers) that the values are stored in "2's compliment" format (and not "sign and magnitude" or anything else)
check that the file complies with the specification as much as possible (not just the alignment requirement, but including things like "data can't start in middle of header", "data start + entries * entry_size can't exceed file's size", "version not recognized", etc).
have different code for little-endian machines (e.g. where which code is used may be selected at compile time with an #ifdef), where you can cast the memory mapped file's data to int32_t (or uint32_t). Note that the code you've shown (e.g. (buffer[ptr + 3] << 24) + (buffer[ptr + 2] << 16) + (buffer[ptr + 1] << 8) + buffer[ptr]) is broken for negative numbers (even on "2's compliment" machines); so the alternative code (for "not little-endian" cases) will be more complicated (and slower) than yours is. Of course if you don't need to support negative numbers you should not be using any signed integer type (e.g. int), and quite frankly you shouldn't be using "possibly 16 bit" int for 32-bit values anyway.
determine how many threads you should use (maybe command line argument; maybe by asking OS how many CPUs the computer actually has). Start the threads and tell them which "thread number" they are (where existing thread is number 0, first spawned thread is number 1, etc).
let the threads calculate their starting and ending offset (in the memory mapped file) from their "thread number", a global "total threads", a global "total entries" and a global "offset of first entry". This is mostly just division with special care for rounding. Note that (to avoid global variables) you could pass a structure containing the details to each thread instead. No safeguards (e.g. locks, critical sections) will be needed for this data because threads only read it.
let each thread parse its section of the data in parallel; then wait for them all to finish (e.g. maybe "thread number 0" does "pthread_join()" if you don't want to keep the threads for later use).
You will probably also need to check that all values (parsed by all threads) are within an allowed range (to comply with the file format specification); and have some kind of error handling for when they don't (e.g. when the file is corrupt or has been maliciously tampered with). This could be as simple as a (global, atomically incremented) "number of dodgy values found so far" counter; which could allow you to display an "N dodgy values found" error message after all values are parsed.
Note 1: If you don't want to use a memory mapped file (or can't); you can have one "file reader thread" and multiple "file parser threads". This takes a lot more synchronization (it devolves into a FIFO queue with flow control - e.g. with provider thread doing some kind of "while queue full { wait }" and consumer threads doing some kind of "while queue empty { wait }"). This extra synchronization will increase overhead and make it slower (in addition to being more complex), compared to using memory mapped files.
Note 2: If the file's data isn't cached by the operating system's file data cache, then you'll probably be bottlenecked by file IO regardless of what you do and using multiple threads probably won't help performance for that case.

Storing input values in structs for fastest comparison later

I'm sampling eight input ports and comparing the values up to ten times a second.
These inputs will be XOR'd against a similar field, indicating which signals are set to "Active Low", then an AND operation to mask out input signals that are not going to be compared (though all signals are sampled, whether compared or not).
So this is an example for the sampling. I've created a struct where the signals will be stored and then saved in memory. This struct contains a lot of other values, so replacing the whole struct is not an option. Anyway, these input values need to be saved in a efficient way so I later on can perform fast XOR and AND operations with my masks.
void SampleData(){
// These are not all values o be sampled, only inputs
currentSample.i0 = RD13_bit;
currentSample.i1 = RD12;
currentSample.i2 = RD11;
currentSample.i3 = RD10;
currentSample.i4 = RE12;
currentSample.i5 = RE13;
currentSample.i6 = RF8;
currentSample.i7 = RF9;
}
This is an example of the comparison I need
checkInputSignals(){
activated = ((inputValues ^ activeLowInputs) & activeInputsMask);
if(activated ){
importantMethod();
}
}
I've tried a bitfield, but I couldn't get the operators to work, and I've no knowledge about the effiency using bitfield. Efficiency in this project is not focused on memory, but speed and comfort. How should I store my three fields? If it helps, I am using a dsPic33EP microprocessor.
If using a 'char' or 'uint_8', my sample method would look like this, right? And this does not seem to be the most elegant solution.
unsigned char inputValues;
void SampleData(){
currentSample.i0 = RD13_bit;
currentSample.i1 = RD12;
currentSample.i2 = RD11;
currentSample.i3 = RD10;
currentSample.i4 = RE12;
currentSample.i5 = RE13;
currentSample.i6 = RF8;
currentSample.i7 = RF9;
// For the masking
inputValues += currentSample.i7;
inputValues = (inputValues << 1) + currentSample.i6;
inputValues = (inputValues << 1) + currentSample.i5;
inputValues = (inputValues << 1) + currentSample.i4;
inputValues = (inputValues << 1) + currentSample.i3;
inputValues = (inputValues << 1) + currentSample.i2;
inputValues = (inputValues << 1) + currentSample.i1;
inputValues = (inputValues << 1) + currentSample.i0;
}
And I would have to do the same for my masks, for example.
void ConfigureActiveLowInputs(){
activeLowInputs += currentCalibration->I0_activeLow;
activeLowInputs = (activeLowInputs << 1) + currentCalibration->I1_activeLow;
activeLowInputs = (activeLowInputs << 1) + currentCalibration->I2_activeLow;
activeLowInputs = (activeLowInputs << 1) + currentCalibration->I3_activeLow;
activeLowInputs = (activeLowInputs << 1) + currentCalibration->I4_activeLow;
activeLowInputs = (activeLowInputs << 1) + currentCalibration->I5_activeLow;
activeLowInputs = (activeLowInputs << 1) + currentCalibration->I6_activeLow;
activeLowInputs = (activeLowInputs << 1) + currentCalibration->I7_activeLow;
}
There must be a better solution than bit shifting?
Some things I think you need to know.
Don't use bit fields. Apart from being non-portable, they make this kind of bit-twiddling harder, not easier.
Don't use run-time shifts. Get the compiler to do your work.
Do read code, study and practice. Learning bit-twiddling can be hard, and from your code I don't think you're quite there yet.
If we're going to help there are some things we need to know.
You mention 8 ports. Are they single bit ports, or single ports with multiple bits?
You mention 3 fields. What are they?
Your sample code uses + operators, which are rarely used in bit operations. Why?
In C the code usually ends up with a set of macros and defines, plus a few small functions. It's all quite simple, generates good code, and runs fast without too much effort. If we only knew what you were trying to do.
You seem to be storing individual bits is separate structure members, and then packing them to word on the fly to be able to apply masks; but it is probably more efficient to pack them into a word, and use a mask to access the individual bits when necessary.
The members i0, i1 etc. are probably unnecessary. It would be simpler to pack the bits directly into a uint8_t member, then write functions or macros to return individual bits where necessary.
uint8_t void SampleData()
{
return (RD13_bit << 7 ) |
(RD12 << 6) |
(RD11 << 5) |
(RD10 << 4) |
(RE12 << 3) |
(RE13 << 2) |
(RF8 << 1) |
RF9 ;
}
Then:
currentSample.i = SampleData() ;
Then you can apply masks to that directly. If you need to access individual bits (and if you don't, why make then separate members in the first case?) then for example:
#include <stdbool.h>
#define GETBIT( word, bit ) (((word) & (1<<bit) != 0)
bool i6 = GETBIT( currentSample.i, 6 ) ;

MPI - Parallel dot product calculation

I'm struggling to modify a program that takes two files as input (each representing a vector) and calculates the dot product between them. It's supposed to be done in parallel, but I was told that the number of points in each file might not be evenly divisible by the number of available processors and each process might read from incorrect positions within the files. What I mean is that, if there are four processors, the first 250 points might be correctly read and calculated but the second processor might read over those same 250 points and provide an incorrect result. This is what I've done so far. Any modifications I've made are noted.
#include "fstream"
#include "stdlib.h"
#include "stdio.h"
#include "iostream"
#include "mpi.h"
int main(int argc, char *argv[]){
MPI_Init(&argc, argv);
//parse command line arguments
if( argc < 3 || argc > 3){
std::cout << "*** syntax: " << argv[0] << " vecFile1.txt vecFile2.txt" << std::endl;
return(0);
}
//get input file names
std::string vecFile1(argv[1]);
std::string vecFile2(argv[2]);
//open file streams
std::ifstream vecStream1(vecFile1.c_str());
std::ifstream vecStream2(vecFile2.c_str());
//check that streams opened properly
if(!vecStream1.is_open() || !vecStream2.is_open()){
std::cout << "*** Could not open Files ***" << std::endl;
return(0);
}
//if files are open read their lengths and make sure they are compatible
long vecLength1 = 0; vecStream1 >> vecLength1;
long vecLength2 = 0; vecStream2 >> vecLength2;
if( vecLength1 != vecLength2){
std::cout << "*** Vectors are no the same length ***" << std::endl;
return(0);
}
int numProc; //New variable for managing number of processors
MPI_Comm_size(&numProc,MPI_COMM_WORLD); //Added line to obtain number of processors
int subDomainSize = (vecLength1+numProc-1)/numProc; //Not sure if this is correct calculation; meant to account for divisibility with remainders
//read in the vector components and perform dot product
double dotSum = 0.;
for(long i = 0; i < subDomainSize; i++){ //Original parameter used was vecLength1; subDomainSize used instead for each process
double ind1 = 0.; vecStream1 >> ind1;
double ind2 = 0.; vecStream2 >> ind2;
dotSum += ind1*ind2;
}
std::cout << "VECTOR DOT PRODUCT: " << dotSum << std::endl;
MPI_Finalize();
}
Aside from those changes, I don't know where to go from here. What can I do to make this program properly calculate a dot product of two vectors using paralleling processing with two text files as input? Each contains 100000 points so it's impractical to manually modify the files.
I wont write the code here as it seems to be an assignment problem but I would try to give you some tips to go into right direction.
Each processor has an assigned rank that can be found out using the MPI_Comm_rank API. So for parallel processing you can divide the vectors of the files among the processors such that processor with rank r processes the vectors r*subdomainsize to (r+1)*subdomainsize - 1.
You need to make sure that the vector from correct position is read from the file by a particular processor. Use seek api to go to the right offset and then call the read(>>) operator of your filestream.
For calculating subdomainsize I am not sure whether the equation you mentioned works or not. There can be several approaches. The simplest is to use vectorlength/numProc as subdomainsize. Each processor can handle subdomainsize elements, however the last processor (rank == numProc) will handle the remaining elements.
After the for loop, you should use a reduction operation to collect the individual sums from the processors and sum it up globally for the final result. See MPI_Reduce.
Use Barrier for synchronization between the processors. A barrier must be placed after the for loop and before calling reduction.

Map Creation Size Error

So, I'm working at inventing my own tile map creation and I got a problem on size. The maximum size (which I did not set) is <700x700, anything higher makes it crash. First, I thought it's something I got wrong when making the "presentation version" which outputs the result on screen -> ScreenShot, but now I just finished making it more compact and tried using 800x800 and it still has the 7 limit, but I have no idea why. Since the code isn't that big I will show it here. If you have some tips I don't mind taking them.
#include <iostream>
#include <string.h>
#include <fstream>
#include <ctime>
#include <cstdlib>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#define _WIN32_WINNT 0x0501
#include <windows.h>
using namespace std;
int main()
{
sf::Vector2i Size;
int Points,rands,PointsCheck=1,x,y,RandX,RandY,CurrentNumber=1;
srand(time(0));
bool Done=false,Expanded,Border;
ofstream Out("txt.txt");
/***/
cout << "Size X-Y = "; cin >> Size.x >> Size.y;cout << endl;
cout << "MAX Points - " << (Size.x*Size.y)/10 << endl;
cout << "Number of POINTS = ";cin >> Points ;cout << endl;
/***/
int PixelMap[Size.x+1][Size.y+1];
/***/
for (x=1;x<=Size.x;x++) for (y=1;y<=Size.y;y++) PixelMap[x][y]=0;
/***/
while(PointsCheck<=Points)
{
rands=1+(rand()%10);
RandX=1+(rand()%(Size.x));RandY=1+(rand()%(Size.y));
if (rands==1 && PointsCheck<=Points && PixelMap[RandX][RandY]==0)
{PixelMap[RandX][RandY]=CurrentNumber;CurrentNumber+=2;PointsCheck++;}
}
/***/
while(Done==false)
{
Done=true;
for(x=1;x<=Size.x;x++)
for(y=1;y<=Size.y;y++)
if(PixelMap[x][y]%2!=0 && PixelMap[x][y]!=-1)
{
if (PixelMap[x+1][y]==0) PixelMap[x+1][y]=PixelMap[x][y]+1;
if (PixelMap[x-1][y]==0) PixelMap[x-1][y]=PixelMap[x][y]+1;
if (PixelMap[x][y+1]==0) PixelMap[x][y+1]=PixelMap[x][y]+1;
if (PixelMap[x][y-1]==0) PixelMap[x][y-1]=PixelMap[x][y]+1;
}
for(x=1;x<=Size.x;x++)
for(y=1;y<=Size.y;y++)
if(PixelMap[x][y]!=0 && PixelMap[x][y]%2==0) {PixelMap[x][y]--;Done=false;}
}
for(x=1;x<=Size.x;x++){
for(y=1;y<=Size.y;y++)
{Out << PixelMap[x][y] << " ";}Out << endl;}
//ShowWindow (GetConsoleWindow(), SW_HIDE);
}
What you have here is the concept from which this site gets its name. You have a stack overflow:
int PixelMap[Size.x+1][Size.y+1];
If you want to allocate a large amount of memory, you need to do it dynamically (on the heap).
You can do this any number of ways. Since you are using C++, I recommend using a std::vector. The only trick is making the array 2-dimensional. Usually this is done in the same way as the one you allocated on the stack, except you don't get language syntax to help you:
vector<int> PixelMap( (Size.x+1) * (Size.y+1) );
Above, you'll need to calculate the linear index from the row/column. Something like:
int someval = PixelMap[ row * (size.y+1) + column ];
If you really want to use the [row][column] indexing syntax, you can either make a vector-of-vectors (not recommended), or you can index your rows:
vector<int> PixelMapData( (Size.x+1) * (Size.y+1) );
vector<int*> PixelMap( Size.x+1 );
PixelMap[0] = &PixelMapData[0];
for( int i = 0; i < Size.x+1; i++ ) {
PixelMap[i+1] = PixelMap[i] + Size.y + 1;
}
Now you can index in 2D:
int someval = PixelMap[row][col];
There's a couple of problems with your code:
First off:
int PixelMap[Size.x+1][Size.y+1];
for (x=1;x<=Size.x;x++)
for (y=1;y<=Size.y;y++)
PixelMap[x][y]=0;
In the above snipped you are never setting the value of PixelMap[0][0], or PixelMap0, etc. Basically those values will be undefined. Arrays in C++ are 0 indexed so you need to be sure you address those. Also, why are you using Size.x+1 and Size.y+1? Something feels wrong about that.
A better loop would be:
int PixelMap[Size.x][Size.y];
for (x=0;x<Size.x;x++)
for (y=0;y<Size.y;y++)
PixelMap[x][y]=0;
Second, this next bit of code is illegible:
while(PointsCheck<=Points)
{
rands=1+(rand()%10);
RandX=1+(rand()%(Size.x));
RandY=1+(rand()%(Size.y));
if (rands==1 && PointsCheck<=Points && PixelMap[RandX][RandY]==0)
{
PixelMap[RandX][RandY]=CurrentNumber;
CurrentNumber+=2;
PointsCheck++;
}
}
You're only incrementing PointsCheck if
PointsCheck <= Points
Why? You test for this to be true in your while condition. PointsCheck doesn't get incremented anywhere before this test.
rands is never guaranteed to be equal to 1 by the way, so your loop could go on for eternity (though unlikely).
The next loop suffers from similar problems as above:
while(Done==false)
{
Done=true;
What's the reason for this? You never break out of the while loop, and you never set Done to false, so the next block of code will only ever be executed once. remove this bit.
Your for-loops that follow should start at 0 and go while < Size(Size.x and Size.y)
for(x=0;x<Size.x;x++)
for(y=0;y<Size.y;y++)
Fix these issues first, and then if you still have a problem we can move on. And for all our sake, please use brackets {} to scope your for loops and if statements so that we can follow. Also, separate commands onto separate lines. It's a lot of work for us to follow more than one semicolon per line.
EDIT
Since you seem unwilling to fix these issues first:
This could be an issue with the amount of memory allocated on the stack for your program. If you're trying to create an array of 800x800 integers, then you're using 800*800*4 bytes = 2.4 MB of data. I know this is higher than visual studio's default limit of 1 MB, but since a 700x700 array uses 1.8 MB, then whatever program you're using has a higher default (or you set visual studio's higher, but not high enough).
See if you can set your limit to at least 3 MB. More is better, though. If this doesn't fix your scaling problem up to 800, then you have other issues.
EDIT2
I just noticed this:
sf::Vector2i Size;
//unimportant stuff
cin >> Size.x >> Size.y;
int PixelMap[Size.x+1][Size.y+1];
Vector2i will probably have default values for x and y. If you want to dynamically allocate more than what those are, you cannot statically say
PixelMap[Size.x][Size.y]
You need to dynamically allocate the array. I strongly suggest using something like a std::vector > for this
e.g.(untested code):
sf::Vector2i Size;
//unimportant stuff
cin >> Size.x >> Size.y;
std::vector<vector<int> > PixelMap;
//Initialize values to 0
for(size_t i=0; i < Size.x; ++i){
vector<int> nextVec;
for(size_t j=0; j < Size.y; ++j){
nextVec.push_back(0);
}
PixelMap.push_back(nextVec);
}
Not sure if this has anything to do with your crash (I would have added a comment, but I don't have the reputation), but here's a problem I noticed:
Your array indexing scheme is not consistent. Since you're using index 1 to indicate the first element, your bounds checking should look like this...
if (y!=1 && y!=Size.y && x!=1 && x!=Size.x && ...
...instead of this...
if (y!=0 && y!=Size.y && x!=0 && x!=Size.x && ...
[EDIT]
I just tried this:
...
cout << "asdf" << endl;
int PixelMap[Size.x+1][Size.y+1];
cout << "asdf" << endl;
...
and verified it's a stack overflow problem. So, as others mentioned above, allocate your pixel map on the heap and it should be fine.
BTW, this code...
int PixelMap[Size.x+1][Size.y+1];
is not standard C++. It's an extension some compilers provide, called 'variable length arrays'. Check this out for more info -> Why aren't variable-length arrays part of the C++ standard?
[/EDIT]

How to save a vector of keypoints using openCV

I was wondering if it was possible to save out a vector of cv::KeyPoints using the CvFileStorage class or the cv::FileStorage class. Also is it the same process to read it back in?
Thanks.
I am not sure about what you really expect :
The code I provide you is simply an example, to show how the file storage works in the OpenCV C++ bindings. It assumes here that you write in the XML file all the Keypoints separately, with their name being their position in the vector they were stored in.
It assumes aswell that when you read them back, you know the number of them you want to read, if not, the code is a little bit more complex. You'll find a way (if for instance you read the filestorage and test what it gives you, if it doesn't give you anything, then it means there is no more point to read) -it's just an idea, you have to find a solution, maybe this piece of code will be enough for you.
I should precise that i use ostringstream to put the integer in the string and by the way change the place where it will be written in the *.yml file.
//TO WRITE
vector<Keypoint> myKpVec;
FileStorage fs(filename,FileStorage::WRITE);
ostringstream oss;
for(size_t i;i<myKpVec.size();++i) {
oss << i;
fs << oss.str() << myKpVec[i];
}
fs.release();
//TO READ
vector<Keypoint> myKpVec;
FileStorage fs(filename,FileStorage::READ);
ostringstream oss;
Keypoint aKeypoint;
for(size_t i;i<myKpVec.size();<++i) {
oss << i;
fs[oss.str()] >> aKeypoint;
myKpVec.push_back(aKeypoint);
}
fs.release();
Julien,
char* key;
FileStorage f;
vector<Keypoint> keypoints;
//writing
write(f, key, keypoints);
//reading
read(f[key], keypoints);
int main() {
String filename = "data.xml";
FileStorage fs(filename,FileStorage::WRITE);
Vector<Mat> vecMat;
Mat A(3,3,CV_32F, Scalar(5));
Mat B(3,3,CV_32F, Scalar(6));
Mat C(3,3,CV_32F, Scalar(7));
vecMat.push_back(A);
vecMat.push_back(B);
vecMat.push_back(C);
//ostringstream oss;
for(int i = 0;i<vecMat.size();i++) {
stringstream ss;
ss << i;
string str = "x" + ss.str();
fs << str << vecMat[i];
}
fs.release();
vector<Mat> matVecRead;
FileStorage fr(filename,FileStorage::READ);
Mat aMat;
int countlabel = 0;
while(1) {
stringstream ss;
ss << countlabel;
string str = "x" + ss.str();
cout << str << endl;
fr[str] >> aMat;
if (fr[str].isNone() == 1) {
break;
}
matVecRead.push_back(aMat.clone());
countlabel ++;
}
fr.release();
for( unsigned j = 0; j < matVecRead.size(); j++){
cout << matVecRead[j] << endl;
}
}
Put a letter eg 'a' infront of the numbering as the OPENCV XML Format specify the xml KEY must start with a letter.
This is a code to save Vector<Mat> for visual studio 2010, i think it will works for Vector<KeyPoints>

Resources