/******************************************************************************
Online C++ Compiler.
Code, Compile, Run and Debug C++ program online.
Write your code in this editor and press "Run" button to compile and execute it.
*******************************************************************************/
#include <iostream>
#include "Point2DSet.h"
using namespace std;
int main()
{
Point2DSet set;
set.add({"p00", -5,-6});
set.add({"p01", 6,-4});
set.add({"p02", 5.5,-3});
set.add({"p03", 8,0});
set.add({"p04", 5,0});
set.add({"p05", 4,2});
set.add({"p06", 1,3});
set.add({"p07", 0,2});
set.add({"p08", -1,1});
set.add({"p09", -1.5, 2});
set.add({"p10", -1.5,6});
set.add({"p11", -5.5, 1.5});
set.add({"p12", -8,-1});
Point2DSet destination;
set.buildConvexHull(destination);
std::cout << "Result: " << std::endl;
for (const auto& element : destination.fPoints) {
std::cout << element << std::endl;
}
return 0;
}
#include <iostream>
class Vector2D {
public:
Vector2D(double aX, double aY);
void setX(double aX);
double getX() const;
void setY(double aY);
double getY() const;
Vector2D operator+(const Vector2D& aRHS) const;
Vector2D operator-(const Vector2D& aRHS) const;
double magnitude() const;
double direction() const;
double dot(const Vector2D& aRHS) const;
double cross(const Vector2D& aRHS) const;
double angleBetween(const Vector2D& aRHS) const;
double fX;
double fY;
};
std::ostream& operator<<(std::ostream& aOutStream, const Vector2D& aObject);
std::istream& operator>>(std::istream& aInStream, Vector2D& aObject);
#include "Vector2D.h"
#include <cmath>
Vector2D::Vector2D(double aX, double aY): fX(aX), fY(aY){ }
void Vector2D::setX(double aX){ fX = aX;}
double Vector2D::getX() const { return fX; }
void Vector2D::setY(double aY) { fY = aY;}
double Vector2D::getY() const { return fY; }
Vector2D Vector2D::operator+(const Vector2D& aRHS) const
{
return {fX + aRHS.fX, fY + aRHS.fY};
}
Vector2D Vector2D::operator-(const Vector2D& aRHS) const
{
return {fX - aRHS.fX, fY - aRHS.fY};
}
double Vector2D::magnitude() const
{
return sqrt((fX * fX) + (fY * fY));
}
double Vector2D::direction() const
{
return atan2(fY, fX);
}
double Vector2D::dot(const Vector2D& aRHS) const
{
return (this->getX() * aRHS.getX()) + (this->getY() * aRHS.getY());
}
double Vector2D::cross(const Vector2D& aRHS) const
{
return (this->getX() * aRHS.getY()) - (aRHS.getX() * this->getY());
}
double Vector2D::angleBetween(const Vector2D& aRHS) const
{
double dntmr = magnitude() * aRHS.magnitude();
if (dntmr > 0.0)
{
return acos(this->dot(aRHS) / (this->magnitude() * aRHS.magnitude()));
}
return acos(1.0/1.0);
}
std::ostream& operator<<(std::ostream& aOutStream, const Vector2D& aObject)
{
aOutStream << " ( " << aObject.fX << ", " << aObject.fY << " )";
return aOutStream;
}
std::istream& operator>>(std::istream& aInStream, Vector2D& aObject)
{
aInStream >> aObject.fX;
aInStream >> aObject.fY;
return aInStream;
}
#include "Vector2D.h"
class Point2D {
public:
// Private function gets direction in reference to aOther
double directionTo(const Point2D& aOther) const ;
// Private Function to get magnitude in reference to aOther
double magnitudeTo(const Point2D& aOther) const ;
Point2D();
Point2D(const std::string& aId, double aX, double aY);
const std::string& getId() const;
void setX(const double& aX);
void setY(const double& aY);
const double getX() const;
const double getY() const;
void setOrigin(const Point2D& aPoint);
Vector2D operator-(const Point2D& aRHS) const;
// Return Direction with reference to origin
double direction() const;
// Return Direction with reference to origin
double magnitude() const;
bool isCollinear(const Point2D& aOther) const;
// Check to see if the point is Clockwise or not
bool isClockwise(const Point2D& aP0, const Point2D& aP2) const;
bool operator<(const Point2D& aRHS) const;
const Point2D& getOrigin() const;
std::string fId;
Vector2D fPosition;
const Point2D* fOrigin;
};
std::ostream& operator<<(std::ostream& aOStream, const Point2D& aObject);
std::istream& operator>>(std::istream& aIStream, Point2D& aObject);
#include "Point2D.h"
static const Point2D gCoordinateOrigin;
// Private function gets direction in reference to aOther
double Point2D::directionTo(const Point2D& aOther) const
{
return (aOther.fPosition - fPosition).direction();
}
// Private Function to get magnitude in reference to aOther
double Point2D::magnitudeTo(const Point2D& aOther) const
{
return (aOther.fPosition - fPosition).magnitude();
}
Point2D::Point2D() : fId(" "), fPosition(0,0), fOrigin(&gCoordinateOrigin) { }
Point2D::Point2D(const std::string& aId, double aX, double aY) : fId(aId), fPosition(aX,aY), fOrigin(&gCoordinateOrigin) { }
const std::string& Point2D::getId() const { return fId; }
void Point2D::setX(const double& aX) { fPosition.setX(aX); }
void Point2D::setY(const double& aY) { fPosition.setY(aY); }
const double Point2D::getX() const { return fPosition.getX(); }
const double Point2D::getY() const { return fPosition.getY(); }
void Point2D::setOrigin(const Point2D& aPoint) { fOrigin = &aPoint;}
Vector2D Point2D::operator-(const Point2D& aRHS) const
{
return (fPosition - aRHS.fPosition);
}
// Return Direction with reference to origin
double Point2D::direction() const
{
return fOrigin->directionTo(*this);
}
// Return Direction with reference to origin
double Point2D::magnitude() const
{
return fOrigin->magnitudeTo(*this);;
}
bool Point2D::isCollinear(const Point2D& aOther) const
{
if (fPosition.cross(aOther.fPosition) == 0)
{
return true;
}
return false;
}
// Check to see if the point is Clockwise or not
bool Point2D::isClockwise(const Point2D& aP0, const Point2D& aP2) const
{
double val = (fPosition.getY() - aP0.fPosition.getY()) * (aP2.fPosition.getX() - fPosition.getX()) -
(fPosition.getX() - aP0.fPosition.getX()) * (aP2.fPosition.getY() - fPosition.getY());
double val2 = fPosition.angleBetween(aP2.fPosition) - fPosition.angleBetween(aP0.fPosition);
if (val < 0 )
{
return false;
}
return true;
}
bool Point2D::operator<(const Point2D& aRHS) const
{
if (fPosition.getY() < aRHS.getY())
{
return true;
}
return false;
}
const Point2D& Point2D::getOrigin() const { return *fOrigin;}
std::ostream& operator<<(std::ostream& aOStream, const Point2D& aObject)
{
aOStream << aObject.fId << " : " << aObject.fPosition;
return aOStream;
}
std::istream& operator>>(std::istream& aIStream, Point2D& aObject)
{
aIStream >> aObject.fId >> aObject.fPosition;
return aIStream;
}
#include <fstream>
#include <stdexcept>
#include <algorithm>
#include <functional>
#include <vector>
#include "Point2D.h"
class Point2DSet
{
public:
using Comparator = std::function<bool(const Point2D&, const Point2D&)>;
using Iterator = std::vector<Point2D>::const_iterator;
void add (const Point2D & aPoint);
void add (Point2D && aPoint);
void removeLast ();
bool doesNotTurnLeft (const Point2D & aPoint) const;
void populate (const std::string & aFileName);
void buildConvexHull (Point2DSet & aConvexHull);
size_t size () const;
void clear ();
void sort (Comparator aComparator);
const Point2D & operator[] (size_t aIndex) const;
Iterator begin () const;
Iterator end () const;
void rotatePointsByLowest();
std::vector < Point2D > fPoints;
};
#include "Point2DSet.h"
#include <fstream>
#include <stdexcept>
#include <algorithm>
void Point2DSet::add(const Point2D& aPoint)
{
fPoints.push_back(aPoint);
}
void Point2DSet::add(Point2D&& aPoint)
{
fPoints.push_back(aPoint);
}
void Point2DSet::removeLast()
{
fPoints.pop_back();
}
bool Point2DSet::doesNotTurnLeft(const Point2D& aPoint) const
{
return fPoints[size()-1].isClockwise(fPoints[size()-2],aPoint);
}
// Comparator function for Stable_sort
bool orderByCoordinates(const Point2D& aLeft, const Point2D& aRight)
{
return aLeft < aRight;
}
bool orderByMagnitudeDescending(const Point2D& aLeft, const Point2D& aRight)
{
return aLeft.magnitude() > aRight.magnitude();
}
//Comparator function for Stable_sort
bool orderByPolarAngle(const Point2D& aLHS, const Point2D& aRHS)
{
if (aLHS.isCollinear(aRHS))
{
return aLHS.magnitude() > aRHS.magnitude();
}
return aLHS.direction() < aRHS.direction();
}
void Point2DSet::populate(const std::string& aFileName)
{
std::ifstream INPUT(aFileName);
//std::ifstream INPUT("Pointers.txt");
std::string id;
double x;
double y;
while (INPUT >> id >> x >> y)
{
Point2D z(id, x, y);
add(z);
}
INPUT.close();
}
void Point2DSet::rotatePointsByLowest() {
auto lowestPoint = fPoints.begin();
for (auto iterator = fPoints.begin() + 1;iterator != fPoints.end(); iterator++) {
if (iterator->fPosition.fY < lowestPoint->fPosition.fY) {
lowestPoint = iterator;
} else if ((iterator->fPosition.fY == lowestPoint->fPosition.fY) && (iterator->fPosition.fX < lowestPoint->fPosition.fX)) {
lowestPoint = iterator;
}
}
std::rotate(fPoints.begin(), lowestPoint, fPoints.end());
}
void Point2DSet::buildConvexHull(Point2DSet& aConvexHull)
{
aConvexHull.clear();
// Get points with bigger magnitude first.
sort(orderByMagnitudeDescending);
sort(orderByPolarAngle);
// We want to have the lowest point as the first element.
rotatePointsByLowest();
aConvexHull.add(fPoints[0]); // Origin (Smallest y-coordinate)
aConvexHull.add(fPoints[1]);
for(size_t i = 2; i < size(); i++)
{
if (fPoints[i - 1].isCollinear(fPoints[i]))
{
continue; //i++;
}
// There should be a loop instead of an if statement.
while (aConvexHull.fPoints.size() > 2 && aConvexHull.doesNotTurnLeft(fPoints[i]))
{
aConvexHull.removeLast();
}
aConvexHull.add(fPoints[i]);
}//*/
}
size_t Point2DSet::size() const
{
return fPoints.size();
}
void Point2DSet::clear()
{
fPoints.clear();
}
void Point2DSet::sort(Comparator aComparator)
{
stable_sort(fPoints.begin(), fPoints.end(), aComparator);
}
const Point2D& Point2DSet::operator[](size_t aIndex) const
{
return fPoints[aIndex];
}
Point2DSet::Iterator Point2DSet::begin() const
{
return fPoints.begin();
}
Point2DSet::Iterator Point2DSet::end() const
{
return fPoints.end();
}