How to draw a program graph similar to but with multiple methods?
As it seems the flow of data across methods are not necessarily in the order of declaration.
Mulitple Classes
public class Temp
{
//
private int lowThreshold = 18200; // 1
private int firstTier = 37000; // 2
private int firstTierBase = 3572; // 3
public Temp(int income, int age, bool medicareLevy, bool TBRLevy, bool LILevy) // 4
{
actualIncome = income - ReturnTax(income, age, medicareLevy, TBRLevy, LILevy); //5
}
private double ReturnTax(int income, int age, bool medicareLevy, bool TBRLevy, bool LILevy) // 6
{
double stage1 = 0.19; // 7
double stage2 = 0.325; // 8
double stage3 = 0.37; // 9
double stage4 = 0.45; // 10
double medicareLevyCharge = 0.02; // 11
double TBRLevyCharge = 0.02; // 12
....
Related
How to hide the arrow in Omnet++ v5.6.1 ?
I'm newbie, I'm using connectTo() method to create arrows.
gate->connectTo(gatein);
How to hide it ?
Thank you. This is my simulation's image:
my simulation
Sorry, it don't work for me. This is my code to create conection:
if (id != this->myId)
{
cGate *g;
cGate *g0;
int items;
int dist = distanceCal(x, y,this->xpos,this->ypos);
if (dist <= trRange)
{
items = this->gateSize("out");
ritems = mod->gateSize("in");
this->setGateSize("out",items+1);
mod->setGateSize("in",ritems+1);
g0 = this->gate("out",items);
g = mod->gate("in",ritems);
g0->connectTo(g);
//cDisplayString & disp = g0->getDisplayString();
//disp.setTagArg("ls",1,long (0));
}
}
This is my ned file:
// Base Station
simple BaseStation
{
parameters:
#display("i=device/antennatower_l");
int id;
int randInit;
int numNodes;
int xpos;
int ypos;
gates:
input in[];
output out[];
}
// Sensor node
simple SensorNode
{
parameters:
#display("i=misc/node");
int id;
int energy;
int xpos;
int ypos;
gates:
input in[];
output out[];
}
// ARPEES network
network WSN
{
parameters:
//numeric energy;
int energy;
//numNodes: numeric,
int numNodes;
//trRange: numeric,
int trRange;
//trRangeD0: numeric,
int protocol;
//protocol: numeric,
//showHideRange: numeric,
int showHideRange;
int ssRange;
int kRequire;
int rounds;
int frames;
int sRand;
int xMax;
int yMax;
#display("p=0,0;b=$xMax,$yMax,rect;o=white");
submodules:
bs: BaseStation {
parameters:
id = 1;
randInit = sRand;
xpos = int (xMax/2);
ypos = yMax+40;
numNodes = numNodes;
}
node[numNodes]: SensorNode {
parameters:
energy = energy;
id = index+2;
xpos = intuniform(10,xMax-10);
ypos = intuniform(10,yMax-10);
}
connections allowunconnected:
//{display("p=0,0;b=$xMax,$yMax,rect;o=white");} //DarkSeaGreen
}
}
What i need to do now ?
A connection may be hidden by setting its width to zero. The following code may be used to do it:
cDisplayString & disp = gate->getDisplayString();
disp.setTagArg("ls", 1, "0"); // 1 indicates argument of the Tag, 0 - width
Reference: Display String Tags.
I'm trying to create a class for employees, and have a problem with its constructor.
My class looks like that (please note the name parameter which is char* type):
class Employee {
int id;
char * name ;
float salary;
int hours;
int extra;
public:
//constructor
Employee(int, char *, float, int, int);
//Getters and Setters:
void setId(int a) { id = a; }
int getId() { return id; }
void setName(char * c) { name = c; }
char * getName() { return name; }
void setSalary(float f) { salary = f; }
float getSalary() { return salary; }
void setHours(int h) { hours = h; }
int getHours() { return hours; }
void setExtra(int e) { extra = e; }
int getExtra() { return extra; }
};
I built a constructor and I want it to have default parameters, and I don't know how to deal with the name parameter to have a default of let's say "unknown".
This is the constructor:
Employee::Employee(int i = 123456789, char * na, float sal = 30, int ho = 45, int ex = 10)
{
id = i;
name = na;
salary = sal;
hours = ho;
extra = ex;
}
You can use a character array, and initialise the array to point to the first element of the array. You can store the array for example as a static member:
// in the class definition
inline static char default_name[] = "unknown";
// in argument list of the constructor
... char * na = default_name, ...
Although, you may want to consider whether it makes sense for name to be pointer to non-const. Perhaps a pointer to const would suffice. In such case, you could initialise it to point to the literal "unknown" directly.
A cleaner version
class Employee {
int id = 0;
char *name = nullptr;
float salary = 0.0;
int hours = 0;
int extra = 0;
And you don't need to have constructors, this depends on the case, but you get the idea that by initializing the variables on the definition you reduce the inconsistency of having multiples constructors for example
I'm currently learning C++ by creating an N body simulation. In order to improve the number of bodies in my simulations I'm trying to implement the Barnes Hut approximation method. I'm actually coding a QuadTree structure in C++ (see below).
In order to construct my tree, I define three classes :
class Point : Corresponding to the bodies of my simulation with x and y position as attributes
class Rectangle : Corresponding to the properties of the leaves of my tree with position and dimension attributes
class QuadTree : Corresponding to my QuadTree and its children (leaves) and a Rectangle object, a vector of Point objects, four leaves objects (QuadTree) and a boolean to say if it contain leaves or not.
I wrote a main function where I define my tree with its boudaries and I divide it to make appear four leaves. Then I ask informations about my tree and the associated subtrees using the function void QuadTree::get_information(). This function allows to show some information about the current tree by displaying if it has children or not (divided), its boudaries, and the points it contains. If it has children, then we apply the function QuadTree::get_information() on each child and we repeat the process.
The problem is that the code give an error of this kind :
QuadTree : Capacity = 1, Divided (0:False, 1:True) = 0
Rectangle : Center Position = (0, 0), Width = 10, Height = 10
-------------------
-------------------
QuadTree : Capacity = 1, Divided (0:False, 1:True) = 1
Rectangle : Center Position = (0, 0), Width = 10, Height = 10
Northwest :
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
It seems that I have a problem of allocation memory. I think I make a bad use of the pointers NW, NE, SW, SE defined in the QuadTree class.
I'm not an expert of the utilisation of the memory allocation on C++, maybe I do a naive error. Do you see something wrong about the way a manage these pointers ? Could you suggest a solution to my problem and make run my algorithm ?
Thank you so much for your time ! :)
#include <iostream> //For console output/input
#include <fstream> //Allows to read/write files
#include <math.h> //Basic mathematic functions
#include <vector> //For dynamic arrays
#include <string> //Operations on strings
#include <tuple>
#include <cmath>
#include <sstream>
using namespace std;
class Point
{
public :
double get_x();
double get_y();
void set_x(double xp);
void set_y(double yp);
void get_information();
private :
double x;
double y;
};
double Point::get_x(){return x;}
double Point::get_y(){return y;}
void Point::set_x(double xp){x = xp;}
void Point::set_y(double yp){y = yp;}
class Rectangle
{
public :
double get_x();
double get_y();
double get_w();
double get_h();
void set_x(double xc);
void set_y(double yc);
void set_w(double wc);
void set_h(double hc);
bool contain(Point pt);
void get_information();
private :
double x;
double y;
double w;
double h;
};
double Rectangle::get_x() {return x;}
double Rectangle::get_y() {return y;}
double Rectangle::get_w() {return w;}
double Rectangle::get_h() {return h;}
void Rectangle::set_x(double xc) {x = xc;}
void Rectangle::set_y(double yc) {y = yc;}
void Rectangle::set_w(double wc) {w = wc;}
void Rectangle::set_h(double hc) {h = hc;}
class QuadTree
{
public :
Rectangle get_boundary();
int get_capacity();
void set_boundary(double xc, double yc, double wc, double hc);
void set_rectangle(Rectangle rect);
void set_capacity(int capacity);
void insert(Point pt);
void subdivide();
void set_divided();
bool is_divided();
void get_information();
QuadTree getNW();
QuadTree getNE();
QuadTree getSW();
QuadTree getSE();
void setNW(QuadTree nw);
void setNE(QuadTree ne);
void setSW(QuadTree sw);
void setSE(QuadTree se);
private :
QuadTree* NW=NULL;
QuadTree* NE=NULL;
QuadTree* SW=NULL;
QuadTree* SE=NULL;
Rectangle boundary;
vector<Point> p;
bool divided = false;
};
QuadTree QuadTree::getNW(){return *NW;}
QuadTree QuadTree::getNE(){return *NE;}
QuadTree QuadTree::getSW(){return *SW;}
QuadTree QuadTree::getSE(){return *SE;}
void QuadTree::setNW(QuadTree nw){NW=&nw;}
void QuadTree::setNE(QuadTree ne){NE=≠}
void QuadTree::setSW(QuadTree sw){SW=&sw;}
void QuadTree::setSE(QuadTree se){SE=&se;}
bool QuadTree::is_divided(){return divided;}
bool Rectangle::contain(Point pt)
{
return (pt.get_x() > get_x() - get_w()
and pt.get_x() < get_x() + get_w()
and pt.get_y() > get_y() - get_h()
and pt.get_y() < get_y() + get_h());
}
Rectangle QuadTree::get_boundary() {return boundary;}
void QuadTree::set_boundary(double xc, double yc, double wc, double hc)
{
boundary.set_x(xc);
boundary.set_y(yc);
boundary.set_w(wc);
boundary.set_h(hc);
}
//int QuadTree::get_capacity() {return n;}
//void QuadTree::set_capacity(int capacity) {n = capacity;}
void QuadTree::set_divided() {divided = true;}
void QuadTree::set_rectangle(Rectangle rect) {boundary = rect;}
void QuadTree::subdivide()
{
double xc = boundary.get_x();
double yc = boundary.get_y();
double wc = boundary.get_w();
double hc = boundary.get_h();
Rectangle nw;
nw.set_x(xc-wc/2.);
nw.set_y(yc+hc/2.);
nw.set_w(wc/2.);
nw.set_h(hc/2.);
Rectangle ne;
ne.set_x(xc+wc/2.);
ne.set_y(yc+hc/2.);
ne.set_w(wc/2.);
ne.set_h(hc/2.);
Rectangle sw;
sw.set_x(xc-wc/2.);
sw.set_y(yc-hc/2.);
sw.set_w(wc/2.);
sw.set_h(hc/2.);
Rectangle se;
se.set_x(xc-wc/2.);
se.set_y(yc+hc/2.);
se.set_w(wc/2.);
se.set_h(hc/2.);
QuadTree oNW, oNE, oSW, oSE;
oNW.set_rectangle(nw);
oNE.set_rectangle(ne);
oSW.set_rectangle(sw);
oSE.set_rectangle(se);
setNW(oNW);
setNE(oNE);
setSW(oSW);
setSE(oSE);
//NW = &oNW;
//NE = &oNE;
//SW = &oSW;
//SE = &oSE;
}
void QuadTree::insert(Point pt)
{
if (! get_boundary().contain(pt) ) {cout<<"Hello 1"<<endl; return; }
if (p.size() < 1)
{
cout<<"Hello 2"<<endl;
p.push_back(pt); // Insert element at the end
}
else
{
if (!divided)
{
QuadTree::subdivide();
QuadTree::set_divided();
}
}
NW->insert(pt);
NE->insert(pt);
SW->insert(pt);
SE->insert(pt);
}
void Point::get_information(){cout<<"Point : x = "<<get_x()<<"; y = "<<get_y()<<endl;}
void Rectangle::get_information(){cout<<"Rectangle : Center Position = ("<<get_x()<<", "<<get_y()<<"), Width = "<<get_w()<<", Height = "<<get_h()<<endl;}
void QuadTree::get_information()
{
cout<<"QuadTree : Capacity = "<<" 1"<<", Divided (0:False, 1:True) = "<<divided<<endl;
boundary.get_information();
/*cout<<"Points_in : "<<endl;
int siz = p.size();
for (int ii=0; ii<siz; ii++)
{
p[ii].get_information();
}*/
if (divided) {
cout<<" Northwest : "<<endl;
getNW().get_information();
cout<<" Northeast : "<<endl;
getNE().get_information();
cout<<" Southwest : "<<endl;
getSW().get_information();
cout<<" Southeast : "<<endl;
getSE().get_information();
}
}
int main()
{
QuadTree tree;
tree.set_boundary(0., 0., 10., 10.);
tree.get_information();
cout<<"-------------------"<<endl;
tree.subdivide();
tree.set_divided();
cout<<"-------------------"<<endl;
tree.get_information();
}
I'm trying to implement the A* algorithm for finding the fastest path to the destination. I can find the path when the destination is not far away from the player. But it's freezes when I take a position that is far away from the player. Can anyone help me out with this? Can't find it anyway.
int Controller::findPathfindingNodes(int xdes, int ydes)
{
std::vector<std::shared_ptr<Tile>> tiles = model->getAllLimitTiles(); //all the tiles where we can move
std::shared_ptr<Protagonist> prota = model->getAllProtagonist(); //get data from protagonist
int currentX = prota->getXPos(); //get xpos of prota
int currentY = prota->getYPos(); //get ypos of prota
openList.clear();
closedList.clear();
mylist.clear();
//return 50;
std::shared_ptr<Tile> endPoint = model->getCoordinate(QPointF(xdes,ydes));
std::shared_ptr<Tile> startPoint = model->getCoordinate(QPointF(currentX,currentY));
int sumtotal = abs((currentX - xdes) + (currentY - ydes));
//we insert our start position, we have no parrent yet
PathFinding* start = new PathFinding(startPoint,currentX, currentY, 0, sumtotal,nullptr);
//this value we insert in our openList
openList.insert(start->getXCoord() + (model->getCols()+1)*start->getYCoord(), start);
bool pathFound = false;
int i = 0;
int pathcost;
//do whil path is found
while(!pathFound){
QHashIterator<int, PathFinding*> iterator(openList);
PathFinding* parent;
iterator.next();
parent = iterator.value();
//we take the next tile, and we take the one with the lowest value
while(iterator.hasNext()){
iterator.next();
//checking lowest f value
if((iterator.value()->getGcost() + iterator.value()->getHcost()) < (parent->getGcost() + parent->getHcost())){
parent = iterator.value();
}
}
//here we check if we are at the destionation. if we are we return our pathcost.
if(atDestionation(parent,endPoint)){
pathFound = true;
while(parent->hasParent()){
mylist.append(parent);
parent = parent->getParent();
}
//we calculate what the pathcost is and return it
pathcost = calculatePathCost(mylist);
return pathcost;
}else{
int parent_x = parent->getXCoord();
int parent_y = parent->getYCoord();
i++;
clearLists(parent);
filllists(parent,endPoint);
}
}
}
To put the values of the nodes in the open & closed list I do with this:
void Controller::filllists(PathFinding *parent,std::shared_ptr<Tile> endPoint)
{
int xPosNode = parent->getXPos();
int yPosNode = parent->getYPos();
//while found location
for(int x = -1; x < 2; x++) {
for(int y = -1; y <2; y++) {
int p_x = xPosNode + x;
int p_y = yPosNode + y;
// Is this coordinate within the world?
if(p_x >= 0 && p_x < model->getCols() && p_y >= 0 && p_y < model->getRows()) {
//we check if the tile exist (if it's no infinity tile)
if(model->tileExist(QPointF(p_x,p_y))){
// Already in open list > Check if current node is a better parent
if((!openList.value(p_x))+ (model->getCols() + 1)*(p_y)){
// Not in open and not in closed list > Possible candidate
if((!closedList.value(p_x))+ (model->getCols() + 1)*(p_y)){
int h_value = calculateHvalue(parent->getXCoord(),parent->getYCoord(),endPoint->getXPos(),endPoint->getYPos());
//int g_value = parent->getGcost() + calculateTileCost(parent->getXCoord(),parent->getYCoord(),p_x,p_y);
int g_value = calculateGvalue(parent, p_x, p_y);
std::shared_ptr<Tile> tile = model->getCoordinate(QPointF(p_x,p_y));
PathFinding* move = new PathFinding(tile,p_x, p_y, g_value, h_value, parent);
int number = move->getXCoord() + (model->getCols()+1)*move->getYCoord();
openList.insert(move->getXCoord() + (model->getCols()+1)*move->getYCoord(), move);
}
}
}
}
}
}
}
My header file looks like:
class Controller : public QObject
{
Q_OBJECT
public:
Controller(std::shared_ptr<Model> &modelPtr,std::shared_ptr<View> &viewPtr);
// void checkTile(QString position,PathFinding *parent, std::shared_ptr<Tile> endPoint, int pos);
void checkAboveTile(PathFinding *parent, std::shared_ptr<Tile> endPoint, int pos);
void checkBelowTile(PathFinding *parent, std::shared_ptr<Tile> endPoint, int pos);
void checkLeftTile(PathFinding *parent, std::shared_ptr<Tile> endPoint, int pos);
void checkRightTile(PathFinding *parent, std::shared_ptr<Tile> endPoint, int pos);
bool atDestionation(PathFinding *parent, std::shared_ptr<Tile> endPoint);
float calculateTileCost(int xposnew,int yposnew, int xpos, int ypos);
int calculateHvalue(int p_x,int p_y, int des_x, int des_y);
int calculateGvalue(PathFinding *parent, int x, int y);
void filllists(PathFinding *parent, std::shared_ptr<Tile> endPoint);
//QPair<QList<QPointF>, float> generatePath(Tile* endPoint);
//Openlist contains the nodes to be examined
QHash <int, PathFinding *> openList;
//ClosedList has the nodes that are already examined
QHash <int, PathFinding *> closedList;
QList<QPointF> pathlist;
void clearLists(PathFinding *parent);
QList<PathFinding*> mylist;
int calculatePathCost(QList<PathFinding*> mylist);
int findPathfindingNodes(int xdes, int ydes);
private:
std::shared_ptr<Model> model;
std::shared_ptr<View> view;
int heurCost;
signals:
void atDestination(int xPos,int yPos);
void gotoview(int xPos,int yPos);
public slots :
void goToDestination(int xDestination, int yDestination);
};
#endif // CONTROLLER_H
When I try to output the path which is travelled the I can see that it put sometimes the same position in mylist.
X1 value : 2 Y1 value : 3
X1 value : 1 Y1 value : 3
X1 value : 0 Y1 value : 3
X1 value : 1 Y1 value : 3
X1 value : 1 Y1 value : 3
X1 value : 2 Y1 value : 3
X1 value : 2 Y1 value : 4
X1 value : 3 Y1 value : 4
X1 value : 3 Y1 value : 4
X1 value : 3 Y1 value : 5
X1 value : 2 Y1 value : 6
X1 value : 2 Y1 value : 6
X1 value : 1 Y1 value : 6
X1 value : 0 Y1 value : 6
X1 value : 0 Y1 value : 7
X1 value : 0 Y1 value : 6
X1 value : 0 Y1 value : 5
This is how the player walked, can see that he sometimes uses the same parent over again.
I can't see anywhere that you move visited nodes from the open list to the closed list.
This would account for visiting the same place multiple times.
if((!openList.value(p_x)) + (model->getCols() + 1)*(p_y)) is very likely to be true.
(Adding 0 or 1 to (model->getCols() + 1)*p_y is probably non-zero.)
I believe you meant if(!openList.value(p_x + (model->getCols() + 1)*p_y)).
(Same issue with the closed list.)
This would also account for multiple visits, as you repeatedly insert the same nodes in the open list.
I would suggest abstracting out the index calculation:
int index(shared_ptr<Model> model, int x, int y)
{
return x * (model->getCols() + 1)* y;
}
and using that instead of error-prone code reproduction, e.g.
openList.insert(index(model, start->getXCoord(), start->getYCoord()), start);
// ...
if(!openList.value(index(model, p_x, p_y)))
It's also a good idea to add tracing output along the way.
Both base classes, Arc and Lines, are derived from class Shape.
The compiler says Ojbect b1 "error: shape is ambiguous". I know that two instances of Shape are being created, but don't know how to resolve it?
Graph_lib::Box b1(Point,100,100), 100,100);
win1.attach(b1);
This class will be able to draw a box with rounded corners. I just wrote the code for the Box Lines part, I didn't get to the Arc yet since this won't even work.
//------------------------------------------------------------------------------
struct Box : Lines , Arc {
Box(Point xy, int ww, int hh);
void Top_segment();
void Bottom_segment();
void Left_side_segment();
void Right_side_segment();
void draw_lines() const;
int height() const { return h; }
int width() const { return w; }
private:
int h; // height
int w; // width
double width_tenth; //10% of the width that will calculate the length to remove from each side to make room for the arcs
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Box::Box(Point xy, int ww, int hh): w(ww), h(hh)
{
width_tenth = (xy.x + w) * 0.10;
if (h<=0 || w<=0) error("Bad box: non-positive side");
}
//------------------------------------------------------------------------------
void Box::Top_segment()
{
double top_seg_begin_w; //where the line segment will begin after deducting 10% of w;
double top_seg_end_w; //where the line segment will end after deducting 10% of w;
top_seg_begin_w = xy.x + width_tenth;
top_seg_end_w = (xy.x + w) - width_tenth;
Lines::add(Point(top_seg_begin_w,xy.y),Point(top_seg_end_w,xy.y));
}
//------------------------------------------------------------------------------
void Box::Bottom_segment()
{
double bottom_seg_begin_w;
double bottom_seg_end_w;
bottom_seg_begin_w = xy.x + width_tenth;
bottom_seg_end_w = (xy.x + w) - width_tenth;
double y_bottom = xy.y + h;
Lines::add(Point(bottom_seg_begin_w,y_bottom),Point(bottom_seg_end_w,y_bottom));
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Box::Left_side_segment()
{
double left_seg_begin_h;
double left_seg_end_h;
left_seg_begin_h = xy.y + width_tenth;
left_seg_end_h = (xy.y + h) - width_tenth;
double x_left = xy.x;
Lines::add(Point(x_left,left_seg_begin_h),Point(x_left,left_seg_end_h));
}
//------------------------------------------------------------------------------
void Box::Right_side_segment()
{
double right_seg_begin_h;
double right_seg_end_h;
right_seg_begin_h = xy.y + width_tenth;
right_seg_end_h = (xy.y + h) - width_tenth;
double x_right = xy.x + w;
Lines::add(Point(x_right,right_seg_begin_h),Point(x_right,right_seg_end_h));
}
//------------------------------------------------------------------------------
Use virtual inheritance for classes Lines and Arc. For example
class Lines : virtual public Shape
{
//...
};
class Arc : virtual public Shape
{
//...
};