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();
}
Related
Hello I I have problem on my assignment which I need to init base constructor which is point multiple time in derived constructor which is polygon.
The polygon have at least 3 point , each point have a coordinate value. any one have ideas how to init base constructor multiple time in constructor init?
The inheritance ideas is not my ideas , is the assignment question.
this is the question
Polygon (constructor) creates a polygon with npoints vertices, the vertices take their values from those stored in the array points. Note that the array points should not be assumed to persist; it may be deleted after the constructor is invoked.
struct PointType
{
float x;
float y;
};
class Point
{
public:
Point(const PointType& center );
virtual ~Point();
private:
PointType m_center;
};
class Polygon : public Point
{
public:
Polygon(const PointType* points, int npoints);
~Polygon();
const VectorType& operator[](int index) const;
private:
int m_npoints;
Object::PointType * m_pt;
};
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include "Object.hpp"
using namespace std;
const float eps = 1e-5f;
bool Near(float x, float y)
{
return abs(x-y) < eps;
}
float frand()
{
return 10.0f*float(rand())/float(RAND_MAX);
}
int main()
{
srand(unsigned(time(0)));
int count = 0,
max_count = 0;
// Polygon tests
int n = 3 + rand()%8;
float *xs = new float[n],
*ys = new float[n];
float x = 0, y = 0;
PointType *Ps = new PointType[n];
for (int i=0; i < n; ++i) {
xs[i] = frand(), ys[i] = frand();
Ps[i] = PointType(xs[i],ys[i]);
x += xs[i], y += ys[i];
}
}
Point::Point(const PointType& center)
: m_center{center}
{
}
// this is wrong, can correct me how to construct it?
Polygon::Polygon(const PointType* points, int npoints, float depth)
:m_npoints{npoints} , m_pt{new Object::PointType[npoints]}, Point (*m_pt ,depth)
{
for(int i=0; i < m_npoints ; ++i)
{
m_pt[i] = points[i];
}
}
enter code here
this the assignment structure like
enter image description here
I took away other object class implementation
Your assignment text doesn't say anything about inheritance. It essentially describes composition. Go from here:
class Polygon
{
public:
// constructor should allocate the array
Polygon(const PointType* points, int npoints);
~Polygon();
private:
Point *m_npoints; // or use smart pointer if you're allowed to.
};
It is a trick question, is actually want me to find centroid point of polygon.
So I need a private compute center point of polygon function and return the result of center point of polygon, and then call the function in point constructor when init.
When I run this code and create an instance of cylinderType by passing four parameters, debugger shows the height I want but, radius=x=y=0. So when I call method printVolume() on this object, it displays '0'.
Am I missing something important with inheritance?
Thank you~
#include <iostream>
using namespace std;
class circleType
{
public:
circleType();
circleType(double r);
double getArea() const;
private:
double radius;
};
class cylinderType : public circleType
{
public:
cylinderType(double h, double r);
void printVolume() const;
private:
double height;
};
int main()
{
cylinderType cylinderA(2, 4);
cylinderA.printVolume();
return 0;
};
circleType::circleType()
{
radius = 0;
};
circleType::circleType(double r)
{
radius = r;
};
double circleType::getArea() const
{
return (3.14 * radius* radius);
};
cylinderType::cylinderType(double h, double r)
{
circleType::circleType(r);
height = h;
};
void cylinderType::printVolume() const
{
cout << (circleType::getArea() * height);
};
The following code asserts in the indicated place with "iterator+offset is out of range."
void Network::PushInput(int c, int h, int w) {
Input* input = new Input(batch, c, h, w, data);
layers.push_back(input); // this happens to be the first push_back()
// layers.push_back(input); // doing another doesn't change the assert!
Layer *foo = layers.back(); // asserts here
Layer *baz = layers[layers.size()-1]; // does not assert
}
Input is a public subclass of Layer. layers is declared as
std::vector<Layer *>layers;
If I attempt to duplicate the above with more vanilla template types, e.g., int*, back() works as expected with no asserts. Somehow, the template type matters here. (Note: _ITERATOR_DEBUG_LEVEL is 2, which triggers that assert check in the vector class.)
I'd rather not bluntly change all of the back()'s in the code to size()-1, but would rather understand what is going on here.
Any ideas? (I'll continue to perturb the code until I can find the apparent cause of this, but hopefully this will be obvious to someone else.)
(I'm using Visual Studio 2013 Community Edition, if that matters.)
.....
Here's a stand-alone file that compiles that shows the problem:
#include <vector>
using namespace std;
namespace layer {
class Layer {
public:
Layer(float alpha = 0, float momentum = 0.9f, float weight_decay = 0);
virtual ~Layer();
// three virtual method that all layers should have
virtual void forward(bool train = true) = 0;
virtual void backward() = 0;
virtual void update() = 0;
void adjust_learning(float scale); // change the learning rate
Layer* prev; // previous layer
Layer* next; // next layer
float* data; // X': output (cuDNN y)
int batch; // n: batch size
float alpha; // learning rate
float momentum; // beta: momentum of gradient
float weight_decay; // gamma: weight decay rate
};
} /* namespace layer */
namespace layer {
Layer::Layer(float alpha_, float momentum_, float weight_decay_)
{
std::memset(this, 0, sizeof(*this));
alpha = alpha_;
momentum = momentum_;
weight_decay = weight_decay_;
}
Layer::~Layer() {}
void Layer::adjust_learning(float scale) {
alpha *= scale;
}
}
namespace layer {
class Input : public Layer {
public:
Input(int n, int c, int h, int w, float* _data);
virtual ~Input();
void forward(bool train = true);
void backward();
void update();
};
}
namespace layer {
Input::Input(int n, int c, int h, int w, float* _data) : Layer() {
prev = NULL;
batch = n;
data = _data;
}
Input::~Input() {
data = NULL;
}
void Input::forward(bool train) {
// nothing
}
void Input::backward() {
// nothing
}
void Input::update() {
// nothing
}
}
using namespace layer;
namespace model {
class Network {
private:
std::vector<Layer*> layers; // list of layers
bool has_input, has_output; // sanity check
float* data; // input on device
int batch; // whole size of data, batch size
public:
Network(int batch_size);
virtual ~Network();
void PushInput(int c, int h, int w);
};
}
namespace model {
void Network::PushInput(int c, int h, int w) {
Input* input = new Input(batch, c, h, w, data);
layers.push_back(input);
Layer *foo = layers.back(); // **WHY DOES THIS ASSERT??**
}
Network::Network(int _batch) {
std::memset(this, 0, sizeof(*this));
batch = _batch;
}
Network::~Network() {
for (Layer* l : layers)
delete l;
}
}
void main()
{
model::Network foo(10);
foo.PushInput(2, 3, 4);
}
You have undefined behavior in your code.
In the Layer constructor you do
std::memset(this, 0, sizeof(*this));
The problem with this is that the above call will clear the virtual function table (which is a part of the object) as well. Any virtual function called after that will not work as expected, if at all. That includes the destruction of the objects as the destructors are virtual.
I've been writing a program for CS class that's supposed to get the X and Y coordinates from the user, as well as the length of a square and the height of the cube, and it should then calculate the area of the square and the surface area and volume of the cube (plus some coordinates stuff but that's not a pressing issue right now)
I've written the test file and it compiled successfully, but I've been getting very long answers for the square and cube properties that are obviously wrong. Can anyone point out whatever logical errors I might have or if I have the access specification and relationship between the classes wrong?
Point.h
class Point
{
protected:
double Xint, Yint;
public:
Point();
void setX(double);
void setY(double);
double getX() const;
double getY() const;
};
Point.ccp
Point::Point()
{
Xint = 0;
Yint = 0;
}
void Point::setX(double x)
{ Xint = x; }
void Point::setY(double y)
{ Yint = y; }
double Point::getX() const
{ return Xint; }
double Point::getY() const
{ return Yint; }
Square.h
#include "Point.h"
class Square : public Point
{
protected:
Point lowerLeft;
double sideLength;
public:
Square(double sideLength, double x, double y) : Point()
{
sideLength = 0.0;
x = 0.0;
y = 0.0;
}
void setLowerLeft(double, double);
void setSideLength(double);
double getSideLength() const;
double getSquareArea() const;
};
Square.ccp
#include "Square.h"
void Square::setLowerLeft(double x, double y)
{
lowerLeft.setX(x);
lowerLeft.setY(y);
}
void Square::setSideLength(double SL)
{ sideLength = SL; }
double Square::getSideLength() const
{ return sideLength; }
// Calculate the area of square
double Square::getSquareArea() const
{ return sideLength * sideLength; }
Cube.h
#include "Square.h"
class Cube : public Square
{
protected:
double height;
double volume;
public:
Cube(double height, double volume) : Square(sideLength, Xint, Yint)
{
height = 0.0;
volume = 0.0;
}
double getSurfaceArea() const;
double getVolume() const;
};
Cube.ccp
#include "Cube.h"
// Redefine GetSquareArea to calculate the cube's surface area
double Cube::getSurfaceArea() const
{ return Square::getSquareArea() * 6; }
// Calculate the volume
double Cube::getVolume() const
{ return getSquareArea() * height; }
"Can anyone point out whatever logical errors I might have or if I have the access specification and relationship between the classes wrong?"
Well, from our well known 3-dimensional geometry a cube is made up from exactly 6 squares.
So how do you think inheriting a Cube class from a Square actually should work well?
You can easily define a Cube class by means of a fixed Point (e.g. the upper, left, front corner) and a fixed size of the edge length.
If you really want and need to, you can add a convenience function for your Cube class, that returns all of the 6 Squares it consist of in 3 dimensional space:
class Cube {
public:
Cube(const Point& upperLeftFrontCorner, double edgeLength);
std::array<Square,6> getSides() const;
};
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
{
//...
};