b2Draw subclass member functions not called - c++

I'm trying to create a minimal test case for another question about Box2d, but I am unable to cause the member functions of my custom drawer to be called:
#include <iostream>
#include "Box2D/Box2D.h"
class DebugDrawer : public b2Draw
{
public:
DebugDrawer() {
AppendFlags(b2Draw::e_shapeBit);
AppendFlags(b2Draw::e_jointBit);
AppendFlags(b2Draw::e_aabbBit);
AppendFlags(b2Draw::e_pairBit);
AppendFlags(b2Draw::e_centerOfMassBit);
}
void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color&)
{
for (int vertex = 0; vertex < vertexCount; ++vertex) {
b2Vec2 vec = vertices[vertex];
std::cout << "DrawPolygon" << "vertex" << vertex << "x" << vec.x << "y" << vec.y;
}
}
void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color&)
{
for (int vertex = 0; vertex < vertexCount; ++vertex) {
b2Vec2 vec = vertices[vertex];
std::cout << "DrawSolidPolygon" << "vertex" << vertex << "x" << vec.x << "y" << vec.y;
}
}
void DrawCircle(const b2Vec2& center, float32 radius, const b2Color&)
{
std::cout << "DrawCircle" << "x" << center.x << "y" << center.y << "radius" << radius;
}
void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2&, const b2Color&) {
std::cout << "DrawSolidCircle" << "x" << center.x << "y" << center.y << "radius" << radius;
}
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color&) {
std::cout << "DrawSegment" << "p1.x" << p1.x << "p1.y" << p1.y << "p2.x" << p2.x << "p2.y" << p2.y;
}
void DrawTransform(const b2Transform& xf) {
std::cout << "DrawTransform" << "x" << xf.p.x << "y" << xf.p.y << "angle" << xf.q.GetAngle();
}
};
int main(int argc, char** argv)
{
b2World world(b2Vec2(0.0f, 0.0f));
DebugDrawer debugDrawer;
world.SetDebugDraw(&debugDrawer);
// body
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position = b2Vec2(0, 0);
b2Body *body = world.CreateBody(&bd);
// shape
b2CircleShape shape;
shape.m_radius = 1.0f;
// fixture
b2FixtureDef fd;
fd.shape = &shape;
fd.density = 1.0f;
body->CreateFixture(&fd);
world.Step(1.0f / 120.0f, 8, 3);
return 0;
}
I've tried calling Step() several times, forcing bodies to stay awake, etc. What am I missing?

I think you explicitly need to call world.DrawDebugData().
Also, did you know you can call SetFlags(a | b | c); instead of AppendFlags(a); AppendFlags(b); AppendFlags(c);?

Related

How to trace a path with pixels in Raylib?

I am making a double pendulum simulator in Raylib and before I get into the deep physics behind how it works I wanted to finish creating the graphics for it.
So far I created a window, made a double pendulum, and can rotate the pendulums however I want, but as the last thing I need to do before working on the physics is trace its path and I went about it using textures using a RenderTexture2D variable.
However when doing so it does trace the path but only 1/4th of the entire window and I am not sure why.
Most likely it has to do with rltranslatef but I am not sure how to fix it. I have a pendulum.h & .cpp file but they are unrelated to making the graphics for this. Any help is appreciated.
pendulum.h:
#ifndef DOUBLE_PENDULUM_SIM_PENDULUM_H
#define DOUBLE_PENDULUM_SIM_PENDULUM_H
class pendulum {
public:
float pLength{};
float pMass{};
float x{};
float y{};
float pAngle{};
public:
[[nodiscard]] float getX() const ;
[[nodiscard]] float getY() const ;
[[nodiscard]] float getAngle() const ;
void setX(float length, float angle);
void setY(float length, float angle);
void setLength(float length);
void setMass(float mass);
void setAngle(float angle);
pendulum();
pendulum(float length, float mass, float angle) : pLength(length), pMass(mass), pAngle(angle) {}
~pendulum();
};
#endif //DOUBLE_PENDULUM_SIM_PENDULUM_H
pendulum.cpp:
#include "includes/pendulum.h"
#include <cmath>
#include <iostream>
#include <raylib.h>
void pendulum::setX(float length, float angle) {
x = length * sin(angle);
}
void pendulum::setY(float length, float angle) {
y = length * cos(angle);
}
float pendulum::getX() const {
return x;
}
float pendulum::getY() const {
return y;
}
void pendulum::setLength(float length) {
pLength = length;
}
void pendulum::setMass(float mass) {
pMass = mass;
}
float pendulum::getAngle() const {
return pAngle;
}
pendulum::~pendulum() {
std::cout << "\nPendulum destroyed" << std::endl;
}
void pendulum::setAngle(float angle) {
pAngle = angle * DEG2RAD;
}
//Default constructor
pendulum::pendulum() = default;
main.cpp in which the main graphics is drawn:
#include <iostream>
#include "raylib.h"
#include "includes/pendulum.h"
#include <rlgl.h>
#include <cmath>
void _testPendulum();
pendulum pen1;
pendulum pen2;
int main() {
//Prompt to make the initial values themselves
float uLength1, uLength2, uMass1, uMass2, uAngle1, uAngle2;
try {
std::cout << "Please choose the length of each pendulum, starting with Pendulum 1, then Pendulum 2. Each value provided can be up to 7 decimal digits, " << "\n" << "length MUST BE greater than 50 and less than 200" << "\n";
std::cin >> uLength1 >> uLength2;
std::cout << "Please choose the mass of each pendulum, starting with Pendulum 1, then Pendulum 2. Each value provided can be up to 7 decimal digits, " << "\n" << "mass MUST BE greater than 20 and less than 100" << "\n";
std::cin >> uMass1 >> uMass2;
std::cout << "Please choose the starting angle of each pendulum, starting with Pendulum 1, then Pendulum 2. Each value provided can be up to 7 decimal digits" << "\n";
std::cin >> uAngle1 >> uAngle2;
} catch (const std::exception & e) {
std::cout << e.what();
}
//Pendulum 1 settings
pen1.setMass(uMass1);
pen1.setLength(uLength1);
pen1.setAngle(uAngle1);
pen1.setX(pen1.pLength,pen1.getAngle());
pen1.setY(pen1.pLength, pen1.getAngle());
std::cout << "X coord: " << pen1.getX() << " Y coord: " << pen1.getY() << std::endl;
//Pendulum 2 settings
pen2.setMass(uMass2);
pen2.setLength(uLength2);
pen2.setAngle(uAngle2); //Can only set this once and cant anywhere else, why?
pen2.setX( pen2.pLength,pen2.getAngle());
pen2.setY( pen2.pLength,pen2.getAngle());
pen2.x = pen1.getX() + pen2.getX();
pen2.y = pen1.getY() + pen2.getY();
std::cout << "X coord: " << pen2.getX() << " Y coord: " << pen2.getY() << std::endl;
Vector2 origin{0,0};
const double screenWidth = 1440;
const double screenHeight = 1080;
InitWindow((int) screenWidth, (int) screenHeight, "Double-Pendulum-Sim");
int frameCounter = 0;
SetTargetFPS(60);
float px1 = pen1.getX();
float py1 = pen1.getY();
float px2 = pen2.getX();
float py2 = pen2.getY();
RenderTexture2D target = LoadRenderTexture((int) screenWidth, (int) screenHeight);
BeginTextureMode(target);
ClearBackground(RAYWHITE);
EndTextureMode();
while (!WindowShouldClose()) {
Vector2 rod1{px1,py1};
Vector2 rod2 {px2, py2};
/**------------------Update------------------*/
frameCounter++;
uAngle1 += 1.0f;
pen1.setAngle(uAngle1); //Can only set this once and cant anywhere else, why?
pen1.setX(pen1.pLength,pen1.getAngle());
pen1.setY(pen1.pLength, pen1.getAngle());
px1 = pen1.getX();
py1 = pen1.getY();
uAngle2 -= 1.0f;
pen2.setAngle(uAngle2); //Can only set this once and cant anywhere else, why?
pen2.setX( pen2.pLength,pen2.getAngle());
pen2.setY( pen2.pLength,pen2.getAngle());
pen2.x = pen1.getX() + pen2.getX();
pen2.y = pen1.getY() + pen2.getY();
px2 = pen2.getX();
py2 = pen2.getY();
std::cout << frameCounter << std::endl;
/**---------------------------------Draw-Pendulums & Path---------------------------------- */
//TODO: Get pathing to work
BeginDrawing();
BeginTextureMode(target);
DrawPixelV(rod2, RED);
EndTextureMode();
rlTranslatef((float) screenWidth/2,(float) screenHeight/4,0);
DrawTextureRec(target.texture, (Rectangle){0,0, (float) target.texture.width, (float) -target.texture.height}, (Vector2){0,0}, WHITE);
ClearBackground(RAYWHITE);
DrawFPS(-350, -200);
DrawLineEx(origin, rod1, 5.0f, BLACK);
DrawCircle( px1,py1,pen1.pMass,BLACK);
DrawLineEx(rod1, rod2, 5.0f, BLACK);
DrawCircle(px2,py2,pen2.pMass,BLACK);
std::cout << "Pendulum 1 X & Y: " << pen1.getX() << " " << pen1.getY() << std::endl;
std::cout << "Pendulum 2 X & Y: " << pen2.getX() << " " << pen2.getY() << std::endl;
EndDrawing();
}
CloseWindow();
return 0;
}
//Test function
void _testPendulum() {
try {
pen1.setMass(20.0f);
pen1.setLength(150.0f);
pen1.setAngle(0.0f);
pen1.setX(pen1.pLength,pen1.getAngle());
pen1.setY(pen1.pLength, pen1.getAngle());
std::cout << "X coord: " << pen1.getX() << " Y coord: " << pen1.getY() << std::endl;
pen2.setMass(50.0f);
pen2.setLength(150.0f);
pen2.setAngle(0.0f);
pen2.setX( pen2.pLength,pen2.getAngle());
pen2.setY( pen2.pLength,pen2.getAngle());
pen2.x = pen1.getX() + pen2.getX();
pen2.y = pen1.getY() + pen2.getY();
std::cout << "X coord: " << pen2.getX() << " Y coord: " << pen2.getY() << std::endl;
} catch (const std::exception & e) {
std::cout << e.what();
}
}
Your problem comes from DrawPixelV(rod2, RED); which is unable to write where position is negative (try without rlTranslatef to see the idea).
Solution:
Don't use rlTranslatef
Instead make origin, px1, py1, px2 and py2 centered on the screen center (not 0,0).
In main.cpp, I changed these lines and the problem disappeared
Vector2 origin{700,200}; // was origin{0,0};
...
float px1 = pen1.getX() + 700; // +700 was not here
float py1 = pen1.getY() + 200; // +200 was not here
float px2 = pen2.getX() + 700;
float py2 = pen2.getY() + 200;
...
px1 = pen1.getX() + 700;
py1 = pen1.getY() + 200;
...
px2 = pen2.getX() + 700;
py2 = pen2.getY() + 200;

I have a project in college and I do some of the requirements [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 10 months ago.
This post was edited and submitted for review 10 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
**my project talk about Shape hierarchy for every shape needs Inheritance, Polymorphism and Files I/0
I did a simple thing of the requirements, but I did not do it 100%, such as requirements 1, 2, 3 or requirements 6 and 7, so I sent all the requirements, please help me**
All classes must have a color and name attributes, both of a string type and stored in the base class (Shape).
All 2D shapes must have area and perimeter attributes, both of double type and stored in their base class (Sahpe2D).
All 3D shapes must have surfaceArea and volume attributes, both of double type and stored in their base class (Shape3D),
readData(), print(), printToFile(ofstream &output), readFromFile(ifstream &input) functions must be implemented in all classes (base and derived), taking into consideration they will be used for polymorphism,
computeArea() and computePerimeter() functions must be implementer in all 2D shape classes (including their base class), taking into consideration their use in polymorphism,
computeSurfaceArea() and computeVolume() functions must be implemented in all 3D shape classes (including their base class), taking into consideration their use in polymorphism,
Requirements
For every class, you need to build a default/parametrized constructor,
The default constructors set the objects' data members to 1.0,
Parametrized constructors are used to set objects' data members using the values passed to the objects during instantiation
readData() function is used to read all the object's data members from the user
print() function is used to print all object's data to the screen,
Your program must be able to write all objects' data to the binary file "Shapes.dat", using the printToFile functions,
Your program should be able to read and append to the "Shapes.dat" file as needed, using the readFromFile functions,
Your main file must be able to store/retrieve data to/from output/input files depending on the user's choice,
It is not known how many objects will be added or their order of addition.
//Shapes.h
#pragma once
#include<iostream>
#include<fstream>
using namespace std;
class Shape {
public:
string color, name;
Shape()
{
cout << "Base Class is Shape for this element . \n";
}
};
//Shape2D.h
#pragma once
#include"shapes.h"
class Shape2D : public Shape {
public:
double area, perimeter;
Shape2D()
{
cout << "Parent Class is Shape2D for this element .\n";
}
};
//Shape3D.h
#pragma once
#include"shapes.h"
class Shape3D : public Shape {
public:
Shape3D()
{
cout << "Parent Class is Shape3D for this element .\n";
}
};
//Square.h
#include"shapes2D.h"
class Square : public Shape2D {
public:
Square()
{
cout << "Calculating square area and perimeter \n";
}
void computeArea(double side)
{
double area;
area = side * side;
print("Area", area);
printToFile("Area", area);
}
void computePerimeter(double side) {
double perimeter;
perimeter = 4 * side;
print("Perimeter", perimeter);
printToFile("Perimeter", perimeter);
}
void print(string x, double y)
{
cout << x << " of Square = " << y << "\n";
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat");
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Square = " << y << "\n";
}
};
//Triangle.h
#include"shapes2D.h"
class Triangle : public Shape2D {
public:
Triangle()
{
cout << "This is a Triangle\n";
}
void computeArea(double base, double height) {
double area;
area = (height * base) / 2;
print("Area", area);
printToFile("Area", area);
}
void computePerimeter(double base, double height) {}
void print(string x, double y)
{
cout << x << " of Triangle = " << y << "\n";
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat");
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Triangle = " << y << "\n";
}
};
//Sphere.h
#include"shapes3D.h"
class Sphere : public Shape3D {
public:
Sphere()
{
cout << "This is a Sphere\n";
}
void computeSurfaceArea(double radius) {
double area;
area = 4 * 3.14 * radius * radius;
print("Area", area);
printToFile("Area", area);
}
void computeVolume(double radius) {
double perimeter;
perimeter = (4 / 3) * (3.14 * radius * radius * radius);
print("Perimeter", perimeter);
printToFile("Perimeter", perimeter);
}
void print(string x, double y)
{
cout << x << " of Sphere = " << y << "\n";
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat");
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Sphere = " << y << "\n";
}
};
//Hexagon.h
#include"shapes2D.h"
class Hexagon : public Shape2D {
public:
Hexagon()
{
cout << "This is a Hexagon\n";
}
void computeArea(double side) {
double area;
area = 3 * sqrt(3) * side * side / 2;
print("Area", area);
printToFile("Area", area);
}
void computePerimeter(double side) {
double perimeter;
perimeter = 6 * side;
print("Perimeter", perimeter);
printToFile("Perimeter", perimeter);
}
void print(string x, double y)
{
cout << x << " of Hexagon = " << y << "\n";
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat");
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Hexagon = " << y << "\n";
}
};
//Cylinder.h
#include"shapes3D.h"
class Cylinder : public Shape3D {
public:
Cylinder()
{
cout << "This is a Cylinder\n";
}
void computeSurfaceArea(double radius, double height) {
double area;
area = (2 * 3.14 * radius) * (radius + height);
print("Surface Area", area);
printToFile("Surface Area", area);
}
void computeVolume(double radius, double height) {
double volume;
volume = 3.14 * radius * radius * height;
print("Volume", volume);
printToFile("Volume", volume);
}
void print(string x, double y)
{
cout << x << " of Cylinder = " << y << "\n";
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat");
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Cylinder = " << y << "\n";
}
};
//Cube.h
#include"shapes3D.h"
class Cube : public Shape3D {
public:
Cube()
{
cout << "This is a Cube\n";
}
void computeSurfaceArea(double side) {
double area;
area = 6 * side * side;
print("Surface Area", area);
printToFile("Surface Area", area);
}
void computeVolume(double side) {
double volume;
volume = side * side * side;
print("Volume", volume);
printToFile("Volume", volume);
}
void print(string x, double y)
{
cout << x << " of Cube = " << y << "\n";
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat");
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Cube = " << y << "\n";
}
};
//Cone.h
#include"shapes3D.h"
#include<cmath>
class Cone : public Shape3D {
double radius, height;
public:
Cone()
{
cout << "This is a Cone\n";
}
void computeSurfaceArea(double radius, double height) {
double area;
area = 3.14 * radius * (radius + sqrt(radius * radius + height * height));
print("Surface Area", area);
printToFile("Surface Area", area);
}
void computeVolume(double radius, double height) {
double volume;
volume = (3.14 * radius * radius * height) / 3;
print("Volume", volume);
printToFile("Volume", volume);
}
void print(string x, double y)
{
cout << x << " of Cone = " << y << "\n";
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat");
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Cone = " << y << "\n";
}
};
//Circle.h
#include"shapes2D.h"
class Circle : public Shape2D{
double radius;
public:
Circle()
{
cout << "Calculating circle area and perimeter \n";
}
void computeArea(double r)
{
double area;
area = 3.14 * r * r;
print("Area", area);
printToFile("Area", area);
}
void computePerimeter(double r) {
double perimeter;
perimeter = 2 * 3.14 * r;
print("Perimeter", perimeter);
printToFile("Perimeter", perimeter);
}
void print(string x, double y)
{
cout << x << " of Square = " << y << "\n";
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat");
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Circle = " << y << "\n";
}
};
//main.cpp
#include"Cone.h"
#include"Cube.h"
#include"Cylinder.h"
#include"Hexagon.h"
#include"sphere.h"
#include"square.h"
#include"Triangle.h"
#include "Circle.h"
int main()
{
Cylinder a;
Cube b;
Cone c;
double r, side, base, height;
int n;
cout << "Select any Number to calculate : ";
cout << "1. Circle \n";
cout << "2. Square\n";
cout << "3. Triangle\n";
cout << "4. Hexagon\n";
cout << "5. Sphere\n";
cout << "6. Cube\n";
cout << "7. Cylinder\n";
cout << "8. Cone\n";
cin >> n;
if (n == 1) {
Circle obj1;
cout << "Circle Radius";
cin >> r;
obj1.computeArea(r);
obj1.computePerimeter(r);
}
if (n == 2) {
Square obj2;
cout << "Square Side";
cin >> side;
obj2.computeArea(side);
obj2.computePerimeter(side);
}
if (n == 3) {
Triangle obj3;
cout << "Triangle Base";
cin >> base;
cout << "Triangle Height";
cin >> height;
obj3.computeArea(base, height);
// obj3.computePerimeter(base,height) ;
}
if (n == 4) {
Hexagon obj4;
cout << "Hexagon Side";
cin >> side;
obj4.computeArea(side);
obj4.computePerimeter(side);
}
if (n == 5) {
Sphere obj5;
cout << "Sphere Radius";
cin >> r;
obj5.computeSurfaceArea(r);
obj5.computeVolume(r);
}
if (n == 6) {
Cube obj6;
cout << "Cube Side";
cin >> side;
obj6.computeSurfaceArea(side);
obj6.computeVolume(side);
}
if (n == 7) {
Cylinder obj7;
cout << "Cylinder Radius";
cin >> r;
cout << "Cylinder Height";
cin >> height;
obj7.computeSurfaceArea(r, height);
obj7.computeVolume(r, height);
}
if (n == 8) {
Cone obj8;
cout << "Cone Radius";
cin >> r;
cout << "Cone Height";
cin >> height;
obj8.computeSurfaceArea(r, height);
obj8.computeVolume(r, height);
}
return 0;
}
There are quite a few things going on here.
You are trying to include header files all over the place. I dont know why you want/need them. It's fine (if you have those files defined somewhere) but for a simple case of defining some classes one monolithic file is ok.
You haven't satisfied the problem statement. It said "default/parametrized constructor" you have default constructors for each i.e. 'myClass()' but no parameterized one ex 'myClass(int heigh, int width)...' so you need to implement those so you can initialize shapes at construction time instead of setting them later.
The formatting is all over the place, I would recommend cleaning that up.
To your main question: "it appears to me that the classes are not defined What is the problem?"
You have defined classes, this is a class definition:
class Shape
{
public:
Shape()
{
cout << "Base Class is Shape for this element . \n";
}
private:
string color, name;
};
Down in main Shape myshape; is creating an object of type shape.
Here is a easy write up to follow as well:
https://www.geeksforgeeks.org/c-classes-and-objects/

Why does my vector store a copy of my object, and not the original value, in c++?

I have a mid-term assignment in which we conduct 3 sets of unit tests with documentation etc for a program from our course. The program I chose is a physics simulation.
Within this program, there are two classes, Thing and World. I am able to independently create these objects. I tried adding the Thing object to the World object by creating a std::vector<Thing> things, and then creating a function to add the Thing to the vector of things. However, when I do that, it seems as though the World object creates its own copy of the Thing, because when I change the Things position, the version of the Thing in the things vector remains the same.
Please provide some guidance on the matter, I feel my problem might be with how I use pointers in this situation.
void testBoundaryBounce()
{
//Create the world
World world{10.0f, 10.0f, 1.0f};
//Thing, 2 units away from boundary
Thing thing{8.0f, 5.0f, 1.0f};
//Add thing to world (adding it the the things vector)
world.addThing(&thing);
//Apply force that should trigger bounce back to x = 7
thing.applyForce(1.0f, 0.0f);
//Updating thing so that movement takes effect
thing.update();
//Running world update to account for collisions, bounces etc
world.update();
std::cout << "thing x : " << thing.getX() << std::endl;
CPPUNIT_ASSERT(thing.getX() == 7);
}
Thing::Thing(float x, float y, float radius)
: x{x}, y{y}, dX{0}, dY{0}, radius{radius}
{
}
World::World(float width, float height, float gravity)
: width{width}, height{height}, gravity{gravity}
{
std::vector<Thing> things;
}
void World::addThing(Thing* thing)
{
float thingX = thing->getX();
float thingY = thing->getY();
float thingRad = thing->getRad();
std::cout << "Radius : " << thingRad << std::endl;
if (thingX + thingRad > width || thingX - thingRad <= 0 || thingY + thingRad >
height|| thingY - thingRad <= 0)
{
std::cout << "Thing is out of bounds or is too large" << std::endl;
}
else {
std::cout << "Thing is good" << std::endl;
things.push_back(*thing);
}
}
void World::update()
{
for (Thing& thing : things)
{
thing.update();
float thingX = thing.getX();
float thingY = thing.getY();
float thingRad = thing.getRad();
float worldGrav = this->gravity;
std::cout << "thing x: " << thingX << std::endl;
std::cout << "thing rad: " << thingRad << std::endl;
//World Boundary Bounces
if (thingX + thingRad >= width)
{
std::cout << "Bounce left" << std::endl;
thing.applyForce(-2.0f, 0.0f);
thing.update();
}
if (thingX + thingRad <= 0)
{
thing.applyForce(2.0f, 0.0f);
thing.update();
std::cout << "Bounce right" << std::endl;
}
if (thingY + thingRad >= height)
{
thing.applyForce(0.0f, -2.0f);
thing.update();
std::cout << "Bounce up" << std::endl;
}
if (thingY - thingRad <= 0)
{
thing.applyForce(0.0f, 2.0f);
thing.update();
std::cout << "Bounce down" << std::endl;
}
//Thing Collision Bounces
for (Thing& otherthing : things)
{
float thing2X = otherthing.getX();
float thing2Y = otherthing.getY();
float thing2Rad = otherthing.getRad();
if (thingX + thingRad == thing2X + thing2Rad && thingY + thingRad ==
thing2Y + thing2Rad)
{
thing.applyForce(-2.0f, -2.0f);
thing.update();
otherthing.applyForce(2.0f, 2.0f);
otherthing.update();
}
}
//Gravitational Pull
thing.applyForce(0.0f, worldGrav);
}
}
Its right in the definition of void push_back (const value_type& val);...
Adds a new element at the end of the vector, after its current last element. The content of val is copied (or moved) to the new element.
so when you call things.push_back(*thing);, you are adding a new element to the 'things' vector which is a copy of the value pointed to by the thing pointer.
You want to change your vector to hold pointers to Thing types instead:
std::vector<Thing *> things;
and add the pointers instead of copies:
things.push_back(thing);
Note you will later have to access fields via -> instead of ., or you can create a reference to it such as:
for (Thing* pt: things)
{
Thing& thing = *pt;
thing.update();
//etc...
Instead of constructing a Thing and copying it into world, you could have World construct the Things that it owns
void testBoundaryBounce()
{
//Create the world
World world{10.0f, 10.0f, 1.0f};
//Thing, 2 units away from boundary
Thing * thing = world.addThing(8.0f, 5.0f, 1.0f);
//Apply force that should trigger bounce back to x = 7
thing->applyForce(1.0f, 0.0f);
//Running world update to account for collisions, bounces etc
//Implies updating all the things
world.update();
std::cout << "thing x : " << thing.getX() << std::endl;
CPPUNIT_ASSERT(thing.getX() == 7);
}
Thing::Thing(float x, float y, float radius)
: x{x}, y{y}, dX{0}, dY{0}, radius{radius}
{
}
World::World(float width, float height, float gravity)
: width{width}, height{height}, gravity{gravity}
{
std::vector<Thing> things;
}
Thing * World::addThing(float x, float y, float radius)
{
std::cout << "Radius : " << radius << std::endl;
if ((x + radius > width) || (x - radius <= 0) || (y + radius >
height) || (y - radius <= 0))
{
std::cout << "Thing is out of bounds or is too large" << std::endl;
return nullptr;
}
else
{
std::cout << "Thing is good" << std::endl;
return &things.emplace_back(x, y, radius);
}
}
void World::update()
{
for (Thing& thing : things)
{
thing.update();
float thingX = thing.getX();
float thingY = thing.getY();
float thingRad = thing.getRad();
float worldGrav = this->gravity;
std::cout << "thing x: " << thingX << std::endl;
std::cout << "thing rad: " << thingRad << std::endl;
//World Boundary Bounces
if (thingX + thingRad >= width)
{
std::cout << "Bounce left" << std::endl;
thing.applyForce(-2.0f, 0.0f);
thing.update();
}
if (thingX + thingRad <= 0)
{
thing.applyForce(2.0f, 0.0f);
thing.update();
std::cout << "Bounce right" << std::endl;
}
if (thingY + thingRad >= height)
{
thing.applyForce(0.0f, -2.0f);
thing.update();
std::cout << "Bounce up" << std::endl;
}
if (thingY - thingRad <= 0)
{
thing.applyForce(0.0f, 2.0f);
thing.update();
std::cout << "Bounce down" << std::endl;
}
//Thing Collision Bounces
for (Thing& otherthing : things)
{
float thing2X = otherthing.getX();
float thing2Y = otherthing.getY();
float thing2Rad = otherthing.getRad();
if (thingX + thingRad == thing2X + thing2Rad && thingY + thingRad ==
thing2Y + thing2Rad)
{
thing.applyForce(-2.0f, -2.0f);
thing.update();
otherthing.applyForce(2.0f, 2.0f);
otherthing.update();
}
}
//Gravitational Pull
thing.applyForce(0.0f, worldGrav);
}
}
As an aside, everything bounces off of itself every update

Coordinate conversion in c++

I am trying to convert different coordinate systems. From polar to rectangular and vice versa. My pol_to_rect()function is not working properly. It is giving very small values(~10^(-44)) after converting and also before converting. There might be some problem while using the sin() and cos() functions. The rect_to_pol() is working fine for positive values.
Edit - When I changed atan() to atan2() how can I incorporate other values of x and y.
#include <iostream>
#include <cmath>
using namespace std;
#define PI 3.1415926
class Polar; // Forward declaration
class Rectangular {
private:
float x, y;
public:
Rectangular() {} // default constructor
Rectangular(float mv_x, float mv_y) {
x = mv_x;
y = mv_y;
}
void showData() const;
Polar rect_to_pol();
float& get_x() {
return x;
}
float& get_y() {
return y;
}
};
void Rectangular::showData() const {
cout << "--Rectangular--" << endl;
cout << "x: " << x << "\t" <<"y: " << y << endl;
}
class Polar {
private:
float r;
float theta;
public:
Polar() {} // default constructor
Polar(float mv_r, float mv_theta) {
r = mv_r;
theta = mv_theta;
}
void showData();
Rectangular pol_to_rect();
float& get_r(){
return r;
}
float& get_theta() {
return theta;
}
};
void Polar::showData() {
cout << "--Polar--" << endl;
cout << "r:" << r << "\t" << "Theta(Radians):" << theta << endl;
}
Rectangular Polar::pol_to_rect() {
Rectangular temp;
temp.get_x() = r * cos(theta*(PI/180.0)); // in degrees
temp.get_y() = r * sin(theta*(PI/180.0));
return temp;
}
Polar Rectangular::rect_to_pol() {
Polar temp;
temp.get_r() = sqrt(pow(x, 2) + pow(y, 2));
temp.get_theta() = atan2(y, x);
return temp;
}
int main()
{
Rectangular r1(-1, -1), r2;
Polar p1(12.0, 30.0), p2;
r1.showData();
p2 = r1.rect_to_pol();
cout << "After Conversion (RECT TO POLAR)->" << endl;
p2.showData();
p1.showData();
r2 = p1.pol_to_rect();
cout << "After Conversion (POLAR TO RECT)" << endl;
r2.showData();
return 0;
}

0xC0000005: Access violation reading location 0xCDCDCDC1

I wrote the code that can generate random Geometry figures and display it in cmd in text form.
Here is my 3 files:
Geometry.h
#pragma once
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#include <iostream>
#include <time.h>
#include <fstream>
#include <string>
#define PI 3.1415926535
using namespace std;
enum color { White, Red, Green, Blue, Yellow, Black };
enum _shape { line, rectangle, circle, picture }; //to roll shapes
void print_color(color c);
//--------------------------Point---------------------------
class Point {
private:
int m_xc, m_yc; //(x,y) coordinats
public:
Point(int x = 0, int y = 0) : m_xc(x), m_yc(y) {}
int x(void) const { return m_xc; };
int y(void) const { return m_yc; };
Point operator+(const Point& p) const
{
return Point(m_xc+p.m_xc, m_yc+p.m_yc);
}
Point& operator+=(const Point& p) //move point
{
m_xc += p.m_xc;
m_yc += p.m_yc;
return *this;
}
friend ostream& operator<<(ostream& os, const Point& p);
Point move(int x, int y){
m_xc += x;
m_yc += y;
return *this;
}
};
//------------------------Shape-----------------------------
class Shape {
protected:
Point m_org;
color m_color;
_shape m_shape;
public:
Shape(const Point& p1 = 0, color c = White, _shape sh = line) : m_org(p1), m_color(c), m_shape(sh){};
virtual ~Shape() = 0 {};
virtual void move(const Point& p) = 0;
virtual void draw(char tabs) const = 0;
virtual void Who_am_I() const = 0;
virtual double Area() const { return 0; };
virtual void Save2File(ofstream &myfile) const = 0;
};
//------------------------Line---------------------------------
class Line : public Shape {
protected:
Point m_end; // line end
public:
Line(const Point& p1, const Point& p2, color c) : Shape(p1, c, line), m_end(p2) {}
void move(const Point& p)
{
m_org += p;
m_end += p;
}
void draw(char tabs) const;
void Who_am_I() const {
print_color(m_color);
cout << "Line";
}
double length() const;
double Area() const { return 0; };
void Save2File(ofstream &myfile) const;
};
//----------------------Rectangle-------------------------------
class Rectangle : public Shape {
protected:
int width;
int height;
public:
Rectangle(const Point& p1, color c = White, int w = 0, int h = 0) : Shape(p1, c, rectangle), width(w), height(h) {}
void move(const Point& p)
{
m_org += p;
}
void draw(char tabs) const;
void Who_am_I() const {
print_color(m_color);
cout << "Rectangle";
}
double Area() const { return width*height; };
void Save2File(ofstream &myfile) const;
};
//----------------------Circle---------------------------
class Circle : public Shape {
protected:
int radius;
public:
Circle(const Point& p1, color c = White, int r = 0) : Shape(p1, c, circle), radius(r) {};
void move(const Point& p)
{
m_org += p;
}
void draw(char tabs) const;
void Who_am_I() const {
print_color(m_color);
cout << "Circle";
}
double Area() const { return PI*(double)radius*(double)radius; };
void Save2File(ofstream &myfile) const;
};
//--------------------------Picture-------------------------
class Picture : public Shape {
private:
Picture(const Picture&); //CCtor is not accessible from main
protected:
Shape** m_shapes; //array of pointers to shapes
int m_count; //number of shapes
static unsigned idx; //number of pictures created for debug
public:
Picture(const Point& p1 = 0, color c = White) : Shape(p1, c, picture), m_count(0){ idx++; }
~Picture();
void insert_shape(Shape* sh);
void draw(char tabs) const;
void move(const Point& p){ m_org += p; };
void Who_am_I() const {
print_color(m_color);
cout << "Picture";
}
void Save2File(ofstream &myfile) const;
int get_count(void){ return m_count; }
double Area() const;
unsigned GetAmPic(void) { return idx; }
};
Geometry.cpp
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#include "geometry.h"
using namespace std;
unsigned Picture::idx = 0;
ostream& operator<<(ostream& os, const Point& p)
{
os << '(' << p.x() << ',' << p.y() << ')';
return os;
}
void print_color(color c) {
string color_print[6] = { "White ", "Red ", "Green ", "Blue ", "Yellow ", "Black " };
cout << color_print[(int)c];
}
//------------------Line methods--------------------
void Line::draw(char tabs) const
{
cout << string(tabs, '\t');
Who_am_I();
cout << " from " << m_org << " to " << m_end << endl;
}
double Line::length() const
{
return sqrt((double)((m_org.x()-m_end.x())*(m_org.x()-m_end.x()) + (m_org.y()-m_end.y())*(m_org.y()-m_end.y())));
}
void Line::Save2File(ofstream& myfile) const {// save to file
myfile << 'L' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " "
<< m_end.x() << " " << m_end.y() << endl;
}
//------------------Rectangle methods----------------
void Rectangle::draw(char tabs) const
{
cout << string(tabs, '\t');
Point temp1 = m_org;
Point temp2 = m_org;
Line l1(temp1, temp2.move(width, 0), m_color);
temp1 = temp2;
Line l2(temp2, temp1.move(0, height), m_color);
temp2 = temp1;
Line l3(temp1, temp2.move(-width, 0), m_color);
temp1 = temp2;
Line l4(temp2, temp1.move(0, -height), m_color);
Who_am_I(); cout << endl;
cout << string(tabs, '\t'); l1.draw(1);
cout << string(tabs, '\t'); l2.draw(1);
cout << string(tabs, '\t'); l3.draw(1);
cout << string(tabs, '\t'); l4.draw(1);
}
void Rectangle::Save2File(ofstream& myfile) const {// save to file
myfile << 'R' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " " << width
<< " " << height << endl;
}
//----------------------Circle methods---------------------------
void Circle::draw(char tabs) const
{
cout << string(tabs, '\t');
Who_am_I();
cout << " Center in " << m_org << " Radius is " << radius << endl;
}
void Circle::Save2File(ofstream& myfile) const {// save to file
myfile << 'C' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " "
<< radius << endl;
}
//----------------------Picture methods--------------------------
void Picture::insert_shape(Shape* s) // insert a new shape to picture
{
if (m_count == 0) {//new picture creating
m_shapes = new Shape*[1];
if (!m_shapes)
cout << "Can't allocate memory!";
}
if (m_count > 0){
Shape** temp = new Shape*[m_count];
memcpy(temp, m_shapes, sizeof(Shape*)*m_count); //save to temp
delete m_shapes; //delete old array
m_shapes = new Shape*[m_count + 1]; //add 1 more place
if (!m_shapes)
cout << "Can't allocate memory!";
memcpy(m_shapes, temp, sizeof(Shape*)*m_count); //return to array
delete temp;
}
m_shapes[m_count] = s; // insert the new shape into the last slot in the array
m_shapes[m_count]->move(m_org); //adjusts the location of the shape
m_count++; // increment the number of shapes in picture
}
void Picture::draw(char tabs) const
{
cout << string(tabs, '\t');
cout << "------------------ ";
Who_am_I();
cout << " ----------------------" << endl;
for (unsigned i = 0; i < m_count; i++)
{
m_shapes[i]->draw(tabs + 1); // draw each shape
}
cout << string(tabs, '\t');
cout << "------------------ End ";
Who_am_I();
cout << " ------------------ " << endl;
}
double Picture::Area() const //sum of areas of all shapes in the picture
{
double area = 0;
for (int i = 0; i < m_count; i++)
{
area += m_shapes[i]->Area();
}
return area;
}
Picture::~Picture()
{
for (int i = 0; i < m_count; i++){
if (m_shapes[i])
delete m_shapes[i];
}
Who_am_I(); cout << " deleting..." << endl;
// sometimes (every 5-10 runs) error here. can't reproduce and debug
if (m_shapes)
delete m_shapes;
// seems like program try to delete already freed memory
}
void Picture::Save2File(ofstream& myfile) const // save to file
{
myfile << 'P' << " " << m_color << " " << m_org.x() << " " << m_org.y() << endl;
for (int i = 0; i < m_count; i++)
m_shapes[i]->Save2File(myfile);
myfile << 'E' << endl; // end of a picture
}
drawing_app.cpp
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#include "geometry.h"
#include <iostream>
#define MAX_PICS_IN_PIC 3
#define MAX_SHAPES 5
using namespace std;
void randomizer(Picture*, int); //recursive function
Picture* Load(istream&);
Point GenP(void);
color GenC(void);
int GenLen(void);
int main(void)
{
srand((unsigned int)time(NULL));
Picture *main_pic = new Picture(Point(0, 0), GenC());
ofstream myfile_write("myfile.txt", ios::out);
if (!myfile_write.is_open())
cout << "Can't open file!" << endl;
randomizer(main_pic, MAX_PICS_IN_PIC); //recursive function
main_pic->Save2File(myfile_write); //save picture to file
myfile_write.close();
cout << " Created Picture:" << endl << endl;
main_pic->draw(0); //draw the main picture
cout << "Created: " << main_pic->GetAmPic() << " pictures." << endl; // for debugging
delete[] main_pic;
ifstream myfile_read("myfile.txt", ios::in);
if (!myfile_read.is_open())
cout << "Can't open file!" << endl;
Picture* buff_pic = Load(myfile_read); //load the picture from the file
cout << endl << endl << " Loaded Picture:" << endl << endl;
buff_pic->draw(0); //display loaded picture
myfile_read.close();
delete[] buff_pic;
cout << "\nLeaks: " << _CrtDumpMemoryLeaks() << endl;
return 0;
}
void randomizer(Picture* pic, int count) {
for (int i = 0; i < MAX_SHAPES; i++){
Point p1 = GenP(); //m_org of the shape
color c = GenC(); //roll random color
_shape shape;
shape = (_shape)(rand() % 4); //roll random shape
if (shape == line){
Point p2 = GenP();
Line* _line = new Line(p1, p2, c);
pic->insert_shape(_line);
}
if (shape == rectangle){
Rectangle* _rect = new Rectangle(p1, c, GenLen(), GenLen());
pic->insert_shape(_rect);
}
if (shape == circle){
Circle* _circ = new Circle(p1, c, GenLen());
pic->insert_shape(_circ);
}
if (shape == picture){
if (count > 0){
Picture* inner_pic = new Picture(p1, c);
count--;
randomizer(inner_pic, count);
pic->insert_shape(inner_pic);
}
else return;
}
}
}
Picture* Load(istream& myfile) {
int m_color, m_org_x, m_org_y;
char m_shape;
myfile >> m_shape >> m_color >> m_org_x >> m_org_y; //read first line
Picture* pic = new Picture(Point(m_org_x, m_org_y), (color)m_color); //create the main picture
myfile >> m_shape; //read next line for shape
while (m_shape != 'E')
{
if (m_shape == 'L'){
int m_end_x, m_end_y;
myfile >> m_color >> m_org_x >> m_org_y >> m_end_x >> m_end_y;
Line* _line = new Line(Point(m_org_x, m_org_y), Point(m_end_x, m_end_y), (color)m_color);
pic->insert_shape(_line);
}
if (m_shape == 'C'){
int radius;
myfile >> m_color >> m_org_x >> m_org_y >> radius;
Circle* Circel = new Circle(Point(m_org_x, m_org_y), (color)m_color, radius);
pic->insert_shape(Circel);
}
if (m_shape == 'R') {
int m_width, m_height;
myfile >> m_color >> m_org_x >> m_org_y >> m_width >> m_height;
Rectangle* Rect = new Rectangle(Point(m_org_x, m_org_y), (color)m_color,
m_width, m_height);
pic->insert_shape(Rect);
}
if (m_shape == 'P') {
myfile.seekg(-1, ios::cur);
Picture* inner_pic = Load(myfile);
pic->insert_shape(inner_pic);
}
myfile >> m_shape;
}
return pic;
}
Point GenP(){ //roll random point x = 0 to 30, y = 0 to 30
Point p(rand() % 31, rand() % 31);
return p;
}
color GenC(){ //generate random color
return (color)(rand() % 6);
}
int GenLen(){ // generate random length from 1 to 50
return rand() % 50 + 1;
}
Every 5-10 runs I got strange error:
Unhandled exception at 0x5214A9E8 (msvcr120d.dll) in Geometry.exe: 0xC0000005: Access violation reading location 0xCDCDCDC1.
Referring me to Destructor of Picture class. I can't reproduce this error and can't find the source of this error. Do you have any ideas how I can debug it?
The obvious error is that it is entirely (and easily) possible to attempt to delete an uninitialized m_shapes pointer in the Picture destructor.
The outline of your code is this:
class Picture : public Shape {
private:
Picture(const Picture&); //CCtor is not accessible from main
protected:
Shape** m_shapes; //array of pointers to shapes
int m_count; //number of shapes
static unsigned idx; //number of pictures created for debug
public:
Picture(const Point& p1 = 0, color c = White) : Shape(p1, c, picture), m_count(0){ idx++; }
//...
~Picture();
};
In the ~Picture() function, you do the following:
Picture::~Picture()
{
for (int i = 0; i < m_count; i++){
if (m_shapes[i])
delete m_shapes[i];
}
if (m_shapes) // This may not have been initialized!!
delete m_shapes;
}
In the Picture() constructor, you failed to initialize m_shapes, thus a simple one line program would be able to invoke the undefined behavior of calling delete on an uninitialized pointer.
Example:
int main()
{
Picture p(Picture(Point(0, 0), GenC()));
} // The `p` destructor will invoke undefined behavior.
Therefore the immediate fix is to go back and make sure m_shapes is initialized to (at least) a nullptr on construction of Picture.
However the ultimate fix is to start to use std::vector and other containers, in addition to using smart pointers such as std::shared_ptr<Shape> and/or std::unique_ptr<Shape>. When you do this, functions such as Picture::insert_shape become either obsolete, or are simple one-line functions issuing a call to (for example) std::vector<Shape*>::push_back().
For example (using a vector of raw pointers)
#include <vector>
class Picture
{
//...
std::vector<Shape *> m_shapes;
void insert_shape(Shape* s);
//...
};
void Picture::insert_shape(Shape* s)
{
m_shapes.push_back(s);
}
If you want to debug the crash in C++ code, let me show you how to use and inspect dumps:
Use adplus.exe (get it from Microsoft) and run your app in process monitor mode
Download WinDBG (also from Microsoft)
Use the following command to create a dump in monitor mode of your process
ADPlus -Crash -pmn Geometry.exe -o C:\CrashDumps
Open the crash dump in WinDBG
Learn the power of WinDBG
A note: You might need symbols (.pdb) files to be created/loaded in your dump inspection
The error is in this line.
Picture *main_pic = new Picture(Point(0, 0), GenC());
You're not giving the size to your Picture pointer and you're deleting it like an array, You must assign a size to your pointer then you also can delete is like this.
delete [] main_pic;