Hello, all,
I am pretty new to C++ and I need to write a program for calculating radio propagation path loss based on ray tracing, C++ is used for its faster processing rather than MATLAB. I have a question about passing 2D arrays between functions.
One of the files looks something like this:
/*this file gets the map information, the map is a 3D vector database which
contains the coordinates of all the corners of the buildings(because the
actual dataset is not available now, so only a text file made up by my own is
used for testing). */
#include "mapInfo.h"
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
MapInfo::MapInfo()
{
}
//this function read the map in uda format and returns a 2D array contains building infomation.
//in form of: [building_number][no_of_corners x y.....wall_thickness bld_type]
std::vector<std::vector<double> > MapInfo::getMapInfo()
{
char str[100];
char name[80];
int max_corner_no = 10;
int building_number;
int corner_number;
int index;
char *tokenPtr;
cout << "Enter file name:";
cin.getline(name,79);
ifstream dataFile(name,ios::in);
if(!dataFile)
{
cerr << "File could not be opened\n";
exit(1);
}
// skip the first 5 lines
for (int i=0; i<5;i++)
{
dataFile.getline(str,99);
}
//get the number of buildings from the 6th line
dataFile.getline(str,99);
no_of_blds = atoi(&str[0]);
std::vector<std::vector<double> > bld_info(no_of_blds,std::vector<double>(max_corner_no*2+3));
/*bld_info = new double *[no_of_blds];
for (int i=0; i<=no_of_blds-1; i++)
bld_info[i]=new double[max_corner_no*2+3]; //*2 because we need x and y coordinates, rest 3 for number
//of corners, wall thickness and building type respectively.*/
// now get the data
while(!dataFile.eof())
{
index=1;
dataFile.getline(str,99);
// get the building coordinates
tokenPtr = strtok(str," ");
//get the building number first
building_number = atoi(tokenPtr);
tokenPtr = strtok(NULL," ");
//now get the number of corners of this building
corner_number = atof(tokenPtr);
no_of_corners += atoi(tokenPtr);
tokenPtr = strtok(NULL," ");
bld_info[building_number-1][0] = corner_number;
while (tokenPtr != NULL)
{
bld_info[building_number-1][index] = atof(tokenPtr);
tokenPtr = strtok(NULL," ");
index++;
}
}
return bld_info;
}
//this function returns the number of buildings in the map
int MapInfo::getNumOfBlds ()
{
return no_of_blds;
}
//this function returns the total number of corners for all the buildings
int MapInfo::getNumOfCorners ()
{
return no_of_corners;
}
//this function returns the gradient of a straight line given two points
double MapInfo::getGrad(double x1,double y1,double x2,double y2)
{
return (y2-y1)/(x2-x1);
}
//this function returns the coordinates of all the corners in a 2D array
//in form of [corner_number][x,y,bld_num]
std::vector<std::vector<double> > MapInfo::getCoordinates(std::vector<std::vector<double> > map_info,int total_blds,int total_corners)
{
int bld_corners;
int x,y;
int coor_index=0;
/*CoordinateArray = new double *[total_corners];
for (int i=0; i<total_corners; i++)
CoordinateArray[i] = new double [3]; // 3 here for [x,y,bld_num]*/
cout<<"here is fine\n";
std::vector<std::vector<double> > CoordinateArray(total_corners,std::vector<double>(3));
for (int bld_num=0; bld_num<total_blds; bld_num++)
{
bld_corners = map_info[bld_num][0];
int cnt=1;
for (int j=0; j<bld_corners; j++)
{
x=map_info[bld_num][cnt];
y=map_info[bld_num][cnt+1];
CoordinateArray[coor_index][0] = x;
CoordinateArray[coor_index][1] = y;
CoordinateArray[coor_index][2] = bld_num+1;
coor_index++;
cnt+=2;
}
}
return CoordinateArray;
}
//this function evaluates all the wall functions
//input of this function should be map_info evaluated from getMapInfo()
//output of this function is the coefficients of each line(wall) in form y=kx+b,
//in form of [wall_num][k,b,x1,y1,x2,y2,bld_num]
std::vector<std::vector<double> > MapInfo::getWallFuncs(std::vector<std::vector<double> > coorArray,int num_of_walls) //number of walls equals to number of corners
{
double x1,y1,x2,y2;
double temp_x,temp_y;
//initialize temp_x and temp_y values to the first corner coordinate in the file
temp_x = coorArray[0][0];
temp_y = coorArray[0][1];
double k,b; //straight line coefficients
//allocate memory for the wall coefficients and relevant numbers
/*WallFuncs = new double *[num_of_walls];
for (int i=0; i<num_of_walls; i++)
WallFuncs[i] = new double [7]; //7 here stores all the relevant numbers*/
std::vector<std::vector<double> > WallFuncs(num_of_walls,std::vector<double>(7));
for (int wall_num=0; wall_num<num_of_walls-1; wall_num++)
{
//test if the two walls belong to the same building
//same building in this case
if(coorArray[wall_num][2] == coorArray[wall_num+1][2])
{
x1 = coorArray[wall_num][0];
y1 = coorArray[wall_num][1];
x2 = coorArray[wall_num+1][0];
y2 = coorArray[wall_num+1][1];
k = getGrad(x1,y1,x2,y2);
b = y2-k*x2;
}
// two edges from different buildings
else
{
x1 = coorArray[wall_num][0];
y1 = coorArray[wall_num][1];
x2 = temp_x;
y2 = temp_y;
k = getGrad(x1,y1,temp_x,temp_y);
b = y1-k*x1;
temp_x = coorArray[wall_num+1][0];
temp_y = coorArray[wall_num+1][1];
}
WallFuncs[wall_num][0] = k;
WallFuncs[wall_num][1] = b;
WallFuncs[wall_num][2] = x1;
WallFuncs[wall_num][3] = y1;
WallFuncs[wall_num][4] = x2;
WallFuncs[wall_num][5] = y2;
WallFuncs[wall_num][6] = coorArray[wall_num][2];
}
//last wall coefficients
k = getGrad(x2,y2,temp_x,temp_y);
b = y2-k*x2;
WallFuncs[num_of_walls-1][0] = k;
WallFuncs[num_of_walls-1][1] = b;
WallFuncs[num_of_walls-1][2] = x2;
WallFuncs[num_of_walls-1][3] = y2;
WallFuncs[num_of_walls-1][4] = temp_x;
WallFuncs[num_of_walls-1][5] = temp_y;
WallFuncs[num_of_walls-1][6] = coorArray[num_of_walls-1][2];
return WallFuncs;
}
now I want to test if this program can give correct result, so in another file which contains only the main function, I got:
#include "mapInfo.h"
#include "firstLayerVisibility.h"
#include <iostream>
using namespace std;
int main()
{
MapInfo map;
FirstLayerVisibility flv;
std::vector<std::vector<double> > angle_result;
std::vector<std::vector<double> > angle_result2;
std::vector<std::vector<double> > mapInfo;
std::vector<std::vector<double> > coorArray;
std::vector<std::vector<double> > wallFunc;
mapInfo = map.getMapInfo();
cout<<mapInfo[0][0]<<" "<<mapInfo[0][1]<<" "<<mapInfo[0][2]<<" "<<mapInfo[0][3]<<" "<<mapInfo[0][4]<<"\n";
int total_corners = map.getNumOfCorners();
int total_blds = map.getNumOfBlds();
[B]coorArray[/B] = map.getCoordinates(mapInfo,total_blds,total_corners);
angle_result = flv.compAngleArray(coorArray,130,300,total_corners);
angle_result2 = flv.sortAngles(angle_result,map.getNumOfCorners());
wallFunc = map.getWallFuncs(coorArray,total_corners);
for(int i=0; i<16; i++)
{
cout<<wallFunc[i][0]<<" "<<wallFunc[i][1]<<" "<<wallFunc[i][2]<<" "<<wallFunc[i][3]<<" " <<wallFunc[i][4]<<" "<<wallFunc[i][5]<<" " <<wallFunc[i][6]<<"\n";
}
cout << "total number of corners is: " << map.getNumOfCorners();
for(int i=0; i<16; i++)
{
cout<<angle_result[i][0]<<" "<<angle_result[i][1]<<" "<<angle_result[i][2]<<" "<<angle_result[i][3]<<" " <<angle_result[i][4] <<" "<<angle_result[i][5]<<"\n";
}
cout << "total number of corners is: " << map.getNumOfCorners();
flv.visiblePoints(wallFunc,angle_result2,130,300,16);
return 0;
}
I am using VS 2008, now when I run the test it reports an error "this program has requested the Runtime to terminate it in an unusual way...", the program terminates at the creation of the second 2D array (map.getCoordinates()), where the first array "mapInfo" is all right. I think this is something to do with the memory allocation, as before I used dynamic 2D array allocation like:
WallFuncs = new double *[num_of_walls];
for (int i=0; i<num_of_walls; i++)
WallFuncs = new double [7];
and this reports an error of invalid memory allocation with a big value. But when I write all my functions within one file, it works properly. So I am just wondering if this is anything to do with the "OO design"? In the above test, when a new object "map" is created, the contents of "mapInfo" can be printed out with correct values, but the program terminates at "coorArray" for error of invalid memory allocation(for using dynamic 2D array allocation) or Runtime error if using std::vector<std::vector<double> > type. Can anyone please help me to work this out? I do need to pass 2D arrays between functions for large number of calculations, so what would be a solution for this?
Another question is that at some later stage of this program, if I want to develop a GUI for it using MFC in visual C++, do I create another "Win32 project" or "MFC application"? As currently the above is a "win32 console application", so what is the basic idea to convert it into a application with GUI using MFC?
Thank you very much for your attention, any comment would be helpful.