how to pick two points from viewer in PCL - point-cloud-library

I would like to pick two points from pointcloud and return coordinates of the two points. In order to get down to the problem, I have used the PointPickingEvent of PCL, and written a class containing pointcloud, visualizer, and a vector to store selected points. My code:
#include <pcl/point_cloud.h>
#include <pcl/PCLPointCloud2.h>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/common/io.h>
#include <pcl/io/ply_io.h>
#include <pcl/io/vtk_lib_io.h>
#include <pcl/visualization/pcl_visualizer.h>
using namespace pcl;
using namespace std;
class pickPoints {
public:
pickPoints::pickPoints () {
viewer.reset (new pcl::visualization::PCLVisualizer ("Viewer", true));
viewer->registerPointPickingCallback (&pickPoints::pickCallback, *this);
}
~pickPoints () {}
void setInputCloud (PointCloud<PointXYZ>::Ptr cloud)
{
cloudTemp = cloud;
}
vector<float> getpoints() {
return p;
}
void simpleViewer ()
{
// Visualizer
viewer->addPointCloud<pcl::PointXYZ>(cloudTemp, "Cloud");
viewer->resetCameraViewpoint ("Cloud");
viewer->spin();
}
protected:
void pickCallback (const pcl::visualization::PointPickingEvent& event, void*)
{
if (event.getPointIndex () == -1)
return;
PointXYZ picked_point1,picked_point2;
event.getPoints(picked_point1.x,picked_point1.y,picked_point1.z,
picked_point2.x,picked_point2.y,picked_point2.z);
p.push_back(picked_point1.x); // store points
p.push_back(picked_point1.y);
p.push_back(picked_point1.z);
p.push_back(picked_point2.x);
p.push_back(picked_point2.y);
p.push_back(picked_point2.z);
//cout<<"first selected point: "<<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;
//cout<<"second selected point: "<<p[3]<<" "<<p[4]<<" "<<p[5]<<endl;
}
private:
// Point cloud data
PointCloud<pcl::PointXYZ>::Ptr cloudTemp;
// The visualizer
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
// The picked point
vector<float> p;
};
int main()
{
//LOAD;
PointCloud<PointXYZ>::Ptr cloud (new PointCloud<PointXYZ> ());
pcl::PolygonMesh mesh;
pcl::io::loadPolygonFilePLY("test.ply", mesh);
pcl::fromPCLPointCloud2(mesh.cloud, *cloud);
pickPoints pickViewer;
pickViewer.setInputCloud(cloud); // A pointer to a cloud
pickViewer.simpleViewer();
vector<float> pointSelected;
pointSelected= pickViewer.getpoints();
cout<<pointSelected[0]<<" "<<pointSelected[1]<<" "<<pointSelected[2]<<endl;
cout<<pointSelected[3]<<" "<<pointSelected[4]<<" "<<pointSelected[5]<<endl;
cin.get();
return 0;
}
But when the code was debugged, I got nothing. Also I know that when picking points with the left button, the SHIFT button should be pressed. Thank you in advance for any help!

I found that the getPoints() method does not work as I expected. However, getPoint() worked well. Here is code to print out the selected points and store them is a vector:
std::vector<pcl::PointXYZ> selectedPoints;
void pointPickingEventOccurred(const pcl::visualization::PointPickingEvent& event, void* viewer_void)
{
float x, y, z;
if (event.getPointIndex() == -1)
{
return;
}
event.getPoint(x, y, z);
std::cout << "Point coordinate ( " << x << ", " << y << ", " << z << ")" << std::endl;
selectedPoints.push_back(pcl::PointXYZ(x, y, z));
}
void displayCloud(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud, const std::string& window_name)
{
if (cloud->size() < 1)
{
std::cout << window_name << " display failure. Cloud contains no points\n";
return;
}
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer(window_name));
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI> point_cloud_color_handler(cloud, "intensity");
viewer->addPointCloud< pcl::PointXYZI >(cloud, point_cloud_color_handler, "id");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "id");
viewer->registerKeyboardCallback(keyboardEventOccurred, (void*)viewer.get());
viewer->registerPointPickingCallback(pointPickingEventOccurred, (void*)&viewer);
while (!viewer->wasStopped() && !close_window){
viewer->spinOnce(50);
}
close_window = false;
viewer->close();
}
You can also find distances between the points pretty easily once they are selected.
if (selectedPoints.size() > 1)
{
float distance = pcl::euclideanDistance(selectedPoints[0], selectedPoints[1]);
std::cout << "Distance is " << distance << std::endl;
}
The selectedPoints vector can be emptied with a keyboardEvent if you want to start over picking points.

Related

How to use Intel realsense camera's (ZR300) with pre-made video or image instead live capture

I want to use pre-made files instead of live capture in the following program to track the person.
what is realsense SDK API used to load pre-made files and catch the frame by frame?
Is it possible to use to detect/track person any general video/image files which captured using any other camera's ?
Example Program:
Example Source Link
Source
#include <thread>
#include <iostream>
#include <signal.h>
#include "version.h"
#include "pt_utils.hpp"
#include "pt_console_display.hpp"
#include "pt_web_display.hpp"
#include "or_console_display.hpp"
#include "or_web_display.hpp"
using namespace std;
using namespace rs::core;
using namespace rs::object_recognition;
// Version number of the samples
extern constexpr auto rs_sample_version = concat("VERSION: ",RS_SAMPLE_VERSION_STR);
// Doing the OR processing for a frame can take longer than the frame interval, so we
// keep track of whether or not we are still processing the last frame.
bool is_or_processing_frame = false;
unique_ptr<web_display::pt_web_display> pt_web_view;
unique_ptr<web_display::or_web_display> or_web_view;
unique_ptr<console_display::pt_console_display> pt_console_view;
unique_ptr<console_display::or_console_display> or_console_view;
void processing_OR(correlated_sample_set or_sample_set, or_video_module_impl* impl, or_data_interface* or_data,
or_configuration_interface* or_configuration)
{
rs::core::status st;
// Declare data structure and size for results
rs::object_recognition::localization_data* localization_data = nullptr;
//Run object localization processing
st = impl->process_sample_set(or_sample_set);
if (st != rs::core::status_no_error)
{
is_or_processing_frame = false;
return;
}
// Retrieve recognition data from the or_data object
int array_size = 0;
st = or_data->query_localization_result(&localization_data, array_size);
if (st != rs::core::status_no_error)
{
is_or_processing_frame = false;
return;
}
//Send OR data to ui
if (localization_data && array_size != 0)
{
or_console_view->on_object_localization_data(localization_data, array_size, or_configuration);
or_web_view->on_object_localization_data(localization_data, array_size, or_configuration);
}
is_or_processing_frame = false;
}
int main(int argc,char* argv[])
{
rs::core::status st;
pt_utils pt_utils;
rs::core::image_info colorInfo,depthInfo;
rs::core::video_module_interface::actual_module_config actualModuleConfig;
rs::person_tracking::person_tracking_video_module_interface* ptModule = nullptr;
rs::object_recognition::or_video_module_impl impl;
rs::object_recognition::or_data_interface* or_data = nullptr;
rs::object_recognition::or_configuration_interface* or_configuration = nullptr;
cout << endl << "Initializing Camera, Object Recognition and Person Tracking modules" << endl;
if(pt_utils.init_camera(colorInfo,depthInfo,actualModuleConfig,impl,&or_data,&or_configuration) != rs::core::status_no_error)
{
cerr << "Error: Device is null." << endl << "Please connect a RealSense device and restart the application" << endl;
return -1;
}
pt_utils.init_person_tracking(&ptModule);
//Person Tracking Configuration. Set tracking mode to 0
ptModule->QueryConfiguration()->QueryTracking()->Enable();
ptModule->QueryConfiguration()->QueryTracking()->SetTrackingMode((Intel::RealSense::PersonTracking::PersonTrackingConfiguration::TrackingConfiguration::TrackingMode)0);
if(ptModule->set_module_config(actualModuleConfig) != rs::core::status_no_error)
{
cerr<<"error : failed to set the enabled module configuration" << endl;
return -1;
}
//Object Recognition Configuration
//Set mode to localization
or_configuration->set_recognition_mode(rs::object_recognition::recognition_mode::LOCALIZATION);
//Set the localization mechnizm to use CNN
or_configuration->set_localization_mechanism(rs::object_recognition::localization_mechanism::CNN);
//Ignore all objects under 0.7 probabilty (confidence)
or_configuration->set_recognition_confidence(0.7);
//Enabling object center feature
or_configuration->enable_object_center_estimation(true);
st = or_configuration->apply_changes();
if (st != rs::core::status_no_error)
return st;
//Launch GUI
string sample_name = argv[0];
// Create console view
pt_console_view = move(console_display::make_console_pt_display());
or_console_view = move(console_display::make_console_or_display());
// Create and start remote(Web) view
or_web_view = move(web_display::make_or_web_display(sample_name, 8000, true));
pt_web_view = move(web_display::make_pt_web_display(sample_name, 8000, true));
cout << endl << "-------- Press Esc key to exit --------" << endl << endl;
while (!pt_utils.user_request_exit())
{
//Get next frame
rs::core::correlated_sample_set* sample_set = pt_utils.get_sample_set(colorInfo,depthInfo);
rs::core::correlated_sample_set* sample_set_pt = pt_utils.get_sample_set(colorInfo,depthInfo);
//Increment reference count of images at sample set
for (int i = 0; i < static_cast<uint8_t>(rs::core::stream_type::max); ++i)
{
if (sample_set_pt->images[i] != nullptr)
{
sample_set_pt->images[i]->add_ref();
}
}
//Draw Color frames
auto colorImage = (*sample_set)[rs::core::stream_type::color];
pt_web_view->on_rgb_frame(10, colorImage->query_info().width, colorImage->query_info().height, colorImage->query_data());
//Run OR in a separate thread. Update GUI with the result
if (!is_or_processing_frame) // If we aren't already processing or for a frame:
{
is_or_processing_frame = true;
std::thread recognition_thread(processing_OR, *sample_set,
&impl, or_data, or_configuration);
recognition_thread.detach();
}
//Run Person Tracking
if (ptModule->process_sample_set(*sample_set_pt) != rs::core::status_no_error)
{
cerr << "error : failed to process sample" << endl;
continue;
}
//Update GUI with PT result
pt_console_view->on_person_info_update(ptModule);
pt_web_view->on_PT_tracking_update(ptModule);
}
pt_utils.stop_camera();
actualModuleConfig.projection->release();
return 0;
}
After installing the Realsense SKD, check the realsense_playback_device_sample for how to load the RSSDK capture file.
The short answer is not really. Beside the images that are captured from the other camera, you also need to supply the camera intrinsic and extrinsic settings in order to calculate the depth of and object and call the person tracking module.

How to extract a set of points in a point cloud data using PCL?

I have a point cloud data, where by clicking a point, I want to extract points surrounding the clicked point within a radius. I want to also push the extracted points into a new cloud. Using Pointpickingevent, I am able to click one point and push it into the cloud. How do I extract a set of points, say points surrounding 0.02cm radius from the clicked point and push them into a new cloud?
Given a point cloud:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud
A Kdtree is then generated to perform an efficient range search:
pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
kdtree.setInputCloud (cloud);
Then, given a point and a radius:
pcl::PointXYZ searchPoint(1,2,3);
float radius = 4;
You can get all the points that are at a distance radius from the point searchPoint:
std::vector<int> pointIdxRadiusSearch; //to store index of surrounding points
std::vector<float> pointRadiusSquaredDistance; // to store distance to surrounding points
if ( kdtree.radiusSearch (searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0 )
{
for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
std::cout << " " << cloud->points[ pointIdxRadiusSearch[i] ].x
<< " " << cloud->points[ pointIdxRadiusSearch[i] ].y
<< " " << cloud->points[ pointIdxRadiusSearch[i] ].z
<< " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
}
You can print all the surrounding points and their distance to the searchPoint to check the code functional correctness.
Finally, create a cloud with the obtained points:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
cloud_cluster->points.push_back(cloud->points[ pointIdxRadiusSearch[i] ]);
cloud_cluster->width = cloud_cluster->points.size ();
cloud_cluster->height = 1;
cloud_cluster->is_dense = true;
In order to be able to pick a point you can use PointPickingEvent similarly to this answer.
The Class declaration in your .h,
class PCLViewer : public QMainWindow
{
Q_OBJECT
public:
explicit PCLViewer (QWidget *parent = 0);
~PCLViewer ();
void pointPickCallback (const pcl::visualization::PointPickingEvent& event, void*);
public slots:
protected:
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::PointXYZ src_point_;
bool src_point_selected_;
private:
Ui::PCLViewer *ui;
};
In your .cpp,
PCLViewer::PCLViewer (QWidget *parent) :
QMainWindow (parent),
ui (new Ui::PCLViewer)
{
ui->setupUi (this);
[...]
viewer.reset (new pcl::visualization::PCLVisualizer ("viewer", false));
viewer->registerPointPickingCallback (&PCLViewer::pointPickCallback, *this);
[...]
}
and the additional function,
void
PCLViewer::pointPickCallback (const pcl::visualization::PointPickingEvent& event, void*)
{
// Check to see if we got a valid point. Early exit.
int idx = event.getPointIndex ();
if (idx == -1)
return;
// Get the point that was picked
event.getPoint (src_point_.x, src_point_.y, src_point_.z);
PCL_INFO ("Src Window: Clicked point %d with X:%f Y:%f Z:%f\n", idx, src_point_.x, src_point_.y, src_point_.z);
src_point_selected_ = true;
}
There is a more detailed example of the utilisation of it in the manual registration app:
pcl/apps/src/manual_registration/manual_registration.cpp
pcl/apps/include/pcl/apps/manual_registration.h

program crashes with haarcascade_fullbody.xml

I am working with OpenCV for Qt.
I am working on doing a program which is able to detect several objects. So far I could make a face, eye and nose detector, but when I try to make a full body detection I get either totally wrong detections, no detections at all or the program crashes. For detecting the full body I just use the same code as for the other detections but with the haarcascade_fullbody.xml file. Is it not possible to use the same code? Why does it work for the other features and not for the full body?
I have also tried to implement a car detection using OpenCV's pretrained models from https://github.com/Itseez/opencv_extra/tree/master/testdata/cv/latentsvmdetector/models_VOC2007 but I get parsing errors.
Thanks in advance!
Code from MainWindow:
void MainWindow::on_btnFullBody_clicked()
{
WriteInLog("Full body detection requested");
QString xml = tr("%1/%2").arg(QApplication::applicationDirPath()).arg(FULL_BODY_FILE);
FeatureDetector detector(xml);
std::vector<QRect> rest;
float scaleFactor= 1.1f;
uint neighbours= 2;
bool ret = detector.DetectFeature(&mSelectedImage, rest, scaleFactor, neighbours);
if (!ret)
{
WriteInLog("No full body has been detected");
}
else
{
QVector<QRect> qRect = QVector<QRect>::fromStdVector(rest);
processedImage(qRect);
WriteInLog("Bodys detected: "+QString::number(qRect.size()));
}
}
Code from DetectFeature:
bool FeatureDetector::DetectFeature(QImage* image, std::vector<QRect> &returnList, float scaleFactor, uint neighbours)
{
returnList.clear();
bool ok = false;
qDebug() << "Starting...";
if (!image->isNull()) {
//Changing from QImage to matrix
QImage temp = image->copy();
cv::Mat res(temp.height(),temp.width(),CV_8UC3,(uchar*)temp.bits(),temp.bytesPerLine());
cv::Mat res_gray;
//Changing the image to grey scale an equalizing the result
cvtColor(res, res_gray,CV_BGR2GRAY);
cv::equalizeHist(res_gray,res_gray);
cv::CascadeClassifier detector;
std::vector< cv::Rect > featureVec;
bool retDetector=true; // detector.load("C:/Users/ansurbcn_2/Pictures/cara.jpg");
qDebug()<<mXmlFilePath;
if (!detector.load(mXmlFilePath.toLatin1().constData()))
{
qDebug() << "Error loading detector";
return false;
}
detector.detectMultiScale(res_gray, featureVec);
//detector.detectMultiScale(res_gray, featureVec, scaleFactor, neighbours, 18|9);
if (retDetector) {
qDebug() << "OK Detector";
}
else {
qDebug() << "Failed Detector";
}
for(size_t i=0; i<featureVec.size();i++)
{
cv::Rect oneFeature =featureVec[i];
QRect qrect(oneFeature.x, oneFeature.y, oneFeature.width, oneFeature.height);
returnList.push_back(qrect);
ok = true;
}
}
return ok;
}

error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Car' (or there is no acceptable conversion)

Queue class
#ifndef Queue_H
#define Queue_H
#include "Car.h"
#include <iostream>
#include <string>
using namespace std;
const int Q_MAX_SIZE = 20;
class Queue {
private:
int size; // size of the queue
Car carQueue[Q_MAX_SIZE];
int front, rear;
public:
Queue();
~Queue();
bool isEmpty();
bool isFull();
void enqueue(Car c);
void dequeue(); // just dequeue the last car in the queue
void dequeue(Car c); // if a certain car wants to go out of the queue midway.
// Condition: Car is not in washing. Meaning is not the 1st item in the queue
void dequeue(int index); // same as the previous comment
Car getFront();
void getCarQueue(Queue);
int length();
Car get(int);
};
Queue::Queue() {
size = 0;
front = 0;
rear = Q_MAX_SIZE -1;
}
Queue::~Queue() {
while(!isEmpty()) {
dequeue();
}
}
void Queue::enqueue(Car c) {
if (!isFull()) {
rear = (rear + 1) % Q_MAX_SIZE; // circular array
carQueue[rear] = c;
size++;
} else {
cout << "Queue is currently full.\n";
}
}
void Queue::dequeue() {
}
void Queue::dequeue(int index) {
if(!isEmpty()) {
front = (front + 1) % Q_MAX_SIZE;
if(front != index) {
carQueue[index-1] = carQueue[index];
rear--;
size--;
} else {
cout << "Not allowed to dequeue the first car in the queue.\n";
}
} else {
cout << "There are no cars to dequeue.\n";
}
}
bool Queue::isEmpty() {
return size == 0;
}
bool Queue::isFull() {
return (size == Q_MAX_SIZE);
}
Car Queue::getFront() {
return carQueue[front];
}
int Queue::length() {
return size;
}
Car Queue::get(int index) {
return carQueue[index-1];
}
void Queue::getCarQueue(Queue q) {
for(int i = 0; i< q.length(); i++)
cout << q.get(i) << endl; // Error here
}
#endif
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Car' (or there is no acceptable conversion)
I get this error which is kind of odd. so is there anything wrong? Thanks!
cout has no idea how to process a car object; it has never seen a car object and doesn't know how you output a car as text. cout can only process types it knows about, string, char, int, etc. The specific error is because there is version of operator << that takes an ostream and a car.
There are two options:
Creation an overload for operator<< that takes an ostream and a car. That will show cout how to output a car. This isn't usually done becuase there is usually more than one way your would want to display a car.
Write the output statement so that it manually prints out car properties like
cout << c.getMake() << " " << c.getModel()

Stack-recursion program problems

I am a novice C++ coder and obviously not very good at it. I am having an immense amount of trouble with this program.
I am getting syntax errors on my opening and closing parenthesis on my functions, syntax errors on my "<" in my header cpp file, and errors that I'm missing parenthesis.
My first stack is not recognized (main driver file) and in my StackType.cpp file - original is an "undeclared identifier".
Lastly, the left of Push must have class/struct/union - in my for loop when filling the first stack with the rings.
I apologize for all of these issues in advance. Any help you could give me would be greatly appreciated!
Thank you.
======================Stack Header================================
// File: StackType.h
// Stack template class definition.
// Dynamic array implementation
#ifndef StackType
#define StackType
template <class ItemType>
class StackType
{
private:
int ItemType;
ItemType *myStack; // pointer to dynamic array
int _top, _maxSize; // using underscores to remind that it's private
public:
StackType(int numRings = 50); // Constructor
StackType (const StackType<ItemType>&); // Copy Constructor
// Member Functions
void Push(ItemType); // Push
void Pop(ItemType &); // Pop
void stackTop(ItemType &) const; // retrieve top
bool stackIsEmpty() const; // Test for Empty stack
bool stackIsFull() const; // Test for Full stack
~StackType(); // Destructor
};
#endif
=====================Stack cpp file==================================
#include "StackType.h"
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
// Constructor with argument, size is numRings, limit is 50 (set in .h header)
template <class ItemType>
StackType<ItemType>::StackType()
{
_maxSize = numRings;
_top = -1;
}
// Copy Constructor
template <class ItemType>
StackType<ItemType>::StackType(const StackType<ItemType>& original :
_maxSize(original._maxSize), top(original._top)
{
myStack = new ItemType[_maxSize];
for (int i = 0; i <= top; i++) myStack[i] = original.myStack[i];
}
// Destructor
template <class ItemType>
StackType<ItemType>::~StackType()
{
delete [] myStack;
}
// Push
template <class ItemType>
void StackType<ItemType>::Push(StackType<ItemType> ringVal)
{
if(stackIsFull()) cout << "\t There is not enough available memory = the stack is
full!" << endl;
else myStack[++_top] = ringVal;
}
// Pop
template <class ItemType>
void StackType<ItemType>::Pop(StackType<ItemType> &ringVal)
{
if(stackIsEmpty()) cout << "\t The stack is empty!" << endl;
else ringVal = myStack[_top--];
}
// Retrieve stack top without removing it
template <class ItemType>
void StackType<ItemType>::stackTop(StackType<ItemType> &ringVal) const
{
if(stackIsEmpty()) cout << "The stack is empty!";
else ringVal = myStack[_top];
}
// Test for Empty stack
template <class ItemType>
bool StackType<ItemType>::stackIsEmpty() const
{
return (_top < 0);
}
// Test for Full stack
template <class ItemType>
bool StackType<class ItemType>::stackIsFull() const
{
return (_top >= (_maxSize - 1));
}
// end StackType.cpp
=========================Main Driver file=======================================
#include "StackType.h"
#ifdef _DEBUG
#include "StackType.cpp"
#endif // _DEBUG
#include <stack>
#include "StdAfx.h"
#include <iostream>
using namespace std;
// Global Variable - Counter to display the number of moves.
int count = 0;
class StackType;
// Functions Prototypes
void MoveRings(StackType<ItemType>&, StackType<ItemType>&);
// Function to move the rings
void Pegs(int D,StackType<ItemType>& b,StackType<ItemType>& e, StackType<ItemType>& h);
// This is a recursive function.
void Display (int, StackType <ItemType>& , StackType<ItemType>&, StackType<ItemType>&);
// Function to display the pegs
// Main - Driver File
int main()
{
// create 3 empty stacks
StackType<ItemType> FirstPeg; // Receiving an error that this is not identified
StackType<ItemType> EndPeg;
StackType<ItemType> HelperPeg;
// Number of rings.
int numRings;
cout << "\n\t *********** Rings to Pegs (Towers of Hanoi) ***********\n" << endl;
cout << "\t Please Enter the number of rings you want to play with: ";
// Input number of rings
cin >> numRings;
cout << endl;
while(numRings < 0 || isalpha(numRings)) // To make sure that the user did not
// enter an invalid number
{
cout << " Your entry is invalid. Please use only integers. Please re-
enter: ";
cin >> numRings;
cout << endl;
}
for(int i = 1; i <= numRings; i++)
// Fill the first peg with the number of rings.
{
FirstPeg.Push(i);
}
Pegs(int, StackType<ItemType>&, StackType<ItemType>&, StackType<ItemType>&);
// To call the recursive function that will move the rings
Display (int, StackType<ItemType>&, StackType<ItemType>&, StackType<ItemType>&);
// To call the display function
cin.clear();
cin.ignore('\n');
cin.get();
return 0;
}
// This function will move an ring from first peg to the second peg
void MoveRings(StackType<ItemType>& beg, StackType<ItemType>& theEnd) //End
{
int r; // disk will be removed from one stack and added to the other
beg.Pop(r);//pop from source
theEnd.Push(r);//and move to target
}
// This function displays the moves
void Display(int R, StackType<ItemType>& toBegin , StackType<ItemType>& toEnd,
StackType<ItemType>& toHelp)
{
StackType<int> B;// create temporarily first stack
StackType<int> E;// create temporarily End(End) stack
StackType<int> H;// create temporarily helper stack
for(int i = 1; i <= R; i++)
{
toBegin.Pop(i);//moves the ring from source
B.Push(i);//to the temporarily stack to display it
cout << "Beginning Peg:" << &B << endl;
toEnd.Pop(i);//moves the ring from source
E.Push(i);//to the temporarily stack to display it
cout << " End(Final) Peg: " << &E << endl;
toHelp.Pop(i);//moves the ring from source
H.Push(i);//to the temporarily stack to display it
cout << " Helper Peg:" << &H << endl;
}
}
//-------------------------------------------------------------------
void Pegs(int D,StackType<ItemType>& b,StackType<ItemType>& e,StackType<ItemType>& h)
// This is a recursive function.
{
if (D == 0) // The base
{
return 1;
}
else if(D == 1) // If there is only one ring, move this ring from the
// first peg to the end(final) peg
{
MoveRings(b, e); // moves the ring from the first to the end(final) peg
cout<<" Really? You have entered one ring..." << endl;
cout<<" It moves directly from the first peg to the End peg." << endl;
count++; // increment the number of moves
cout << "There has been " << count << " move. "<< endl;// display the
// number of moves
Display (D, b, e, h);
}
else if (D > 1) // a recursive function in order to move the rings
{
Pegs(D - 1, b, e, h); // to move N-1 rings from the first peg to the
// end(final) peg by using the helper peg
MoveRings(b, e);// to move the last ring to the end(final) peg
count++; // increment the number of steps before displaying
cout << "There has been " << count << " moves. "<< endl;
Pegs(D - 1, b, e, h);
// to move N-1 rings from the helper peg to the end(final) peg with the help of
// first peg
//Display ( D(rings), First Peg, End(Final) Peg, Helper Peg );
}
}
One problem that I can see immediately is that your header file defines StackType to prevent double inclusion, which is also used as a class name. After #define StackType, it ends up being a macro that expands to nothing, so your code looks like class { ... }.
You should use a symbol to prevent double inclusion that isn't used for anything else. The typical thing to use is STACKTYPE_H for a file called StackType.h.
Once you've fixed this, some other problems you're experiencing might go away. Please come back with an update if you're having more problems, and post the exact compiler errors if you do.

Resources