Displaying Depth-First Search Graph Traversal C++ - c++

I am working on traversing a graph which I have set up as a class, using vectors to store the vertices and edges. I am using a Depth-First Search on the graph to show paths as it is traversed, but I would like to somehow get my code to display the vertices in order as it goes through them, in a format sort of like this:
<u, i1, i2, ... v>
Where 'u' and 'v' are BOTH the start vertex (I want it to start and end at the same vertex) and the 'i' values are the vertices that it passes through along the way.
This is the function for DFS that I have so far, I've simplified it so that this can be used as a general reference. Is there anything I can modify here in order to get this to display what I want it to? (It is not currently set up to display anything).
vector<Vertex*> vertices;
vector<Edge*> edges;
class Vertex {
public:
Vertex () {};
Vertex (int id, float safetyIndex, string name)
: id(id), safetyIndex(safetyIndex), name(name), previous(NULL), distFromStart(INT_MAX), color("white")
{
vertices.push_back(this);
}
public:
int id;
float safetyIndex;
string name;
int distFromStart;
Vertex* previous;
string color;
};
class Edge {
public:
Edge () {};
Edge (Vertex* intersection1, Vertex* intersection2, int distance)
: intersection1(intersection1), intersection2(intersection2), distance(distance)
{
edges.push_back(this);
}
bool street_connection(Vertex* intersection1, Vertex* intersection2)
{
return (
(intersection1 == this->intersection1 && intersection2 == this->intersection2) ||
(intersection1 == this->intersection2 && intersection2 == this->intersection1));
}
public:
Vertex* intersection1;
Vertex* intersection2;
int distance;
};
void pathFinder(Vertex* startVertex)
{
DFS_visit(startVertex);
}
void DFS_visit(Vertex* u)
{
u->color = "gray"; // Mark that we have visited intersection 'u'
// Create a vector containing all adjacent vertices to intersection 'u'
vector<Vertex*>* adjVertex = AdjVertices(u);
const int size = adjVertex->size();
for( int i=0; i<size; ++i)
{
Vertex* v = adjVertex->at(i);
if ( v->color == "white" )
{
DFS_visit(v); // recursive function call
}
}
// Once all adjacent vertices have been located, we are done with this node
u->color = "black";
}
vector <Vertex*>* AdjVertices(Vertex* vert)
{
// Creates a vector containing all of the adjacent vertices
// to the intersection in question (vert)
vector<Vertex*>* adjVertex = new vector <Vertex*> ();
const int size = edges.size();
for(int i=0; i<size; ++i)
{
Edge* edge = edges.at(i);
Vertex* adjacent = NULL;
if (edge->intersection1 == vert) // if edge's start vertex is the vertex in question
{
adjacent = edge->intersection2;
}
else if (edge->intersection2 == vert) // if edge's end vertex is the vertex in question
{
adjacent = edge->intersection1;
}
if (adjacent && vertices_check(vertices, adjacent))
{
adjVertex->push_back(adjacent);
}
}
return adjVertex;
}

You could use a Vector (constructed in your other function calling DFS_visit) and pass it on to DFS_visit. In DFS_visit, you add the node at the start and then each time you would return from an investigated child. That should give you a complete path description.
void DFS_visit(Vertex* u, Vector<Vertex*> path )
{
u->color = "gray"; // Mark that we have visited intersection 'u'
path.push_back(u);
// Create a vector containing all adjacent vertices to intersection 'u'
vector<Vertex*>* adjVertex = AdjVertices(u);
const int size = adjVertex->size();
for( int i=0; i<size; ++i)
{
Vertex* v = adjVertex->at(i);
if ( v->color == "white" )
{
DFS_visit(v,path); // recursive function call
path.push_back(u);
}
}
// Once all adjacent vertices have been located, we are done with this node
u->color = "black";
}

Related

How to fix binary operators errors?

I have to write code that represent the graph using an adjacency list. I tried setting up my code to use a std::list but now that gives me errors saying
Error C2679 binary '=': no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion) on multiple lines of my code. I'm confused on how I get my code to use an adjacency list without having all these issues.
#include "GraphInterface.h"
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
#include<list>
#ifndef GRAPH_TWO
#define GRAPH_TWO
template<class LabelType>
class GraphTwo : public GraphInterface<LabelType>
{
private:
// Define maximum number of nodes
static const int size = 10;
std::list <int> adj[size][size];
std::list<bool>visited[size];
public:
GraphTwo();
// Get the number of vertices
int getNumVertices() const;
// Get the number of the edges
int getNumEdges() const;
// Creates an undirected edge in this graph between two vertices
// that have the given labels.If such vertices do not exist, creates
// themand adds them to the graph before creating the edge
bool add(LabelType start, LabelType end, int edgeWeight);
// Removes an edge from this graph. If a vertex has no other edges,
// it is removed from the graph since this is a connected graph.
bool remove(LabelType start, LabelType end);
// Gets the weight of an edge in this graph.
int getEdgeWeight(LabelType start, LabelType end) const;
// Performs a depth - first search of this graph beginning at the given
// vertex and calls a given function once for each vertex visited.
void depthFirstTraversal(LabelType start, void visit(LabelType&));
// Performs a breadth - first search of this graph beginning at the given
// vertex and calls a given function once for each vertex visited.
void breadthFirstTraversal(LabelType start, void visit(LabelType&));
};
template<class LabelType>
GraphTwo<LabelType>::GraphTwo()
{}
template<class LabelType>
int GraphTwo<LabelType>::getNumVertices() const
{
return size;
}
template<class LabelType>
int GraphTwo<LabelType>::getNumEdges() const
{
int edgeCount = 0;
for (int i = 0; i < size; ++i)
for (int j = 0; j < size; ++j)
if (adj[i][j] != 0)
++edgeCount;
return edgeCount / 2;
}
template<class LabelType>
bool GraphTwo<LabelType>::add(LabelType start, LabelType end, int edgeWeight)
{
adj[start][end] = edgeWeight; //error here
adj[end][start] = edgeWeight; //error here
return true;
}
template<class LabelType>
bool GraphTwo<LabelType>::remove(LabelType start, LabelType end)
{
adj[start][end] = 0; // error here
adj[end][start] = 0; // error here
return true;
}
template<class LabelType>
int GraphTwo<LabelType>::getEdgeWeight(LabelType start, LabelType end) const
{
return adj[start][end];
}
template<class LabelType>
void GraphTwo<LabelType>::depthFirstTraversal(LabelType start, void visit(LabelType&))
{
// Visit the current node
visit(start);
// Mark the current node as visited
visited[start] = true;
// For all other nodes
for (int i = 0; i < size; ++i) {
if (adj[start][i] != 0 && (!visited[i]))
depthFirstTraversal(i, visit);
}
}
template<class LabelType>
void GraphTwo<LabelType>::breadthFirstTraversal(LabelType start, void visit(LabelType&))
{
// Vector that contains the adjacent nodes
std::vector<LabelType> alist;
alist.push_back(start);
// Mark current node as visited
visited[start] = true; // error here
int check;
while (!alist.empty()) {
check = alist[0];
// Print node
visit(check);
alist.erase(alist.begin());
// Every vertex adjacent
for (int i = 0; i < size; ++i) {
if (adj[check][i] != 0 && (!visited[i])) {
// Add node to the queue
alist.push_back(i);
// Mark next node as visited
visited[i] = true; // error here
}
}
}
// Reset visited as all false
for (int i = 0; i < size; ++i)
visited[i] = false; // error here
}
#endif
std::list <int> adj[size][size];
This is not what you think it is. adj is an array of size arrays of size lists.
This makes adj[start][end] have type std::list<int>. The same applies to all your lists. Go find a good documentation on how to use std::list and don't try to guess the C++ syntax, learn it.

free(): invalid pointer error on vector.push_back()

My code gives me free(): invalid pointer error (I don't call free, so my understanding is that it has something to do with how vectors operate internally). I am beginner to C++, so though I checked other answers to similar questions, I fail to see what exactly causes the issue.
I have a grid graph (i.e. vertex is connected with its 4-neighbors). Some vertices hold a special value, which is written done in a file in a form:
row columns value
The code:
graph::graph(const char *file_name) {
ifstream infile(file_name);
istringstream iss;
int R = 2; // number of rows
int C = 4; // number of columns
for (int i=0; i<R*C; i++) add_vertex(i+1);
adj = new std::vector<edge*>[R*C]; // adjacency list
// add all edges to the grid
for (int r=0; r<R; r++) {
for (int c=0; c<C; c++) {
if (c!=C-1) add_edge(vertices[r*C+c], vertices[r*C+(c+1)]);
if (r!=R-1) add_edge(vertices[r*C+c], vertices[(r+1)*C+c]);
}
}
int P = 2; // number of vertices holding a special value
for (int i=0; i<P; i++) {
getline(infile, line);
iss.str(line);
iss >> r >> c >> p;
vertices[r*C+c]->set_value(p);
p_vertices.push_back(vertices[r*C+c]);
iss.clear();
}
void graph::add_vertex(int v) {
auto *vert = new vertex(v);
vertices.push_back(vert);
}
void graph::add_edge(vertex *v, vertex *u) {
edge e = std::make_tuple(v, u, 1);
adj[v->get_id()].push_back(&e);
adj[u->get_id()].push_back(&e);
}
Header:
#include "vertex.h"
typedef std::tuple<vertex*, vertex*, int> edge;
class graph {
private:
std::vector<vertex*> vertices; // all vertices
std::vector<vertex*> p_vertices; // vertices with a special value
std::vector<edge*> *adj; // adjacency list
public:
explicit graph(const char *file_name);
void add_vertex(int v);
void add_edge(vertex *v, vertex *u);
};
Header for a vertex:
#include <string>
#include <vector>
class vertex {
private:
int id;
int val;
public:
explicit vertex(int id) {
this->id = id;
this->val = 0;
};
int get_id() { return id; };
void set_value(int p) { val = p; };
};
Example input:
0 0 1
1 2 3
The error disappears if I comment out this line:
p_vertices.push_back(vertices[r*C+c]);
And remains even if I try to change p_vertices to std::vector<int> instead of std::vector<vertex*> (and use p_vertices.push_back(r*C+c)).
Thanks for any hints on how to fix the error.

Invalid operands to binary expression (‘const Vector’ and ‘const Vector’)

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].

Why doesn't this polygon clipping code give desired result?

This is my implementation of Sutherland-Hodgman Polygon Clipping Algorithm.
I am trying to clip a Positively Oriented and Convex polygon with a rectangular clipping area.
I am using BGI library from colorado university. I am using OS=Win7. Visual C++ 2008 Express.
This program isn't working correctly.
//Sutherland-Holdgman Line Clipping
#include "Line2d.h"
#include "Rectangle2d.h"
#include "Coordinates2d.h"
#include "Bits.h"
#include "Polygon2d.h"
#include <list>
typedef enum PointPosition
{
Left, Right
} PointPosition;
typedef enum LinePosition
{
CompletelyOut, CompletelyIn, ClippingCandidate, ClippingCandidateExtended
} LinePosition;
class ClippingPolygon2d
{
private:
Rectangle2d rectangle;
Polygon2d polygon;
public:
ClippingPolygon2d(){}
//ClippingPolygon2d(Rectangle2d & rectangle, Polygon2d & polygon): rectangle(rectangle), polygon(polygon){}
void SetCandidatePolygon(Polygon2d & pol)
{
polygon = pol;
}
void SetClippingPolygon(Rectangle2d & rect)
{
rectangle = rect;
}
public:
std::vector<Point2d> GetClippedPoints()
{
std::vector<Point2d> vertexList = polygon.GetVertices();
std::vector<Point2d> clipping = rectangle.GetVertices();
for (size_t i = 0; i < clipping.size(); i++)
{
//obtaining one vertex and the next one from the clipping region.
//Then, constructing a line from them.
Line2d clippingEdge(clipping[i], clipping[(i + 1) % clipping.size()]);
std::vector<Point2d> temp;
for (size_t j = 0; j < vertexList.size(); j++)
{
Point2d polygonEdgeStart = vertexList[j];
Point2d polygonEdgeEnd = vertexList[(j + 1) % vertexList.size()];
if (clippingEdge.onLeft(polygonEdgeStart))
{
if (clippingEdge.onLeft(polygonEdgeEnd))
{
// point on the left, just add to vertexList
temp.push_back(polygonEdgeEnd);
}
else //Right
{
// calculate intersection I and add it to vertexList
temp.push_back(clippingEdge.GetIntersection(Line2d(polygonEdgeStart, polygonEdgeEnd)));
}
}
else //Right
{
if (clippingEdge.onLeft(polygonEdgeEnd))
{
//calculate intersection I and add I and polygonEdgeEnd to vertexList
temp.push_back(clippingEdge.GetIntersection(Line2d(polygonEdgeStart, polygonEdgeEnd)));
temp.push_back(polygonEdgeEnd);
}
else //Right
{
// nothing to do: outside of the window
}
}
}
vertexList = temp;
}
return vertexList;
}
};
int main()
{
//////////////////////// Initialize ///////////////////////
Coordinates2d::ShowWindow("Sutherland-Hodgeman Line Clipping");
///////////////////////////////////////////////////////////////
Rectangle2d rectangle(Point2d(20, 20), Point2d(200, 140));
Polygon2d polygon;
polygon.Add(Point2d(30, 40));
polygon.Add(Point2d(110,40));
polygon.Add(Point2d(130,110));
polygon.Add(Point2d(70,150));
polygon.Add(Point2d(10,110));
ClippingPolygon2d clip;
clip.SetClippingPolygon(rectangle);
clip.SetCandidatePolygon(polygon);
std::vector<Point2d> clippedVerticesList = clip.GetClippedPoints();
Coordinates2d::Draw(polygon, Red);
Coordinates2d::Draw(rectangle, Magenta);
Coordinates2d::Draw(clippedVerticesList, Thick, Yellow);
//////////////////////// Draw /////////////////////////
Coordinates2d::Wait(); return 0;
///////////////////////////////////////////////////////////////
}
double Line2d :: orientationOf(Point2d & point)
{
return (end.x - start.x) * (point.y - start.y) - (end.y - start.y) * (point.x - start.x);
}
bool Line2d :: onRight(Point2d & point)
{
return orientationOf(point) < -E; //for precision reason
}
bool Line2d :: onLeft(Point2d & point)
{
return orientationOf(point) > E;//for precision reason
}
I found at least 2 problems in GetClippedPoints function:
you use if(i) - it's not right because i iterates on windows edges. I think that you suppose to use if(j).
supposed that for(size_t i=0 ; i<clippingRegionLines.size() ; i++) should transform (generate new) vertexList (initially vertexList==allPolygonVertexes) and use it in next step. (so after all iterations of this loop you will get clipped polygon). So my advice here: represent input polygon as list of vertexes instead of list of edges.
Also you need to be sure that std::vector<Line2d> clippingRegionLines = rectangle.GetLines(); returns segments oriented counter-clockwise.

how to convert this code from Dijkstra to Astar?

So I have a project of which I want to switch to Astar due to speed reasons.
But C++ is not my strongest point. Could anyone help me (or tell me how to do the..) converting the algorythm from Dijkstra to Astar?
I found this Astar implementation:
http://code.google.com/p/a-star-algorithm-implementation/
But I don't know how to use it with my existing code.
Here is the graph file which got the algorithm:
#include "Graph.h"
#include <iostream>
#include <algorithm>
#include <stack>
Graph::Graph(void)
{
}
Graph::~Graph(void)
{
while(!mNodes.empty())
{
delete mNodes.back();
mNodes.pop_back();
}
}
void Graph::addNode(int name, bool exists, Node** NodeID )
{
Node* pStart = NULL;
mNodes.push_back(new Node(name,exists));
std::vector<Node*>::iterator itr;
itr = mNodes.begin()+mNodes.size()-1;
pStart = (*itr);
if(exists == true)pStart->DoesExist_yes();
*NodeID = pStart;
}
void Graph::connect_oneway(Node* pFirst, Node* pSecond, int moveCost)
{
if(pFirst != NULL && pSecond != NULL)
{
pFirst->createEdge(pSecond, moveCost);
}
}
#define MAX_NODES (32768)
#define MAX_CONNECTIONS (5)
#include <time.h>
int * Graph::findPath_r(Node* pStart, Node* pEnd)
{
int *arr = new int[MAX_NODES+2];
for (int i=0; i<MAX_NODES; i++)
arr[i] = -1;
arr[0] = 0;
if(pStart == pEnd)
{
return arr;
}
std::vector<Node*> openList;
openList.push_back(pStart);
Node* pCurrNode = NULL;
while(!openList.empty())
{
//Get best node from open list (lowest F value).
//Since we sort the list at the end of the previous loop we know
//the front node is the best
pCurrNode = openList.front();
//Exit if we're are the goal
if(pCurrNode == pEnd)
break;
//Remove the node from the open list and place it in the closed
openList.erase(openList.begin());
pCurrNode->setClosed(true); //We use a flag instead of a list for speed
//Test all of the edge nodes from the current node
std::vector<Edge*>* pEdges = pCurrNode->getEdges();
Node* pEdgeNode = NULL;
for(std::vector<Edge*>::iterator i = pEdges->begin(); i != pEdges->end(); ++i)
{
pEdgeNode = (*i)->pNode;
//If it's closed we've already analysed it
if(!pEdgeNode->getClosed() && pCurrNode->DoesExist() == true)
{
if(!inList(pEdgeNode,&openList))
{
openList.push_back(pEdgeNode);
pEdgeNode->setGCost(pCurrNode->getGCost()+(*i)->moveCost);
pEdgeNode->calcFCost();
pEdgeNode->setParent(pCurrNode);
}
else
{
//If this is a better node (lower G cost)
if(pEdgeNode->getGCost() > pCurrNode->getGCost()+(*i)->moveCost)
{
pEdgeNode->setGCost(pCurrNode->getGCost()+(*i)->moveCost);
pEdgeNode->calcFCost();
pEdgeNode->setParent(pCurrNode);
}
}
}
}
//Place the lowest F cost item in the open list at the top, so we can
//access it easily next iteration
std::sort(openList.begin(), openList.end(), Graph::compareNodes);
}
//Make sure we actually found a path
if(pEnd->getParent() != NULL)
{
//Output the path
//Use a stack because it is LIFO
std::stack<Node*> path;
while(pCurrNode != NULL)
{
path.push(pCurrNode);
pCurrNode = pCurrNode->getParent();
}
int counter = 0;
arr[1] = 0;
while(!path.empty())
{
arr[counter+2] = path.top()->getName();
counter++;
arr[1] += path.top()->getGCost();
path.pop();
}
arr[0] = counter;
return arr;
}
return arr;
}
bool Graph::inList(Node* pNode, std::vector<Node*>* pList)
{
for(std::vector<Node*>::iterator i = pList->begin(); i != pList->end(); ++i)
{
if((*i) == pNode)
{
return true;
}
}
return false;
}
bool Graph::compareNodes(Node* pFirst, Node* pSecond)
{
return pFirst->getFCost() < pSecond->getFCost();
}
void Graph::reset(void)
{
for(std::vector<Node*>::iterator i = mNodes.begin(); i != mNodes.end(); ++i)
{
(*i)->reset();
}
}
The function for finding the path is this one:
Graph::findPath_r
What I really want to do is preserve the edges (because they decide if the road is both or one-way).
Here are the other files:
Graph.h
#ifndef _GRAPH_H_
#define _GRAPH_H
#include "Node.h"
class Graph
{
public:
Graph(void);
~Graph(void);
//void addNode(int name, bool exists);
void addNode(int name, bool exists, Node** NodeID );
void connect_oneway(int ppFirst, int ppSecond, int moveCost);
void connect_oneway(Node* pFirst, Node* pSecond, int moveCost);
//int * findPath_r(int start, int end);
int * findPath_r(Node* pStart, Node* pEnd);
void reset(void);
private:
void findNodesx(int firstName, Node** ppFirstNode);
bool inList(Node* pNode, std::vector<Node*>* pList);
static bool compareNodes(Node* pFirst, Node* pSecond);
std::vector<Node*> mNodes;
};
#endif
Node.h
#ifndef _NODE_H_
#define _NODE_H_
#include <string>
#include <vector>
//Forward declare Node so Edge can see it
class Node;
struct Edge
{
Edge(Node* node, int cost) : pNode(node), moveCost(cost){}
Node* pNode;
int moveCost;
};
class Node
{
public:
Node(void);
Node(int name, bool exists);
~Node(void);
void createEdge(Node* pTarget, int moveCost);
void setGCost(int cost);
void setClosed(bool closed);
void setParent(Node* pParent);
int getGCost(void);
int getFCost(void);
bool getClosed(void);
Node* getParent(void);
int getName(void);
bool DoesExist(void);
bool DoesExist_yes(void);
std::vector<Edge*>* getEdges(void);
void calcFCost(void);
void reset(void);
private:
int mGCost;
int mTotal;
bool mClosed;
Node* mpParent;
int mName;
bool mHeur;
std::vector<Edge*> mEdges;
};
#endif
Node.cpp
#include "Node.h"
Node::Node(void)
{
}
Node::Node(/*const std::string&*/int name, bool exists) : mGCost(0), mTotal(0), mClosed(false), mpParent(NULL), mName(name), mHeur(exists)
{
}
Node::~Node(void)
{
while(!mEdges.empty())
{
delete mEdges.back();
mEdges.pop_back();
}
}
int Node::getName(void)
{
return mName;
}
void Node::createEdge(Node* pTarget, int moveCost)
{
mEdges.push_back(new Edge(pTarget, moveCost));
}
void Node::setClosed(bool closed)
{
mClosed = closed;
}
bool Node::getClosed(void)
{
return mClosed;
}
std::vector<Edge*>* Node::getEdges(void)
{
return &mEdges;
}
int Node::getGCost(void)
{
return mGCost;
}
void Node::setGCost(int cost)
{
mGCost = cost;
}
void Node::calcFCost(void)
{
mTotal = mGCost;
}
void Node::setParent(Node* pParent)
{
mpParent = pParent;
}
int Node::getFCost(void)
{
return mTotal;
}
bool Node::DoesExist(void)
{
return mHeur;
}
bool Node::DoesExist_yes(void)
{
mHeur = true;
return true;
}
Node* Node::getParent(void)
{
return mpParent;
}
void Node::reset(void)
{
mGCost = 0;
mTotal = 0;
mClosed = false;
mpParent = NULL;
}
You mentioned a library on GoogleCode. It is node clear what you want to do with, and I think the best is to write your implementation yourself.
First, you should know that Dijsktra is a special case of A*. In A*, you have an heuristic, named h; A* = possible implementation of Dijsktra when h is the null function.
Then, about your implementation, let's start with Node. It will need the following functions:
constructor, destructor
create/get edge
set/get parent
set/is closed (for speed)
set/get GCost
set/get FCost
set/is obstacle (name way more descriptive than 'DoesExist')
set/get position
reset
// optional method:
get name
Hopefully, this part of your code won't change a lot. The heuristic code will be placed in the pathfinder. The Edge class is left untouched.
Now the big one: Graph. You won't need to delete any of your public methods.
You will need a heuristic method. For the implementation which will be described, you will need an admissible consistent heuristic:
it must not over-estimate the distance to the goal (admissible)
it must be monotone (consistent)
The general case signature is int getHCost(Node* node);. If you always return 0, you will have a Dijsktra algorithm, which is not what you want. Here we will take the euclidiean distance between the node and the goal. Slower to compute than manhattan distance, but better results. You can change this afterwards.
int getHCost(Node* node, Note* goal);
This implies you must place your nodes in the 3d space. Note that the heuristic is a heuristic, ie, an estimation of the distance.
I won't write the code. I will write some pseudo-code adapted to your situation. The original pseudocode is located on the Wikipedia A* page. This pseudo-code is your findPath_r function:
function A*(start,goal)
set all nodes to not closed // The set of nodes already evaluated.
openset = {start} // The set of tentative nodes to be evaluated, initially containing the start node
start.gcost = 0 // Cost from start along best known path.
// Estimated total cost from start to goal through y.
start.fcost = start.gcost + getHCost(start, goal)
while openset is not empty
current = the node in openset having the lowest f_cost (usually the first if you use a sorted list)
if current == goal
return construct_path(goal)
remove current from openset
current.closed = true
for each neighbor in (node connected by edge in current.edges) // Here is the condition for one-way edges
if neighbor.closed or neighbor.obstacle
continue
gcost = current.gcost + dist_between(current,neighbor) // via edge distance
if neighbor not in openset
add neighbor to openset
neighbor.parent = current
neighbor.gcost = gcost
neighbor.fcost = neighbor.gcost + getHCost(neighbor, goal)
else if gcost < neighbor.gcost
neighbor.parent = current
neighbor.gcost = gcost
neighbor.fcost = neighbor.gcost + getHCost(neighbor, goal)
update neighbor position in openset
return failure
function construct_path(current_node)
std::vector<Node*> path
while current_node != 0
path.push_front(current_node)
current_node = current_node.parent
return path
The implementation above use one-way edges.
You were able to write Dijsktra algorithm in C++, so writing this pseudocode in C++ shouldn't be a problem.
Second part, performances. First, measure ;).
I have some hints that can improve performances:
use a memory pool for allocation deallocation
use an intrusive list for the open list (you can also make it auto-sorted with this technique)
I advise you to read A* for beginners, which is a useful reading, even if you don't use tilemap.