renaming labs
This commit is contained in:
8
labs/exceptions_inheritance/cp2/output_simple.txt
Normal file
8
labs/exceptions_inheritance/cp2/output_simple.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
7 Polygon(s): blue brown grey olive orange purple red
|
||||
3 Triangle(s): brown purple red
|
||||
2 IsoscelesTriangle(s): purple red
|
||||
1 EquilateralTriangle(s): red
|
||||
3 Quadrilateral(s): blue olive orange
|
||||
2 Rectangle(s): blue orange
|
||||
1 Square(s): blue
|
||||
3 Shape(s) with all equal sides: blue grey red
|
||||
7
labs/exceptions_inheritance/cp2/simple.txt
Normal file
7
labs/exceptions_inheritance/cp2/simple.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
blue (0,0) (0,1) (1,1) (1,0)
|
||||
brown (2,0) (0,1) (3,3)
|
||||
grey (1,0) (1.5,0.866) (1,1.732) (2,1.732) (2.5,0.866) (2,0)
|
||||
olive (0,0) (1,2) (6,3) (4,0)
|
||||
orange (0,0) (0,3) (2,3) (2,0)
|
||||
purple (0,0) (0,2) (3,1)
|
||||
red (0,0) (0.5,0.866) (1,0)
|
||||
168
labs/exceptions_inheritance/cp2/simple_main.cpp
Normal file
168
labs/exceptions_inheritance/cp2/simple_main.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
|
||||
#include "polygons.h"
|
||||
|
||||
// helper function prototypes
|
||||
Polygon* CreatePolygon(const std::string &name, const std::vector<Point> &points);
|
||||
void OutputStats(const std::vector<Polygon*> &polygons, std::ofstream &ostr);
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
// command line arguments & opening files
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " input.txt output.txt" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::ifstream istr(argv[1]);
|
||||
if (!istr) {
|
||||
std::cerr << "ERROR: could not open " << argv[1] << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::ofstream ostr(argv[2]);
|
||||
if (!ostr) {
|
||||
std::cerr << "ERROR: could not open " << argv[2] << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// the master container of polygons
|
||||
std::vector<Polygon*> polygons;
|
||||
|
||||
// read the input file one line at a time
|
||||
std::string line;
|
||||
while (getline(istr,line)) {
|
||||
std::stringstream ss(line);
|
||||
std::string name, token;
|
||||
if (!(ss >> name)) continue;
|
||||
std::vector<Point> points;
|
||||
while (ss >> token) {
|
||||
std::stringstream ss2(token);
|
||||
char c;
|
||||
double x,y;
|
||||
ss2 >> c;
|
||||
assert (c == '(');
|
||||
ss2 >> x;
|
||||
ss2 >> c;
|
||||
assert (c == ',');
|
||||
ss2 >> y;
|
||||
ss2 >> c;
|
||||
assert (c == ')');
|
||||
points.push_back(Point(x,y));
|
||||
}
|
||||
assert (points.size() >= 3);
|
||||
Polygon* p = CreatePolygon(name,points);
|
||||
// add the new polygon to the master container
|
||||
polygons.push_back(p);
|
||||
}
|
||||
|
||||
// write out the statistics
|
||||
OutputStats(polygons,ostr);
|
||||
|
||||
// delete the dynamically allocated polygons
|
||||
for (int i = 0; i < polygons.size(); i++) {
|
||||
delete polygons[i];
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
// This function determines the most specific type of shape that can
|
||||
// be created from the sequence of points. It does this by process of
|
||||
// elimination. Note that the order in which it attempts to create
|
||||
// the shapes is important.
|
||||
|
||||
Polygon* CreatePolygon(const std::string &name, const std::vector<Point> &points) {
|
||||
Polygon *answer = NULL;
|
||||
try{
|
||||
answer = new EquilateralTriangle(name,points);
|
||||
}
|
||||
catch (int) {
|
||||
try {
|
||||
answer= new IsoscelesTriangle(name,points);
|
||||
}
|
||||
catch (int) {
|
||||
try {
|
||||
answer= new Triangle(name,points);
|
||||
}
|
||||
catch (int) {
|
||||
try {
|
||||
answer= new Square(name,points);
|
||||
}
|
||||
catch (int) {
|
||||
try {
|
||||
answer= new Rectangle(name,points);
|
||||
}
|
||||
catch (int) {
|
||||
try {
|
||||
answer= new Quadrilateral(name,points);
|
||||
}
|
||||
catch (int) {
|
||||
answer= new Polygon(name,points);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert (answer != NULL);
|
||||
return answer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
// This function prints the output. C++ macros are used to abbreviate
|
||||
// some repetitive code. The function call-like macros are actually
|
||||
// replaced using substitution by the preprocessor before the code is
|
||||
// given to the compiler. (You are not required to understand the
|
||||
// details of the macros. You do not need to edit this code.)
|
||||
|
||||
void OutputStats(const std::vector<Polygon*> &polygons, std::ofstream &ostr) {
|
||||
|
||||
// define and initialize variables
|
||||
# define InitializeCount(type) std::vector<std::string> all_##type
|
||||
InitializeCount(Polygon);
|
||||
InitializeCount(Triangle);
|
||||
InitializeCount(IsoscelesTriangle);
|
||||
InitializeCount(EquilateralTriangle);
|
||||
InitializeCount(Quadrilateral);
|
||||
InitializeCount(Rectangle);
|
||||
InitializeCount(Square);
|
||||
std::vector<std::string> equal_sides;
|
||||
|
||||
// count & record the names of shapes in each category
|
||||
for (std::vector<Polygon*>::const_iterator i = polygons.begin(); i!=polygons.end(); ++i) {
|
||||
# define IncrementCount(type) if (dynamic_cast<type*> (*i)) all_##type.push_back((*i)->getName())
|
||||
IncrementCount(Polygon);
|
||||
IncrementCount(Triangle);
|
||||
IncrementCount(IsoscelesTriangle);
|
||||
IncrementCount(EquilateralTriangle);
|
||||
IncrementCount(Quadrilateral);
|
||||
IncrementCount(Rectangle);
|
||||
IncrementCount(Square);
|
||||
if ((*i)->HasAllEqualSides()) equal_sides.push_back((*i)->getName());
|
||||
}
|
||||
|
||||
|
||||
// output data for each category, sorted alphabetically by the shape's name
|
||||
# define PrintVector(vecname) std::sort((vecname).begin(),(vecname).end()); \
|
||||
for (unsigned int j = 0; j < (vecname).size(); j++) { ostr << " " << (vecname)[j]; } ostr << std::endl
|
||||
# define PrintCount(type) do { ostr << all_##type.size() << " " #type"(s): "; PrintVector(all_##type); } while (0)
|
||||
PrintCount(Polygon);
|
||||
PrintCount(Triangle);
|
||||
PrintCount(IsoscelesTriangle);
|
||||
PrintCount(EquilateralTriangle);
|
||||
PrintCount(Quadrilateral);
|
||||
PrintCount(Rectangle);
|
||||
PrintCount(Square);
|
||||
ostr << equal_sides.size() << " Shape(s) with all equal sides: ";
|
||||
PrintVector(equal_sides);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
120
labs/exceptions_inheritance/cp2/utilities.h
Normal file
120
labs/exceptions_inheritance/cp2/utilities.h
Normal file
@@ -0,0 +1,120 @@
|
||||
// =========================================
|
||||
//
|
||||
// IMPORTANT NOTE: DO NOT EDIT THIS FILE
|
||||
//
|
||||
// =========================================
|
||||
|
||||
#ifndef _UTILITIES_H_
|
||||
#define _UTILITIES_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
|
||||
// epsilon values used in comparing the edge lengths & angles between
|
||||
// edges note that these values are dependent on the precision of
|
||||
// the coordinates and the overall scale of the objects
|
||||
#define DISTANCE_EPSILON 0.0001
|
||||
#define ANGLE_EPSILON 0.1
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// Stores a 2D coordinate
|
||||
class Point {
|
||||
public:
|
||||
Point(double _x, double _y) : x(_x),y(_y) {}
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
// Stores a 2D vector, constructed from 2 Points
|
||||
class Vector {
|
||||
public:
|
||||
Vector(const Point &a, const Point &b) { dx = b.x-a.x; dy = b.y-a.y; }
|
||||
double Length() const { return sqrt(dx*dx+dy*dy); }
|
||||
void Normalize() {
|
||||
// make this a unit vector (length = 1)
|
||||
double length = Length();
|
||||
if (length < DISTANCE_EPSILON) throw std::string("LENGTH = 0");
|
||||
assert (length > DISTANCE_EPSILON);
|
||||
dx /= length;
|
||||
dy /= length;
|
||||
}
|
||||
// representation
|
||||
double dx;
|
||||
double dy;
|
||||
};
|
||||
|
||||
|
||||
inline std::ostream& operator<< (std::ostream &ostr, const Vector &v) {
|
||||
ostr << "<" << v.dx << "," << v.dy << ">";
|
||||
return ostr;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// calculate the length of an edge, the distance between 2 points
|
||||
inline double DistanceBetween(const Point &a, const Point &b) {
|
||||
Vector v(a,b);
|
||||
return v.Length();
|
||||
}
|
||||
|
||||
// Calculate the angle at vertex b in degrees, that is, the angle
|
||||
// between edges ab and bc. This will return a positive number
|
||||
// measured as the clockwise rotation in the xy plane from point c to
|
||||
// point a (rotating around point b).
|
||||
inline double Angle(const Point &a, const Point &b, const Point &c) {
|
||||
// make unit vector along each of the edges
|
||||
Vector ba(b,a); ba.Normalize();
|
||||
Vector bc(b,c); bc.Normalize();
|
||||
// calculate the angle in radians
|
||||
double dot_product = ba.dx * bc.dx + ba.dy * bc.dy;
|
||||
|
||||
if (dot_product < -1 || dot_product > 1) throw std::string("DOT PRODUCT RANGE");
|
||||
|
||||
assert (dot_product >= -1 && dot_product <= 1);
|
||||
float perpDot = ba.dx * bc.dy - ba.dy * bc.dx;
|
||||
// using atan2 to ensure than we get a signed answer.
|
||||
double angle_in_radians = atan2(perpDot, dot_product);
|
||||
// convert to degrees
|
||||
double answer = angle_in_radians * 180.0 / M_PI;
|
||||
if (answer < 0) {
|
||||
answer += 360;
|
||||
}
|
||||
assert (answer >= 0 && answer <= 360);
|
||||
return answer;
|
||||
}
|
||||
|
||||
// returns true if these two vectors are parallel
|
||||
inline bool Parallel(const Vector &a, const Vector &b) {
|
||||
Vector a2 = a; a2.Normalize();
|
||||
Vector b2 = b; b2.Normalize();
|
||||
double dot_product = a2.dx * b2.dx + a2.dy * b2.dy;
|
||||
// parallel vectors have dot product == 1
|
||||
if (fabs(dot_product) > 1-DISTANCE_EPSILON) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// simple functions for angles & sides
|
||||
|
||||
inline bool EqualSides(double a, double b) {
|
||||
return (fabs(a-b) < DISTANCE_EPSILON);
|
||||
}
|
||||
|
||||
inline bool EqualAngles(double a, double b) {
|
||||
assert (a >= 0.0 && a < 360.0);
|
||||
assert (b >= 0.0 && b < 360.0);
|
||||
return (fabs(a-b) < ANGLE_EPSILON);
|
||||
}
|
||||
|
||||
inline bool RightAngle(double a) {
|
||||
assert (a >= 0.0 && a < 360.0);
|
||||
return (fabs(a-90.0) < ANGLE_EPSILON);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user