Error with global vector of object pointers c++ - c++

I am developing a 2D physics engine in c++, and one of the main structures I am using is name RigidBody. In order to easily iterate through all of the RigidBody objects in each time step, I attempted to create a global vector of RigidBody object pointers.
vector<RigidBody*> RigidBodies
As suggested in other StackOverflow answers, I declared the global variable in a header file, and defined it in one of the other project .cpp files. However, when I attempt to access member functions or variables, I get bogus values. Below are my source and header files. Could someone please let me know if there is an error with this or if I am doing something fundamentally wrong, as I have been trying to find an error for a few days, and have not been able to figure it out yet.
main.cpp:
#include <iostream>
#include <vector>
#include "polygon.h"
#include "rendering.h"
int test;
std::vector<RigidBody*> RigidBodies;
RigidBody * rigPtr;
void CreateBody() {
Material m1; // Settings for ROCK.
m1.density = 0.6;
m1.restitution = 0.1;
float volume = 1;
Vector p0 = {0,1};
Vector p1 = {1,1};
Vector p2 = {1,0};
Vector p3 = {0,0};
std::vector<Vector*> Points;
Points.push_back(&p0);
Points.push_back(&p1);
Points.push_back(&p2);
Points.push_back(&p3);
//std::cout << Points.at(0)->y << '\n';
Polygon pol1(Points, m1, volume);
Polygon * polPtr = &pol1;
//std::cout << pol1.Points.at(0)->y << '\n';
std::cout << "polygon created" << '\n';
Vector pos1;
pos1.x = 10;
pos1.y = 10;
RigidBody r1(pos1, polPtr);
rigPtr = &r1;
std::cout << "rigid body created" << '\n';
// std::cout << RigidBodies.at(0)->dt << '\n';
}
// MAIN
int main() {
test = 3;
//std::cout << test << '\n';
test = 6;
CreateBody();
RigidBodies.push_back(rigPtr);
//std::cout << test << '\n';
unsigned int lastTime = SDL_GetTicks();
unsigned int currentTime;
SDL_Renderer* renderer = InitializeRender();
while(1) {
currentTime = SDL_GetTicks();
if (currentTime - lastTime > 33) {
//RigidBodies.at(0)->Step();
Render(renderer, RigidBodies);
lastTime = SDL_GetTicks();
}
}
return(0);
}
rendering.cpp:
#include <iostream>
#include "polygon.h"
#include "rendering.h"
SDL_Renderer* InitializeRender() {
SDL_Window * window = NULL;
window = SDL_CreateWindow
(
"RIGID BODIES SIM", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_SHOWN
);
// Setup renderer
SDL_Renderer * renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
return(renderer);
}
void Render(SDL_Renderer * renderer, std::vector<RigidBody*> RigidBodies) {
float scale = 10; // METERS to PIXELS.
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); // Clear screen.
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); // Set polygon drawing color (GREEN)
std::cout << RigidBodies.at(0)->dt << '\n';
for (int j = 0; j < RigidBodies.size(); j++) {
RigidBody * rPtr = RigidBodies.at(j); // Not recognizing rigid body pointer correctly
//std::cout << rPtr->dt << '\n';
Polygon * polyPtr = rPtr->p;
std::cout << "hey1" << '\n';
int size = polyPtr->Points.size(); // ERROR HERE //
std::cout << "hey2" << '\n';
// std::cout << polyPtr->Points.at(0)->y << '\n';
for (int i = 0; i < size; i++) {
std::cout << "hey3" << '\n';
auto pointPtr1 = polyPtr->Points.at(i);
int lastIndex = size - 1;
//std::cout << i+1 << '\n';
auto pointPtr2 = polyPtr->Points.at((i + 1) % (lastIndex)); // Modulo so last point links back up to first one.
SDL_RenderDrawLine(renderer, (rPtr->position.x + pointPtr1->x) * scale, SCREEN_HEIGHT
- (rPtr->position.y + pointPtr1->y) * scale, (rPtr->position.x + pointPtr2->x) * scale,
SCREEN_WIDTH - (rPtr->position.y + pointPtr2->y * scale));
}
}
SDL_RenderPresent(renderer);
}
rendering.h:
#include <vector>
#include <SDL2/SDL.h>
#ifndef RENDERING_H
#define RENDERING_H
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//SDL_Renderer * renderer;
SDL_Renderer* InitializeRender();
void Render(SDL_Renderer*, std::vector<RigidBody*>);
#endif
rigid_bodies.cpp
// Joaquin Matias Giorgi jmgiorgi#bu.edu Impulse-Based Physics Engine 2D //
#include <iostream>
#include <math.h>
#include <SDL2/SDL.h>
#include <vector>
#include "polygon.h"
using namespace std;
vector<RigidBody*> RigidBodies;
// VECTOR STUFF //
// Multiplication by scalar quantity.
Vector Vector::operator*(const float scalar) {
Vector vout;
vout.x = this->x * scalar;
vout.y = this->y * scalar;
return(vout);
}
// Addition overload.
Vector Vector::operator+=(const Vector vec) {
Vector vout;
vout.x = this->x + vec.x;
vout.y = this->y + vec.y;
return(vout);
}
float dot (Vector vec1, Vector vec2) {
float out = (vec1.x * vec2.x) + (vec1.y * vec2.y);
return(out);
}
float cross2d (Vector vec1, Vector vec2) {
// magnitude of perpendicular vector in 3d case.
float out = (vec1.x * vec2.y) - (vec1.y * vec2.x);
return(out);
}
// POLYGON Struct Methods //
Polygon::Polygon(vector< Vector* > Points1, Material m1, float volume1) {
Points = Points1;
m = m1;
volume = volume1;
}
float Polygon::ComputeMass() {
float mass = m.density * this->volume;
return(mass);
}
// RIGID BODY Struct Methods //
RigidBody::RigidBody(Vector position1, Polygon * p1) {
std::cout << test << '\n';
position = position1;
p = p1;
mass = p1->ComputeMass();
orientation = 0;
angularVelocity = 0;
dt = .033;
gravity.x = 0;
gravity.y = -9.8;
velocity.x = 0;
velocity.y = 0;
//RigidBodies.push_back(this); // Push to global vector of all RigidBodies.
}
// UPDATE at each iteration.
void RigidBody::Step() {
this->velocity += this->gravity * this->dt;
this->position += this->velocity * this->dt;
this->orientation += this->angularVelocity * this->dt;
}
polygon.h:
#include <vector>
#ifndef POLYGON_H
#define POLYGON_H
struct Vector {
float x;
float y;
// Multiplication by scalar quantity.
Vector operator*(const float);
// Addition overload.
Vector operator+=(const Vector);
};
struct Material {
float density;
float restitution;
};
struct Polygon {
std::vector< Vector* > Points;
float volume;
Material m;
Polygon(std::vector< Vector* >, Material, float);
float ComputeMass();
};
struct RigidBody {
float mass;
float volume;
float dt;
// Linear
Vector position;
Vector gravity;
Vector velocity;
float acceleration;
// Angular
float orientation;
float angularVelocity;
float torque;
Polygon * p;
// Constructor
RigidBody(Vector, Polygon*);
// UPDATE at each iteration.
void Step();
};
// DECLARATION
extern std::vector<RigidBody*> RigidBodies; // Global Vector of RigidBody Pointers.
#endif
Makefile:
sim:
g++ -std=c++11 main.cpp rigid_bodies.cpp rendering.cpp -I include -L lib -l SDL2-2.0.0

In your function CreateBody, RigidBody r1 is created on the stack and ceases to exist when the function returns. Your pointer rigPtr (and the pointers in Points and polPtr) is no longer valid after the end of the function. If you call the CreateBody in a loop you will probably see that you get the same pointers for every call.
The simplest solution is to not use pointers at all, your objects are fairly small and shouldn't be too expensive to copy (or even cheaper to move).
If you really want to use pointers you need to allocate your objects on the heap rather than the stack using new. Note that these objects will then need to the deallocated using delete. A safer solution would be to wrap your pointers in std::shared_ptr or std::unique_ptr which takes care of deleting the objects automatically.

Related

Move mouse smoothly

I'm trying to move the user mouse using mouse_event function in WinAPI. This is my code:
while (LeftMouseDown)
{
POINT cursorPos;
GetCursorPos(&cursorPos);
//X Axis And Y Axis is DWORD Array
mouse_event(MOUSEEVENTF_MOVE, xaxis[iCount], yaxis[iCount], 0, 0);
iCount++;
Sleep(200);
}
It's working good but the problem is that I want the code smooth movement, because the function teleports the cursor instantly and I don't want that, I want it to be smooth transition or something like that.
From what it looks like, you are trying to move across a path of points in a smooth manner.
If so, then you are going to have to interpolate along that path via time.
Essentially, the idea is that you first obtain the total length of the path. Then as you are updating time you obtain a total distance via the total duration and the elapsed amount of time. Finally, you find the two points where the obtained distance is somewhere in the middle. Then you simply interpolate along those two points to get a relatively accurate point.
With this class you can pass the points for the path and a a duration to specify how long you would like to be moving along the path for. Then you would simply update it via time intervals.
Mover.h
#include <chrono>
#include <vector>
#ifndef MOVER_H
#define MOVER_H
struct Point {
int x, y;
Point(int x_, int y_)
: x(x_), y(y_) {
}
Point() : Point(0, 0) {
}
};
class Mover {
public:
struct PointData {
float total;
float distance;
Point p1;
Point p2;
PointData()
: total(0.f),
distance(0.f) {
}
PointData(float total, float distance, Point p1, Point p2)
: total(total),
distance(distance),
p1(p1),
p2(p2) {
}
};
using TimePoint = std::chrono::microseconds;
private:
std::vector<Point> m_points;
std::vector<PointData> m_distances;
TimePoint m_duration;
TimePoint m_elapsed;
float m_length;
public:
Mover(std::initializer_list<Point> points, TimePoint duration = std::chrono::microseconds(2000000));
template<typename iter_t>
Mover(iter_t begin, iter_t end, TimePoint duration = std::chrono::microseconds(2000000))
: m_points(begin, end),
m_duration(duration),
m_elapsed(std::chrono::milliseconds(0)) {
updateLength();
}
Mover(const Mover&) = default;
Mover& operator=(const Mover&) = default;
Point update(TimePoint delta);
bool isComplete() const;
void setDuration(TimePoint duration);
TimePoint getDuration() const;
TimePoint getElapsed() const;
private:
void updateLength();
};
#endif // MOVER_H
Mover.cpp
#include "Mover.h"
#include <algorithm>
#include <cmath>
Mover::Mover(std::initializer_list<Point> points, TimePoint duration)
: Mover(points.begin(), points.end(), duration)
{
}
Point Mover::update(TimePoint delta)
{
const auto comparison = [](float left, const PointData& right) {
return left < right.total;
};
m_elapsed = std::min(m_elapsed + delta, m_duration);
const float length = (static_cast<float>(m_elapsed.count()) / static_cast<float>(m_duration.count())) * m_length;
auto& data = *std::prev(std::upper_bound(m_distances.begin(), m_distances.end(), length, comparison));
const float percent = (length - data.total) / data.distance;
Point point(data.p1.x + percent * (data.p2.x - data.p1.x), data.p1.y + percent * (data.p2.y - data.p1.y));
return point;
}
bool Mover::isComplete() const
{
return m_duration == m_elapsed;
}
void Mover::setDuration(TimePoint duration)
{
m_duration = duration;
}
Mover::TimePoint Mover::getDuration() const
{
return m_duration;
}
Mover::TimePoint Mover::getElapsed() const
{
return m_elapsed;
}
void Mover::updateLength()
{
auto distance = [](float x1, float y1, float x2, float y2) -> float{
return std::sqrt(((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
};
float length = 0.f;
for (std::size_t index = 0; (index + 1) < m_points.size(); ++index) {
const float dist = distance(m_points[index].x, m_points[index].y, m_points[index + 1].x, m_points[index + 1].y);
m_distances.emplace_back(length, dist, m_points[index], m_points[index + 1]);
length += dist;
}
m_length = length;
}
Example
#include <iostream>
#include "Mover.h"
int main() {
std::vector<Point> points{ { 0, 0 }, { 100, 100 } };
Mover move(points.begin(), points.end());
auto t1 = std::chrono::steady_clock::now();
while (!move.isComplete()) {
auto t2 = std::chrono::steady_clock::now();
auto point = move.update(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1));
std::cout << point.x << ' ' << point.y;
t1 = t2;
}
}
It's worth mentioning that in order to use this you are going to have to keep track of the time in order to update the mover. So it's probably worth implementing a Clock class or something to keep track of the time for you.
Also, if you want to move along the path relative to the current cursor position, then you would have to simply add the cursor position to the active path point.
I know this is very late but I might as well answer it.
while doing golang I used this library called robot.go and over there they have a function that does the smooth input. So if you want you can use that as a reference.
https://github.com/go-vgo/robotgo/blob/master/mouse/mouse_c.h
looking at your code your mouse will jump pixels every 200 ms.
while (LeftMouseDown)
{
POINT cursorPos;
GetCursorPos(&cursorPos);
//X Axis And Y Axis is DWORD Array
int i;
for (i = 0; i < 20; i++)
{
mouse_event(MOUSEEVENTF_MOVE, (xaxis[icount]-cursorPos.x)/20, (yaxis[icount]-cursorPos.y)/20, 0, 0);
iCount++;
Sleep(10);
}
}

Calculate car movement and distance with C++ classes

This program compiles however, I need to get this function to move on the x & y coordinate and then output the total distance traveled. The xCord moves it right and left while the yCord moves it up and down. I think I need to update my int Taxicab::getDistanceTraveled(), void Taxicab::moveX(int getX), & void Taxicab::moveX(int getX). But for the life of me can't figure out what to do to get it to update properly. When I compile and run it gives me 132617596 for cab1 distance travelled and 0 for the Y coordinate on cab2. Thanks for the help!
#ifndef TAXI_CPP
#define TAXI_CPP
class Taxicab
{
private:
int xCord;
int yCord;
int totalDist;
public:
Taxicab(); //default constructor
Taxicab(int, int); //overload constructor
int getX(); //returns X coordinate
int getY(); //returns Y coordinate
int getDistanceTraveled(); //returns distance calculation
void moveX(int); //moves X left or right
void moveY(int); //moves Y left or right
};
#endif // !TAXI_CPP
#include "Taxi.h"
#include <iostream>
#include <math.h>
#include <cstdlib>
using std::cout;
using std::cin;
using std::endl;
using std::abs;
Taxicab::Taxicab() //default constructor
{
}
Taxicab::Taxicab(int xCord, int yCord) //overload constructor
{
xCord = 0; //initialize to 0
yCord = 0; //initialize to 0
totalDist = 0; //initialize to 0
}
int Taxicab::getX()
{
return xCord; //return x coordinate
}
int Taxicab::getY()
{
return yCord; //return y coordinate
}
void Taxicab::moveX(int getX)
{
int moveX = 0;
moveX = moveX + getX;
}
void Taxicab::moveY(int getY)
{
int moveY = 0;
moveY = moveY + getY;
}
int Taxicab::getDistanceTraveled()
{
return abs(xCord) + abs(yCord);
}
#include <iostream>
#include "Taxi.h"
#include <math.h>
using std::cout;
using std::cin;
using std::endl;
int main()
{
Taxicab cab1;
Taxicab cab2(5, -8);
cab1.moveX(3);
cab1.moveY(-4);
cab1.moveX(-1);
cout << cab1.getDistanceTraveled() << endl;
cab2.moveY(7);
cout << cab2.getY() << endl;
}
Your constructors do not make sense.
In default constructor you have to initialize member variables to something, otherwise their values are undefined and could be set to some random value. Try these maybe:
Taxicab::Taxicab() //default constructor
{
xCord = 0; //initialize to 0
yCord = 0; //initialize to 0
totalDist = 0; //initialize to 0
}
Taxicab::Taxicab(int xCord, int yCord) //overload constructor
{
this->xCord = xCord;
this->yCord = yCord;
totalDist = 0; //initialize to 0
}
Methods to move taxi also do not make much sense. Maybe something like that would be better:
void Taxicab::moveX(int offsetX)
{
totalDist += abs(offsetX);
xCoord += offsetX;
}
void Taxicab::moveY(int offsetY)
{
totalDist += abs(offsetY);
yCoord += offsetY;
}
int Taxicab::getDistanceTraveled()
{
return totalDist;
}

C++ & SFML Separating Axis Theorem

I'm trying to implement collision detection in sfml using the separating axis theorem but my function to get the min translation vector (getMtv()) is always returning that there is a collision (MTV::IsValid()). I was following a tutorial here
but I can't see where I went wrong.
#include <iostream>
#include <math.h>
#include <SFML/Graphics.hpp>
#include <gtest/gtest.h>
typedef sf::Vector2f Vector2;
typedef sf::Vector2f Axis;
typedef sf::Vector2f Projection;
typedef std::vector<Axis> AxesVec;
class MTV
{
private:
bool _valid;
Axis _axis;
float _overlap;
public:
MTV(Axis axis, float overlap, bool valid)
{
_valid = valid;
_overlap = overlap;
_axis = axis;
}
bool IsValid() const
{
return _valid;
}
};
Vector2 perpendicular(Vector2 v)
{
return Vector2(v.y, -v.x);
}
float dot(Vector2 vec1, Vector2 vec2)
{
return (vec1.x * vec2.x) + (vec1.y * vec2.y);
}
float magnitude(Vector2 v)
{
return std::sqrt(dot(v,v));
}
class Polygon : public sf::ConvexShape
{
public:
const AxesVec& GetAxes() const
{
return axes;
}
AxesVec axes;
void generateAxes()
{
for (int i = 0; i < getPointCount(); i++)
{
// get the current vertex
Vector2 p1 = getPoint(i); //shape.vertices[i];
// get the next vertex
Vector2 p2 = getPoint(i + 1 == getPointCount() ? 0 : i + 1);
// subtract the two to get the edge vector
Vector2 edge = p1 - p2;
// get either perpendicular vector
Vector2 normal = perpendicular(edge);
// the perp method is just (x, y) => (-y, x) or (y, -x)
axes.push_back(normal / magnitude(normal));
}
};
float cross(Vector2 vec1, Vector2 vec2)
{
return (vec1.x * vec2.y) - (vec1.y * vec2.x);
}
Vector2 project(Polygon p, Axis axis)
{
float min = dot(axis, p.getPoint(0)); //axis.dot(shape.vertices[0]);
float max = min;
for (int i = 1; i < p.getPointCount(); i++)
{
// NOTE: the axis must be normalized to get accurate projections
float prj = dot(axis, p.getPoint(i));//axis.dot(shape.vertices[i]);
if (prj < min)
{
min = prj;
}
else if (prj > max)
{
max = prj;
}
}
//Projection proj = new Projection(min, max);
return Projection(min, max);
}
class Collison
{
private:
Vector2 mtv;
Polygon a;
Polygon b;
};
bool overlap(Projection a, Projection b)
{
// x = min & y = max
return !(a.x > b.y || a.x > b.y);
}
float getOverlap(Projection a, Projection b)
{
// x = min & y = max
return (a.y < b.y) ? a.y - b.x : b.y - a.x;
}
MTV getMtv(Polygon a, Polygon b)
{
float overlapMax = std::numeric_limits<float>::infinity();// really large value;
float Overlap;
Axis smallest;// = null;
AxesVec axesA = a.GetAxes();
AxesVec axesB = b.GetAxes();
// loop over the axes1
for (auto&& axis : axesA) //for (int i = 0; i < axes1.length; i++)
{
//Axis axis = axes1[i];
// project both shapes onto the axis
Projection pA = project(a, axis);
Projection pB = project(b, axis);
// do the projections overlap?
if (!overlap(pA, pB)) //(!p1.overlap(p2))
{
// then we can guarantee that the shapes do not overlap
return MTV(smallest, 0, false);
}
else
{
// get the overlap
float o = getOverlap(pA, pB); //p1.getOverlap(p2);
// check for minimum
if (o < overlapMax)
{
// then set this one as the smallest
Overlap = o;
smallest = axis;
}
}
}
for (auto&& axis : axesB) //for (int i = 0; i < axes1.length; i++)
{
//Axis axis = axes1[i];
// project both shapes onto the axis
Projection pA = project(a, axis);
Projection pB = project(b, axis);
// do the projections overlap?
if (!overlap(pA, pB)) //(!p1.overlap(p2))
{
// then we can guarantee that the shapes do not overlap
return MTV(smallest, 0, false);
}
else
{
// get the overlap
double o = getOverlap(pA, pB); //p1.getOverlap(p2);
// check for minimum
if (o < overlapMax)
{
// then set this one as the smallest
Overlap = o;
smallest = axis;
}
}
}
//MTV mtv = new MTV(smallest, overlap);
// if we get here then we know that every axis had overlap on it
// so we can guarantee an intersection
return MTV(smallest, Overlap, true);
}
int main(int argc, char **argv)
{
Polygon polygon;
polygon.setPointCount(3);
polygon.setPoint(0, sf::Vector2f(500, 100));
polygon.setPoint(1, sf::Vector2f(250, 500));
polygon.setPoint(2, sf::Vector2f(750, 500));
polygon.setFillColor(sf::Color::Red);
polygon.generateAxes();
Polygon polygon2;
polygon2.setPointCount(3);
polygon2.setPoint(0, sf::Vector2f(100, 0));
polygon2.setPoint(1, sf::Vector2f(50, 150));
polygon2.setPoint(2, sf::Vector2f(150, 150));
polygon2.generateAxes();
//polygon2.setPoint(0, sf::Vector2f(100, 0));
//polygon2.setPoint(1, sf::Vector2f(500, 150));
//polygon2.setPoint(2, sf::Vector2f(250, 150));
polygon2.setFillColor(sf::Color::Green);
sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
// run the program as long as the window is open
while (window.isOpen())
{
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event))
{
// "close requested" event: we close the window
if (event.type == sf::Event::Closed)
window.close();
}
// clear the window with black color
window.clear(sf::Color::Black);
// draw everything here...
window.draw(polygon);
window.draw(polygon2);
std::cout << getMtv(polygon, polygon2).IsValid() << std::endl;
// end the current frame
window.display();
}
return 0;
}

Creating boost.geometry.model.polygon from 2D C List

Supposed I have the following dataset
double * data = (double *) malloc(sizeof(double) * 100 * 2);
for (ii = 0; ii < 100; ii++) {
data[2*ii] = ii;
data[2*ii + 1] = ii;
}
how can I create a boost polygon from this data?
thanks
A complete example
#include <iostream>
#include <boost/polygon/polygon.hpp>
#include <vector>
// Some typedefs
namespace bpl = boost::polygon;
typedef bpl::polygon_data<double> Polygon;
typedef bpl::polygon_traits<Polygon>::point_type Point;
int main() {
// Your C-style data (assumed (x,y) pairs)
double * data = (double *) malloc(sizeof(double) * 100 * 2);
for (int ii = 0; ii < 100; ii++) {
data[2*ii] = ii;
data[2*ii + 1] = ii;
}
// Convert to points
std::vector<Point> points;
for (int i=0;i<100;++i)
points.push_back(Point(data[2*i],data[2*i+1]));
// Create a polygon
Polygon polygon;
polygon.set(points.begin(),points.end());
// Do something with the polygon
std::cout << "Perimeter : " << bpl::perimeter(polygon) << std::endl;
std::cout << "Area : " << bpl::area(polygon) << std::endl;
return 0;
}
Just to illustrate the flexibility you actually have: with a bit of extra typedef work, its possible to define your own pair-of-doubles point type which can be aliased onto your data, which avoids the intermediate copy...
#include <iostream>
#include <boost/polygon/polygon.hpp>
#include <vector>
// Define a point type which can be aliased to your 'C' points
struct Pt {
double x;
double y;
};
// Some typedefs
namespace bpl = boost::polygon;
typedef bpl::polygon_data<double> Polygon;
// Add the necessary to use Pt
namespace boost {
namespace polygon {
template <> struct geometry_concept<Pt> {typedef point_concept type;};
template <> struct point_traits<Pt> {
typedef double coordinate_type;
static inline coordinate_type get(const Pt& pt,orientation_2d orient) {
return (orient == HORIZONTAL ? pt.x : pt.y);
}
};
template <> struct point_mutable_traits<Pt> {
static inline void set(Pt& pt, orientation_2d orient, int value) {
if(orient == HORIZONTAL)
pt.x = value;
else
pt.y = value;
}
static inline Pt construct(double x,double y) {
Pt r;
r.x=x;
r.y=y;
return r;
}
};
}
}
int main() {
// Your C-style data (assumed (x,y) pairs)
double * data = (double *) malloc(sizeof(double) * 100 * 2);
for (int ii = 0; ii < 100; ii++) {
data[2*ii] = ii;
data[2*ii + 1] = ii;
}
// Reinterpret your data as an array of Pt
const Pt*const pts=reinterpret_cast<const Pt*>(data);
// Create a polygon
Polygon polygon;
polygon.set(pts,pts+100);
// Do something with the polygon
std::cout << "Perimeter : " << bpl::perimeter(polygon) << std::endl;
std::cout << "Area : " << bpl::area(polygon) << std::endl;
return 0;
}
And this trend could be continued to a custom polygon class.

Have shape and circle class, and point class. Segmentation fault when creating circle with point class as one parameter

Here is my Shape.h. Ignore all the code that is commented out. That is from a version that I believe was incorrect but I left it in there in case I was wrong.
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <math.h>
#include "Point.h"
using namespace std;
class Shape {
public:
Shape() {}
virtual ~Shape() {}
/*
virtual float calcArea(const Shape& s) const = 0;
virtual float calcCircum(const Shape& s) const = 0;
virtual string calcBox(const Shape& s) const = 0;
virtual void display(const Shape& s) const = 0;
*/
virtual float calcArea() const = 0;
virtual float calcCircum() const = 0;
virtual string calcBox() const = 0;
virtual void display() const = 0;
};
class Circle : public Shape {
public:
int radius;
int pointX;
int pointY;
Point *middlePoint;
float PI;
Circle() : Shape() {
middlePoint = new Point(0,0);
radius = 0;
}
~Circle() {}
Circle(int rad, Point& p) : Shape() {
PI = 3.141592;
*middlePoint = p;
pointX = p.getX();
pointY = p.getY();
radius = rad;
}
// float calcArea(const Circle& s) const {
float calcArea() const {
float tempArea;
// tempArea = PI * s.radius * s.radius;
tempArea = PI * radius * radius;
return tempArea;
}
// float calcCircum(const Circle& s) const {
float calcCircum() const {
// int diameter = 2 * s.radius;
int diameter = 2 * radius;
float tempCircum;
tempCircum = PI * diameter;
return tempCircum;
}
// string calcBox(const Circle& s) const {
string calcBox() const {
// int x = s.pointX;
// int y = s.pointY;
// int r = s.radius;
int x = pointX;
int y = pointY;
int r = radius;
int tlX = x - r;
int tlY = y + r;
int blX = x - r;
int blY = y - r;
int trX = x + r;
int trY = y + r;
int brX = x + r;
int brY = y - r;
Point *topLeft = new Point(tlX,tlY);
Point *bottomLeft = new Point(blX,blY);
Point *topRight = new Point(trX,trY);
Point *bottomRight = new Point(brX,brY);
stringstream output;
string tempOut;
output << *topLeft << *bottomLeft << *topRight << *bottomRight;
tempOut = output.str();
return tempOut;
}
// void display(const Circle& s) const {
void display() const {
cout << "Class Name: Circle" << endl;
// float tmpArea = calcArea(s);
float tmpArea = calcArea();
cout << "Area = " << tmpArea << endl;
// cout << "Radius = " << s.radius << endl;
cout << "Radius = " << radius << endl;
// float tmpCircum = calcCircum(s);
float tmpCircum = calcCircum();
cout << "Circumference = " << tmpCircum << endl;
cout <<"Middle Point = " << middlePoint;
// string bbox = calcBox(s);
string bbox = calcBox();
cout <<"Bounding Box Points = " << bbox;
}
};
Here is my TMA4Question1.cpp code.
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <math.h>
#include "Shape.h"
int main() {
Point *circlePoint = new Point(10,-5);
Circle *mainCircle = new Circle(23,*circlePoint);
}
Ok. Yes this is a homework assignment for University. I'm not looking just for the answer, I would like to know why this program gives me a segmentation fault and how to correct it.
I know the error is in the Circle code, where I pass a pointer to the circlePOint in the constructor for the Circle class. I dont know why it generates a seg fault. I hope someone can provide some insight. Thanks.
Sorry if the code is messy. Had a hard time pasting it into here properly with 4 spaces and all that.
middlePoint is not allocated in your second Circle constructor. You are assigning a value to it before giving it some memory. As an aside, I don't see why anything there needs to be a pointer.
Why do you use pointers to Points inside your classes at all? You only generate memory leaks this way and (without your own copy operations) cause problems with as the midpoints could be shared by different circles.
PS: And it's not needed to have a PI value (even as non-const) in every circle - just use the constant from (afair) cmath for it.