I have a class named Particle and i want to create a vector of particles. The problem is that my code is not drawing the objects stored in the vector. I tried different implementations, the first one was:
std::vector<Particle> particles(10);
and then i filled the vectors:
for(size_t i = 0; i < 10; ++i) particles.emplace_back(new Particle(false));
for drawing i used:
for(const auto& x: particles) window.draw(x);
the problem is that this is drawing just one object. Then i tried to create a class of particles container with a vector of shared_ptr:
std::vector<std::shared_ptr<Particle>> particle_container;
And the problem is the same, it just draws one particle, i don't know if theres something wrong with my implementation of the class particle or something wrong in the waay i use the draw function of sfml. This is my Particle class:
#include "SFML/Graphics.hpp"
#include <random>
#include <cmath>
#include <limits>
#include <memory>
using namespace sf;
class Particle : public sf::Drawable{
sf::CircleShape particle;
Vector2f position; //current position of the particle
Vector2f velocity; //velocity of the particle
double radius; //radius of each particle
double mass; //mass of the particle
int count; //number of collisions of each particle
bool sick; //if the particle is infected
Color color; //color of the particle
public:
//constructors
Particle(Vector2f _position, Vector2f _velocity, double _radius, double _mass, bool _sick);
Particle(bool sick);
}:
the Particle.cpp:
#include "Particle.h"
template<class T>
double Rand(T first, T last) {
std::random_device dev;
std::default_random_engine eng(dev());
std::uniform_real_distribution<double> dis(first, last);
return dis(eng);
}
Particle::Particle(Vector2f _position, Vector2f _velocity, double _radius, double _mass, bool _sick) {
position = _position;
velocity = _velocity;
radius = _radius;
mass = _mass;
sick = _sick;
if(sick) color = sf::Color::Green;
else color = sf::Color::Red;
//giving values to the particle
particle.setPosition(position);
particle.setRadius(radius);
particle.setFillColor(color);
}
Particle::Particle(bool sick) {
position.x = Rand(0.0, 550.0);
position.y = Rand(0.0, 550.0);
velocity.x = Rand(-0.005, 0.005);
velocity.y = Rand(-0.005, 0.005);
radius = 2.0;
mass = 0.5;
if(sick) color = sf::Color::Green;
else color = sf::Color::Red;
particle.setPosition(position);
particle.setRadius(radius);
particle.setFillColor(color);
}
And this is the particles_container
class particles_container : public sf::Drawable {
std::vector<std::shared_ptr<Particle>> particle_container;
//std::vector<Particle> particle_container;
virtual void draw(sf::RenderTarget &renderTarget, sf::RenderStates renderStates) const;
public:
//default constructor
particles_container();
//constructor with a number of given particles
explicit particles_container(size_t size);
//default destructor
~particles_container() override;
//returns the container
std::vector<std::shared_ptr<Particle>> getContainer();
//another function to draw
void drawContainer(sf::RenderWindow &window);
};
the particles_container.cpp:
void particles_container::draw(RenderTarget &renderTarget, sf::RenderStates renderStates) const {
for (const auto & i : particle_container) {
renderTarget.draw(*i);
}
}
particles_container::particles_container(size_t size) {
if(size > 0){
for(size_t i = 0; i < size; ++i) particle_container.emplace_back(new Particle(false));
}
}
std::vector<std::shared_ptr<Particle>> particles_container::getContainer() {
return particle_container;
}
void particles_container::drawContainer(RenderWindow &window) {
for (auto & i : particle_container) {
window.draw(*i);
}
}
and finally this is my main.cpp:
#include "Particle.h"
#include "particles_container.h"
int main() {
sf::RenderWindow window(sf::VideoMode (600, 600), "PF");
std::vector<Particle> particles(10);
for(size_t i = 0; i < 10; ++i) particles.emplace_back(new Particle(false));
Particle p1(sf::Vector2f(45.0,45.0), sf::Vector2f(0.01,0.005), 2, 0.5, false);
particles_container parts(100);
Particle p3(true);
std::vector<std::shared_ptr<Particle> > my_vector(10);
for(size_t i = 0; i < 10; ++i) my_vector.emplace_back(new Particle(false));
while(window.isOpen()){
sf::Event event;
while(window.pollEvent(event)){
switch (event.type) {
case sf::Event::Closed:
window.close();
break;
}
}
window.clear();
//parts.drawContainer(window);
//window.draw(parts);
for(const auto& x: particles) window.draw(x);
window.display();
}
}
this is the output:
output
Any help or advice would be greatly appreciated, thanks.
I am using:
SFML 2.5.1 and c++17
Your Rand function constructs a new random device every time, which has a high probability to always return the same number sequence. Move the construction of dev out of your Rand function.
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;
}
I am new to c++ and I get this error “Invalid operands to binary expression (‘const Vector’ and ‘const Vector’)” and I have no idea where to look at in my own code.
The error appears at the line “{return __x < __y;}” in _functional_base:
#if _LIBCPP_STD_VER > 11
template <class _Tp = void>
#else
template <class _Tp>
#endif
struct _LIBCPP_TYPE_VIS_ONLY less : binary_function<_Tp, _Tp, bool>
{
_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
bool operator()(const _Tp& __x, const _Tp& __y) const
{return __x < __y;}
};
But my real code looks like this:
//
// MCP.cpp
// Speciale
//
// Created by Zaki G on 21/11/15.
// Copyright © 2015 Zaki G. All rights reserved.
//
#include "mcp.h"
#include <cmath>
#include <string>
#include <iomanip>
#include "Vector.h"
#include "Particle.h"
#include "Detector.h"
#include "Cave.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <map>
MCP::MCP(char* name,Vector& dimension,Vector& QuartzDimension, int NumberSubQuartz, double ElectronicThickness, double Reflective_index, double z_axis_sign): Detector(name, dimension, 0)
{
MCP_Dimension = dimension;
MCP_QuartDimension = QuartzDimension;
MCP_NumberSubQuartz = NumberSubQuartz;
MCP_ElectronicThickness = ElectronicThickness;
MCP_Quartz_Reflective_index = Reflective_index;
MCP_z_axis_sign = z_axis_sign;
}
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
Vector MCP::Quartz_wall_Intersection(Detector& name, Vector &inter_front_quartz, Vector &path_photon, Vector &direction_vector, int reflection_on_off, Vector &Cherenkov_photon) //The direction vector is the vector against the normal vectors of the walls, and the Cherenkov_photon is only called to
//calculate the refelcted photon.
{ // Function for finding the intersection with the quartz walls and it can also calculated the reflected photon vector//
Vector detector_posi = name.fPosition; // The position of the detector
double Quartz_L_corner_x = detector_posi.GetX()-(0.053/2);
double Quartz_L_corner_y = detector_posi.GetY()-(0.053/2);
double Quartz_L_corner_z = detector_posi.GetZ();
Vector loop_Quartz_Lcorner = (Quartz_L_corner_x, Quartz_L_corner_y, Quartz_L_corner_z); //The position of the Quartz down left corner.
//Generating walls and roofs position for every sub MCP quartz.
int number_of_walls =int(sqrt(MCP_NumberSubQuartz)); //4+1 walls in total remember "+1"
int walls_position[number_of_walls+1];
for (int i = 0; i<=number_of_walls; i++)
{
walls_position[i] = loop_Quartz_Lcorner.GetX()+i*(0.053/sqrt(MCP_NumberSubQuartz)); // 0.053 is the length and width of the MCP Quartz
}
int number_of_roof =int(sqrt(MCP_NumberSubQuartz));
int roofs_position[number_of_roof+1];
for (int i = 0; i<=number_of_roof; i++)
{
roofs_position[i] = loop_Quartz_Lcorner.GetY()+i*(0.053/sqrt(MCP_NumberSubQuartz));
}
//loop for which section (Divided quartz) is the generated particle close to.
int en = 0;
int to = 0;
double x_array[2];
double y_array[2];
for (int i = 0; i<=number_of_walls; i++)
{
if ( abs(inter_front_quartz.GetX()) - abs(walls_position[i])<= (0.053/sqrt(MCP_NumberSubQuartz))){
x_array[en] = walls_position[i];
en =+1;
if ( abs(inter_front_quartz.GetY()) - abs(roofs_position[i]) <= (0.053/sqrt(MCP_NumberSubQuartz))){
y_array[to] = roofs_position[i];
to =+1;
}
}
}
// Defining the four point in which the particle is incapsuled within the divided quartz:
Vector position_array_one_zero = Vector(x_array[0], y_array[0], 0);
Vector position_array_one_one = Vector(x_array[0], y_array[1], 0);
Vector position_array_two_zero = Vector(x_array[1], y_array[0], 0);
Vector position_array_two_one = Vector(x_array[1], y_array[1], 0);
//Defining the four normal vectors for the incapsuled walls and roofs:
//Walls normal vector:
//Left:
Vector normal_left = (position_array_one_one-position_array_one_zero).Cross(Vector(position_array_one_zero.GetX(),position_array_one_zero.GetY(),position_array_one_zero.GetZ()-0.020)-position_array_one_zero);
//Right:
Vector normal_right = (position_array_two_one-position_array_two_zero).Cross(Vector(position_array_two_zero.GetX(),position_array_two_zero.GetY(),position_array_two_zero.GetZ()-0.020)-position_array_two_one);
//Roof normal vectors:
//Top:
Vector normal_top = (position_array_two_one-position_array_one_one).Cross(Vector(position_array_one_one.GetX(),position_array_one_one.GetY(),position_array_one_one.GetZ()-0.020)-position_array_one_one);
//Bottom:
Vector normal_bottom = (position_array_one_zero-position_array_two_zero).Cross(Vector(position_array_two_zero.GetX(),position_array_two_zero.GetY(),position_array_two_zero.GetZ()-0.020)-position_array_two_zero);
// Putting the normal vectors in a array
Vector normal_walls_roof[4]={normal_left,normal_right,normal_top,normal_bottom};
//point on the surface for every normal vector which coresponds to the each surface
map<Vector, Vector> quartz_surface_position;
quartz_surface_position[normal_walls_roof[1]] =Vector(position_array_one_zero) + Vector(0, (0.053/8), (0.020/2)*MCP_z_axis_sign ) ; //Left
quartz_surface_position[normal_walls_roof[2]] =Vector(position_array_two_zero) + Vector(0, (0.053/8), (0.020/2)*MCP_z_axis_sign ); //Right
quartz_surface_position[normal_walls_roof[3]] =Vector(position_array_one_one) + Vector((0.053/8), 0, (0.020/2)*MCP_z_axis_sign ); //Top
quartz_surface_position[normal_walls_roof[4]] =Vector(position_array_two_one) + Vector(-(0.053/8), 0, (0.020/2)*MCP_z_axis_sign );//Bottom
Vector Quartz_wall_Intersection; //The intersection point on one of the walls
Vector return_intersection_vector;
//Looping over which wall it hits
for (int i=0; i<=3; i++){
double dot_normal = direction_vector.Dot(normal_walls_roof[i]);
if (dot_normal < 10e-18)
{ //the dot product should be less than zero so the angle is stump (over 90 degree)
//The intersection point on one of the walls
Vector Quartz_wall_Intersection = path_photon-(((path_photon-quartz_surface_position[i]).Dot(normal_walls_roof[i])/dot_normal)*direction_vector);
Vector w_quartz = Quartz_wall_Intersection - quartz_surface_position[i];
// If the intersection of the plane falls outside window, return a
// NAN vector.
if (w_quartz.GetY() > name.GetHeight() || w_quartz.GetZ() > name.GetWidth())
{
return_intersection_vector = Vector(NAN,NAN,NAN);
}
else
{
if (reflection_on_off==1) //If the reflected momentum is needed:
{
// Refelction vector with in the quartz walls for the Cherenkov photons
Vector Reflection_vector_quartz = Cherenkov_photon -2.0*(Cherenkov_photon.Dot(normal_walls_roof[i]))*normal_walls_roof[i];
return_intersection_vector = Reflection_vector_quartz;
}
else
{
return_intersection_vector = Quartz_wall_Intersection;
}
}
}
}
return return_intersection_vector;
}
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
void MCP::Cherenkov_Photon_Generation(const Particle& pname, Vector &first_intersection, Vector &second_intersection, Vector pathPhoton_array[], Vector CherenkovPhoton_array[])
{
// Now we generates cherenkov photons along the particle path.//
Vector particle_momentum = pname.GetMomentum();
// The end_value is a constant, which describes the position where the particle is at the end of the quart plan.
double end_value =(second_intersection.GetX()-first_intersection.GetX())/particle_momentum.GetX();
// Generating the path for the particles where the photon should emits as Cherenkov light.
for (int n=0; n<=1000; n++) //1000 Cherenkov photons per particle
{
srand( (unsigned int) time(0) );
double random_number_d = ( double(rand()) / double(RAND_MAX))*end_value; // generate numbers between 0 and end_value.
double path_photon_x =first_intersection.GetX() + random_number_d*particle_momentum.GetX();
double path_photon_y =first_intersection.GetY() + random_number_d*particle_momentum.GetY();;
double path_photon_z =first_intersection.GetZ() + random_number_d*particle_momentum.GetZ();
Vector path_photon(path_photon_x,path_photon_y,path_photon_z);
double random_angle = (rand()/RAND_MAX)* (2*M_PI); //Generate number between 0 and 2*Pi
Vector velocity_vector = pname.GetVelocity();
double v = velocity_vector.Length();
double Cherenkov_Angle = acos((1.0)/(MCP_Quartz_Reflective_index*v));
double x = (pname.GetMomentum()).Length()*sin(Cherenkov_Angle)*cos(random_angle); //random angle is from 0-2pi
double y = (pname.GetMomentum()).Length()*sin(Cherenkov_Angle)*sin(random_angle);
double z = (pname.GetMomentum()).Length()*cos(Cherenkov_Angle);
Vector Cherenkov_photon(x,y,z);
//pathPhoton_Cherenkov_array[path_photon] = Cherenkov_photon;
pathPhoton_array[n] = path_photon;
CherenkovPhoton_array[n] = Cherenkov_photon;
}
return;
}
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
Vector MCP::MCP_end_Intersection_for_particle(const Particle& pname, Vector &particle_pos, Detector& name)
{
// Intersection with the end surface of the quartz//
// end_position is the position of the end plan of the quartz.
Vector front_quartz_position = name.fPosition;
Vector end_position(front_quartz_position.GetX(),front_quartz_position.GetY(),front_quartz_position.GetZ()+(0.020*MCP_z_axis_sign));
Vector particle_momentum = pname.GetMomentum();
Vector normal_end_quartz(0, 0, MCP_QuartDimension.GetX()*MCP_QuartDimension.GetY()*MCP_z_axis_sign);
double dot_end_quartz = particle_momentum.Dot(normal_end_quartz);
if (dot_end_quartz > 10e-18)
{
return Vector(NAN,NAN,NAN);
}
// inter_end_quartz is the intersection point on the end surface of the quartz
Vector inter_end_quartz = particle_pos-(((particle_pos-end_position).Dot(normal_end_quartz)/dot_end_quartz)*particle_momentum);
Vector w_end_quartz = inter_end_quartz - end_position;
// If the intersection of the plane falls outside window, return a
// Zero vector.
if (w_end_quartz.GetX() > MCP_QuartDimension.GetX() || w_end_quartz.GetY() > MCP_QuartDimension.GetY())
{
return Vector(NAN,NAN,NAN);
}
return inter_end_quartz;
}
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
Vector MCP::MCP_end_Intersection_for_Photon(Vector &Photon_momentum, Vector &particle_pos, Detector& name)
{
// Intersection with the end surface of the quartz//
// end_position is the position of the end plan of the quartz.
Vector front_quartz_position = name.fPosition;
Vector end_position(front_quartz_position.GetX(),front_quartz_position.GetY(),front_quartz_position.GetZ()+(0.020*MCP_z_axis_sign));
Vector normal_end_quartz(0, 0, MCP_QuartDimension.GetX()*MCP_QuartDimension.GetY()*MCP_z_axis_sign);
double dot_end_quartz = Photon_momentum.Dot(normal_end_quartz);
if (dot_end_quartz > 10e-18)
{
return Vector(NAN,NAN,NAN);
}
// inter_end_quartz is the intersection point on the end surface of the quartz
Vector inter_end_quartz = particle_pos-(((particle_pos-end_position).Dot(normal_end_quartz)/dot_end_quartz)*Photon_momentum);
Vector w_end_quartz = inter_end_quartz - end_position;
// If the intersection of the plane falls outside window, return a
// Zero vector.
if (w_end_quartz.GetX() > MCP_QuartDimension.GetX() || w_end_quartz.GetY() > MCP_QuartDimension.GetY())
{
return Vector(NAN,NAN,NAN);
}
return inter_end_quartz;
}
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
void MCP::MCP_Intersection(const Particle& pname, Vector &particle_pos, Detector& name, Vector intersection_array[], int array_size)
{
//Intersection with the front surface of the MCP which is the quartz.//
Vector particle_momentum = pname.GetMomentum(); //Momentum of the particle
Vector front_quartz_position = name.fPosition; // position of the MCP on the FIT (Husk nedeunder MCP flad position)
Vector normal_front_quartz(0,0,MCP_QuartDimension.GetY()*MCP_QuartDimension.GetX());
double dot_front_quartz = particle_momentum.Dot(normal_front_quartz);
if (dot_front_quartz > 10e-18)
{
//return Vector(NAN, NAN, NAN);
}
// inter_front_quartz is the intersection point on the quartz
Vector inter_front_quartz = particle_pos-(((particle_pos-front_quartz_position).Dot(normal_front_quartz)/dot_front_quartz)*particle_momentum);
Vector w = inter_front_quartz - front_quartz_position;
// If the intersection of the plane falls outside window, return a
// Zero vector.
if (w.GetX() > name.GetHeight() || w.GetY() > name.GetWidth())
{
//return Vector(NAN,NAN,NAN);
}
//---------------------------------------------------------------------
// Intersection with the end surface of the quartz//
// end_position is the position of the end plan of the quartz. ---------.men hvad med protonen flyver den videre igennem MCP?!!!
Vector end_position(front_quartz_position.GetX(),front_quartz_position.GetY(),front_quartz_position.GetZ()+(0.020*MCP_z_axis_sign));
Vector normal_end_quartz(0, 0, MCP_QuartDimension.GetX()*MCP_QuartDimension.GetY()*MCP_z_axis_sign);
double dot_end_quartz = particle_momentum.Dot(normal_end_quartz);
if (dot_end_quartz > 10e-18) // If it does not intersect with the end panel, then it must intersect with the walls of the MCP.
{
//Here I find the wall intersection
Vector zero_vector(NAN,NAN,NAN);
Vector particle_intersection_with_wall = Quartz_wall_Intersection(name, inter_front_quartz, particle_pos , particle_momentum, 0 , zero_vector);
//Defining the two arrays for path of the photons and the cherenkov photon vector:
Vector pathPhoton_array[1000];
Vector CherenkovPhoton_array[1000];
Cherenkov_Photon_Generation(pname, inter_front_quartz, particle_intersection_with_wall, pathPhoton_array, CherenkovPhoton_array);
//slette Vector array_path_cherenkov_photon = Cherenkov_Photon_Generation(pname, inter_front_quartz, particle_intersection_with_wall);
static Vector intersection_array[1000];
//Here it finds out that the photon intersect with the walls or not.
for (int i = 0; i <= sizeof(pathPhoton_array); i++)
{
Vector photon_intersection_with_wall = Quartz_wall_Intersection(name, inter_front_quartz, pathPhoton_array[i] , CherenkovPhoton_array[i], 0, zero_vector);
if (photon_intersection_with_wall.GetX() != zero_vector.GetX()) //If the photon interc. with the wall:
{
// Here the reflected photon is found:
Vector reflected_photon = Quartz_wall_Intersection(name, inter_front_quartz, pathPhoton_array[i] , CherenkovPhoton_array[i], 1, CherenkovPhoton_array[i]);
//The reflected photon is intersected with MCP
Vector intersection_with_end_MCP = MCP_end_Intersection_for_Photon(reflected_photon, photon_intersection_with_wall, name);
intersection_array[i] = intersection_with_end_MCP;
//return Intersection; // tænk lige over det
}
else // If the photon do not intersect with the wall then:
{
Vector intersection_with_end_MCP = MCP_end_Intersection_for_Photon(CherenkovPhoton_array[i], pathPhoton_array[i], name);
//Intersection[] = intersection_with_end_MCP;
intersection_array[i] = intersection_with_end_MCP;
//return Intersection; // tænk lige over det
}
}
}
//The particle intersection with the MCP directly
Vector intersection_with_end_MCP = MCP_end_Intersection_for_particle(pname, particle_pos, name);
//Intersection[] = intersection_with_end_MCP;
//Generate Cherenkov photon in 2D array
Vector pathPhoton_array[1000] = {};
Vector CherenkovPhoton_array[1000] = {};
Cherenkov_Photon_Generation(pname, inter_front_quartz, intersection_with_end_MCP, pathPhoton_array, CherenkovPhoton_array);
Vector zero_vector(NAN,NAN,NAN);
for (int i = 0; i <= sizeof(CherenkovPhoton_array); i++)
{
Vector photon_intersection_with_wall = Quartz_wall_Intersection(name, inter_front_quartz, pathPhoton_array[i], CherenkovPhoton_array[i], 0, zero_vector);
if (photon_intersection_with_wall.GetX()!= NAN) //If the photon interc. with the wall:
{
// Here the reflected photon is found:
Vector reflected_photon = Quartz_wall_Intersection(name, inter_front_quartz, pathPhoton_array[i] , CherenkovPhoton_array[i], 1, CherenkovPhoton_array[i]);
//The reflected photon is intersected with MCP
Vector intersection_with_end_MCP = MCP_end_Intersection_for_Photon(reflected_photon, photon_intersection_with_wall, name);
intersection_array[i] = intersection_with_end_MCP;
}
else
{
Vector intersection_with_end_MCP = MCP_end_Intersection_for_Photon(CherenkovPhoton_array[i], pathPhoton_array[i], name);
intersection_array[i] = intersection_with_end_MCP;
}
}
}
Hope someone can figure this out.
#ifndef _VECTOR_H
#define _VECTOR_H
//class ostream;
using namespace std;
class Vector
{
private:
double fX;
double fY;
double fZ;
public:
Vector(double x=0, double y=0, double z=0);
double Length(void) const;
void SetX(double x) { fX= x; }
void SetY(double y) { fY= y; }
void SetZ(double z) { fZ= z; }
double GetX(void) const { return fX; }
double GetY(void) const { return fY; }
double GetZ(void) const { return fZ; }
Vector Cross(const Vector& v) const;
double Dot(const Vector& v) const;
Vector operator+(const Vector& v);
Vector operator-(const Vector& v);
Vector operator=(const Vector& v);
bool operator() (const Vector& lhs, const Vector& rhs) const
{
return (lhs.GetX(),lhs.GetY(),lhs.GetZ()) < (rhs.GetX(),rhs.GetY(),rhs.GetZ());
}
}
;
// Global functions
Vector operator*(const double a, const Vector& v);
Vector operator*(const Vector& v, const Vector& u);
std::ostream& operator<<(std::ostream& o, const Vector& v);
#endif
The problem, as pointed out in the last comment, is map<Vector, Vector>. This is a sorted associative container. Its Key is a Vector, and the default order is std::less<Vector>. The compiler duly instantiates std::less<Vector>, finds no specializations, and fails on <. You'll need to provide one, but it can be simple: return std::tie(r.x, r.y, r.z) < std::tie(l.x, l.y, l.z).
PS. normal_walls_roof[] runs from [0] to [3], not [1] to [4].
So here is my code:
//Shapes.cpp
#include <cassert>
#include <cmath>
#include "shapes.h"
using namespace std;
const double PI = 3.14159;
////////////////////////// Ellipse //////////////////////////
Ellipse::Ellipse() : xRad(0), yRad(0){}
Ellipse::Ellipse(double xRad_in, double yRad_in)
: xRad(xRad_in), yRad(yRad_in) {}
double Ellipse::area() const {
return PI * xRad * yRad;
}
void Ellipse::draw(Canvas *canvas) const{
// Iterate through the grid of (x,y) pixel coordinates
// in the canvas.
for(int x = 0; x < CANVAS_WIDTH; ++x){
for(int y = 0; y < CANVAS_HEIGHT; ++y){
// The ellipse contains the point (x,y) if and only if
// ((x-xPos)/xRad)^2 + ((y-yPos)/yRad)^2 <= 1
double xDiff = x - get_xPos();
double yDiff = y - get_yPos();
if( (xDiff/xRad)*(xDiff/xRad) + (yDiff/yRad)*(yDiff/yRad) <= 1 ){
// If the pixel is contained in the ellipse, set it to true
canvas->setPixel(x, y, true);
}
}
}
}
///////////////////////// End Ellipse /////////////////////////
////////////////////////// Circle //////////////////////////
// PUT YOUR CODE (IMPLEMENTATIONS) FOR CIRCLE HERE
Circle::Circle(double rad_in)
: Ellipse(rad_in, rad_in) {}
//Use Ellipse's area function by sending it the radius of the
//circle for the xRad and yRad parameters
//Use Ellipse's draw function
///////////////////////// End Circle /////////////////////////
//////////////////////// Rectangle /////////////////////////
// PUT YOUR CODE (IMPLEMENTATIONS) FOR RECTANGLE HERE
Rectangle::Rectangle(double w_in, double h_in)
: w(w_in), h(h_in) {}
double Rectangle::area() const {
return w * h;
}
void Rectangle::draw(Canvas *canvas) const{
// Iterate through the grid of (x,y) pixel coordinates
// in the canvas.
for(int x = 0; x < CANVAS_WIDTH; ++x){
for(int y = 0; y < CANVAS_HEIGHT; ++y){
// The Rectangle contains the point (x,y) if and only if
// ((x-xPos)/xRad)^2 + ((y-yPos)/yRad)^2 <= 1
double xDiff = x - get_xPos();
double yDiff = y - get_yPos();
if( abs(xDiff) <= w/2 && abs(yDiff) <= h/2 ){
// If the pixel is contained in the Rectangle, set it to true
canvas->setPixel(x, y, true);
}
}
}
}
//////////////////////// End Rectangle //////////////////////
Along with the corresponding .h file:
// Shapes.h
#ifndef SHAPES_H
#define SHAPES_H
#include "Canvas.h"
/////////////////////////// Shape ///////////////////////////
class Shape {
public:
//EFFECTS: creates a shape with initial position (0,0)
Shape() : xPos(0), yPos(0) {}
//EFFECTS: returns the area of this Shape
virtual double area() const = 0;
//MODIFIES: canvas
//EFFECTS: draws this shape onto canvas at its current position
virtual void draw(Canvas *canvas) const {}
//MODIFIES: xPos, yPos
//EFFECTS: sets the position of this shape
void setPosition(double xPos_in, double yPos_in){
xPos = xPos_in;
yPos = yPos_in;
}
double get_xPos() const { return xPos; }
double get_yPos() const { return yPos; }
private:
double xPos; // The x position of this shape
double yPos; // The y position of this shape
};
///////////////////////// End Shape /////////////////////////
////////////////////////// Ellipse //////////////////////////
class Ellipse : public Shape{
public:
Ellipse();
//REQUIRES: xRad_in, yRad_in are non-negative
//EFFECTS: creates an Ellipse with given x and y radii
Ellipse(double xRad_in, double yRad_in);
//EFFECTS: returns the area of this Ellipse
virtual double area() const;
//MODIFIES: canvas
//EFFECTS: draws this shape onto canvas
virtual void draw(Canvas *canvas) const;
private:
double xRad; //Half the x-axis of the ellipse
double yRad; //Half the y-axis of the ellipse
};
///////////////////////// End Ellipse ////////////////////////
///////////////////////////////////////////////////////////////
// DO NOT MODIFY ABOVE THIS LINE //
///////////////////////////////////////////////////////////////
////////////////////////// Circle //////////////////////////
// PUT YOUR CODE (DECLARATION) FOR CIRCLE HERE
class Circle : public Ellipse{
public:
//REQUIRES: rad_in is non-negative
//EFFECTS: creates an Circle with given radius
Circle(double rad_in);
//EFFECTS: returns the area of this Circle
virtual double area() const;
//MODIFIES: canvas
//EFFECTS: draws this shape onto canvas
virtual void draw(Canvas *canvas) const;
private:
double xRad; //Radius of the Circle
double yRad; //Radius of the Circle
};
///////////////////////// End Circle /////////////////////////
//////////////////////// Rectangle /////////////////////////
// PUT YOUR CODE (DECLARATION) FOR RECTANGLE HERE
class Rectangle : public Shape{
public:
//REQUIRES: xRad_in, yRad_in are non-negative
//EFFECTS: creates an Rectangle with given x and y radii
Rectangle(double w_in, double h_in);
//EFFECTS: returns the area of this Rectangle
virtual double area() const;
//MODIFIES: canvas
//EFFECTS: draws this shape onto canvas
virtual void draw(Canvas *canvas) const;
private:
double w; //Length of the Rectangle
double h; //Width of the Rectangle
};
//////////////////////// End Rectangle //////////////////////
#endif /* SHAPES_H */
I am supposed to be making Rectangle derived from Shape and Circle derived from Ellipse, both with the corresponding functions that are present in their implementations, and I thought my code had done so, but I got the following compiler error:
shapes.cpp: In constructor \u2018Circle::Circle(double)\u2019:
shapes.cpp:47:30: error: no matching function for call to \u2018Ellipse::Ellipse()\u2019
: xRad(rad_in), yRad(rad_in) {}
^
shapes.cpp:47:30: note: candidates are:
shapes.cpp:12:1: note: Ellipse::Ellipse(double, double)
Ellipse::Ellipse(double xRad_in, double yRad_in)
^
shapes.cpp:12:1: note: candidate expects 2 arguments, 0 provided
In file included from shapes.cpp:4:0:
shapes.h:45:7: note: Ellipse::Ellipse(const Ellipse&)
class Ellipse : public Shape{
^
shapes.h:45:7: note: candidate expects 1 argument, 0 provided
I really have no idea what's wrong. Please help!
EDIT: Additional Code necessary for compile:
// Canvas.cpp
#include <iostream>
#include <cassert>
#include "Canvas.h"
using namespace std;
///////////////////////// Canvas ///////////////////////////
Canvas::Canvas(){
for(int row = 0; row < CANVAS_HEIGHT; ++row){
for(int col = 0; col < CANVAS_WIDTH; ++col){
grid[row][col] = false;
}
}
}
void Canvas::setPixel(int x, int y, bool value){
assert(0 <= x); assert(x < CANVAS_WIDTH);
assert(0 <= y); assert(y < CANVAS_HEIGHT);
grid[y][x] = value;
}
void Canvas::print() const {
for(int row = 0; row < CANVAS_HEIGHT; ++row){
for(int col = 0; col < CANVAS_WIDTH; ++col){
cout << (grid[CANVAS_HEIGHT-row-1][col] ? PIXEL_ON : PIXEL_OFF) << " ";
}
cout << endl;
}
}
////////////////////////// End Canvas /////////////////////////
And Canvas.h:
#ifndef CANVAS_H
#define CANVAS_H
///////////////////////// Canvas ///////////////////////////
//Canvas Constants
const int CANVAS_WIDTH = 30;
const int CANVAS_HEIGHT = 30;
const char PIXEL_ON = '#';
const char PIXEL_OFF = ' ';
class Canvas {
//OVERVIEW: A Canvas object represents a 2D grid of "pixels"
// which can be set to either "on" or "off". A Canvas
// knows how to print itself out to the terminal. The
// canvas has a fixed width and height and the origin
// (0,0) of the canvas's coordinate system is at the
// bottom left.
public:
//EFFECTS: creates a new Canvas with size CANVAS_WIDTH x CANVAS_HEIGHT
Canvas();
//REQUIRES: the pixel is on the canvas (0 <= x < CANVAS_WIDTH, 0 <= y < CANVAS_HEIGHT)
//MODIFIES: grid
//EFFECTS: if value is true, turns the pixel at (x,y) on
// if value is false, turns the pixel at (x,y) off
void setPixel(int x, int y, bool value);
//EFFECTS: prints this canvas to cout
void print() const;
private:
bool grid[CANVAS_HEIGHT][CANVAS_WIDTH];
};
////////////////////////// End Canvas /////////////////////////
#endif /* CANVAS_H */
Circle inherits from Ellipse, but Ellipse does not have a default constructor. Therefore either provide one, or call the desired constructor of Ellipse in the initialization list of Circle's constructor.
I need to pack triangles into a box as tightly as reasonable, as part of a 3D optimization (I'm stuffing alpha-using segments of different textures into a single different texture, for use with depth-sorting, so textures don't switch with every new tri)
Is there an algorithm for doing this? The triangles themselves can be made to be plyable (transformable to be right angles, effectively making this a box-stuffing algorithm instead), but I would like to avoid this if possible, as it would distort the underlying texture art.
"tight as reasonable" -> Something working is better than nothing.
These code fragments provide a simple solution to stuff shapes (also triangles) band by band into a rectangle.
public abstract class Shape {
protected Point offset = new Point();
public abstract int getHeight();
public abstract int getWidth();
}
public class Triangle extends Shape {
// all points are relative to offset (from Shape)
Point top = new Point(); // top.y is always 0, left.y >= 0 right.y >= 0
Point left = new Point(); // left.x < right.x
Point right = new Point();
public int getHeight() {
return left.y >= right.y ? left.y : right.y;
}
public int getWidth() {
int xmin = left.x <= top.x ? left.x : top.x;
int xmax = right.x >= top.x ? right.x : top.x;
return xmax - xmin;
}
}
public class StuffRectangle extends Shape {
private Point ww = new Point();
private ArrayList<Shape> maintained = new ArrayList<Shape>();
private int insx;
private int insy;
private int maxy;
public int getHeight() {
return ww.y;
}
public int getWidth() {
return ww.x;
}
public void clear() {
insx = 0;
insy = 0;
maxy = 0;
maintained.clear();
}
/**
* Fill the rectangle band by band.
*
* The inserted shapes are removed from the provided shape collection.
*
* #param shapes
* the shapes to insert
* #return the count of inserted shapes.
*/
public int stuff(Collection<Shape> shapes) {
int inserted = 0;
for (;;) {
int insertedInPass = 0;
for (Iterator<Shape> i = shapes.iterator(); i.hasNext();) {
Shape shape = i.next();
// does the shape fit into current band?
int sx = shape.getWidth();
if (insx + sx > getWidth())
continue;
int sy = shape.getHeight();
if (insy + sy > getHeight())
continue;
// does fit
++insertedInPass;
// remove from shapes
i.remove();
// add to maintained and adjust offset
maintained.add(shape);
shape.offset.x = insx;
shape.offset.y = insy;
insx += sx;
if (sy > maxy)
maxy = sy;
}
inserted += insertedInPass;
if (shapes.isEmpty())
break;
// nothing fits current band - try a new band
if (insertedInPass == 0) {
// already a new band - does not fit at all
if (insx == 0)
break;
// start new band
insx = 0;
insy += maxy;
maxy = 0;
continue;
}
}
return inserted;
}
}