/*
* File: ShapeTwoD.h
* Author: Administrator
*
* Created on October 30, 2012, 12:05 AM
*/
#ifndef SHAPETWOD_H
#define SHAPETWOD_H
#include <string>
#include <math.h>
using namespace std;
struct Point {
int x, y;
};
class ShapeTwoD {
public:
ShapeTwoD(string shapename, bool containsWS);
string getName();
bool getContainsWarpSpace();
string toString();
virtual double computeArea();
virtual bool isPointInShape(Point P, Point* V, int n);
virtual bool isPointOnShape(Point A, Point B, Point C, int slope, int intercept, int left, int top, int right, int bottom, int dx, int dy);
void setName(string shapename);
void setContainsWarpSpace(bool containsWS);
private:
string name;
bool containsWarpSpace;
};
class Cross : public ShapeTwoD {
public:
Cross(string shapename = "Cross", bool containsWS, int vertices = 12, Point ordinates[]):ShapeTwoD(shapename, containsWS){}
int getVert();
void setVert(int vertices);
Point getOrd();
void setOrd(Point ordinates[]);
virtual double computeArea(Point A[], int vertices);
private:
int vert;
Point ord[];
};
class Rectangle : public ShapeTwoD {
public:
Rectangle(string shapename = "Rectangle", bool containsWS, int vertices = 4, Point ordinates[]):ShapeTwoD(shapename, containsWS){}
int getVert();
void setVert(int vertices);
Point getOrd();
void setOrd(Point ordinates[]);
virtual double computeArea(Point A, Point B);
private:
int vert;
Point ord[];
};
class Square : public ShapeTwoD {
public:
Square(string shapename = "Square", bool containsWS, int vertices = 4, Point ordinates[]):ShapeTwoD(shapename, containsWS){}
int getVert();
void setVert(int vertices);
Point getOrd();
void setOrd(Point ordinates[]);
virtual double computeArea(Point A, Point B);
private:
int vert;
Point ord[];
};
#endif /* SHAPETWOD_H */
/*
* File: ShapeTwoD.cpp
* Author: Administrator
*
* Created on October 30, 2012, 12:05 AM
*/
#include "ShapeTwoD.h"
#include <sstream>
ShapeTwoD::ShapeTwoD(string shapename, bool containsWS) {
name = shapename;
containsWarpSpace = containsWS;
}
string ShapeTwoD::getName() {
return name;
}
void ShapeTwoD::setName(string shapename) {
name = shapename;
};
bool ShapeTwoD::getContainsWarpSpace() {
return containsWarpSpace;
}
void ShapeTwoD::setContainsWarpSpace(bool containsWS) {
containsWarpSpace = containsWS;
}
string cvtBool(bool b) {
stringstream ss;
ss << b;
return ss.str();
}
string ShapeTwoD::toString() {
return "Name:\t" + name + "\nSpecial Type:\t" + cvtBool(containsWarpSpace) + "\n";
}
// Formulas gotten from http://www.mathopenref.com/coordpolygonarea.html
// http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm
int pointsInShape;
int pointsOnShape;
double ShapeTwoD::computeArea() {
// Based on Pick's Thorem
double area = pointsInShape + (pointsOnShape / 2) - 1;
return area;
}
float isLeft(Point P0, Point P1, Point P2) {
return ((P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y));
}
bool ShapeTwoD::isPointInShape(Point P, Point* V, int n) {
// Input: P = a point,
// V[] = vertex points of a polygon V[n+1] with V[n]=V[0]
int wn = 0; // the winding number counter
// loop through all edges of the polygon
for (int i = 0; i < n; i++) { // edge from V[i] to V[i+1]
if (V[i].y <= P.y) { // start y <= P.y
if (V[i + 1].y > P.y) // an upward crossing
if (isLeft(V[i], V[i + 1], P) > 0) // P left of edge
++wn; // have a valid up intersect
} else { // start y > P.y (no test needed)
if (V[i + 1].y <= P.y) // a downward crossing
if (isLeft(V[i], V[i + 1], P) < 0) // P right of edge
--wn; // have a valid down intersect
}
}
pointsInShape += wn;
return true;
}
bool ShapeTwoD::isPointOnShape(Point A, Point B, Point C, int slope, int intercept, int left, int top, int right, int bottom, int dx, int dy) {
// Linear equation
dx = B.x - A.x;
dy = B.y - A.y;
slope = dy / dx;
intercept = y1 - slope * A.x;
if (A.x < B.x) {
left = A.x;
right = B.x;
} else {
left = B.x;
right = A.x;
}
if (A.y < B.y) {
top = A.y;
bottom = B.y;
} else {
top = B.y;
bottom = A.y;
}
if (slope * C.x + intercept > (C.y - 0.01) && slope * C.x + intercept < (C.y + 0.01)) {
if (C.x >= left && C.x <= right && C.y >= top && C.y <= bottom) {
pointsOnShape++;
return true;
}
}
}
Cross::Cross(string shapename, bool containsWS, int vertices = 12, Point ordinates[]):ShapeTwoD(shapename, containsWS) {
vert = vertices;
ord[] = ordinates[];
}
int Cross::getVert() {
return vert;
}
void Cross::setVert(int vertices) {
vert = vertices;
}
Point Cross::getOrd() {
return ord[];
}
void Cross::setOrd(Point ordinates[]) {
ord[] = ordinates[];
}
double Cross::computeArea(Point A[], int vertices) {
/* If you know the coordinates of the vertices of a polygon, this algorithm can be used to find the area.
* Parameters
* X, Y Arrays of the x and y coordinates of the vertices, traced in a clockwise direction, starting at any vertex. If you trace them counterclockwise, the result will be correct but have a negative sign.
* numPoints The number of vertices
* Returns the area of the polygon
*/
double area = 0;
int j = vertices - 1; // The last vertex is the 'previous' one to the first
for (int i = 0; i < vertices; i++) {
area = (area + (A[j].x + A[i].x) * (A[j].y - A[i].y))/2;
j = i;
}
return area;
}
Rectangle::Rectangle(string shapename, bool containsWS, int vertices = 4, Point ordinates[]):ShapeTwoD(shapename, containsWS) {
vert = vertices;
ord[] = ordinates[];
}
int Rectangle::getVert() {
return vert;
}
void Rectangle::setVert(int vertices) {
vert = vertices;
}
void Rectangle::getOrd() {
return ord[];
}
void Rectangle::setOrd(Point ordinates[]) {
ord[] = ordinates[];
}
double Rectangle::computeArea(Point A, Point B, Point C) {
double length = sqrt(pow((A.x - B.x), 2) + pow((A.y - B.y), 2));
double width = sqrt(pow((B.x - C.x), 2) + pow((B.y - C.y), 2));
double area = length * width;
return area;
}
Square::Square(string shapename, bool containsWS, int vertices, Point ordinates[]):ShapeTwoD(shapename, containsWS) {
vert = vertices;
ord[] = ordinates[];
}
int Square::getVert() {
return vert;
}
void Square::setVert(int vertices) {
vert = vertices;
}
void Square::getOrd() {
return ord[];
}
void Square::setOrd(Point ordinates[]) {
ord[] = ordinates[];
}
double Square::computeArea(Point A, Point B) {
double length = sqrt(pow((A.x - B.x), 2) + pow((A.y - B.y), 2));
double area = pow(length, 2);
return area;
}
/*
* File: Assn2.cpp
* Author: Administrator
*
* Created on October 29, 2012, 11:58 PM
*/
#include "ShapeTwoD.h"
#include <iostream>
#include <math.h>
#include <string>
#include <vector>
using namespace std;
// Global declarations
void menu(), option1(), option2(), option3(), option4();
int choice, vert;
string shape, special;
double area;
bool containsWS;
vector<ShapeTwoD> stdv;
int main() {
cout << "Welcome to Assn2 program!\n\n";
// When user enters 5 as input, the program quits
while (choice != 5) {
menu();
/* switch evaluates expression and checks if it is equivalent to constant1,
* if it is, it executes group of statements 1 until it finds the break statement.
* When it finds this break statement the program jumps to the end of the switch selective structure.
* If expression was not equal to constant1 it will be checked against constant2.
* If it is equal to this, it will execute group of statements 2 until a break keyword is found,
* and then will jump to the end of the switch selective structure.
*/
switch (choice) {
case 1:
option1();
break;
case 2:
option2();
break;
case 3:
option3();
break;
case 4:
option4();
break;
}
}
}
void menu() {
cout << "1) Input sensor data\n";
cout << "2) Compute area (for all records)\n";
cout << "3) Print shapes report\n";
cout << "4) Sort shape data\n";
cout << "5) Quit\n\n";
cout << "Please enter your choice: ";
cin >> choice;
cout << "\n";
}
void option1() {
cout << "[ Input sensor data ]\n";
cout << "Please enter name of Shape (Cross, Rectangle or Square): ";
cin >> shape;
cout << "Please enter Special type (NS or WS): ";
cin >> special;
if (special == "WS") {
containsWS = true;
}
else {
containsWS = false;
}
if (shape == "Cross") {
vert = 12;
for (int v = 0; v < vert; v++) {
Point ordinates[v];
cout << "Please enter x-ordinate of pt. " << (v+1) << ":";
cin >> ordinates[v].x;
cout << "Please enter y-ordinate of pt. " << (v+1) << ":";
cin >> ordinates[v].y;
Cross cross(shape, containsWS, vert, ordinates[v]);
stdv.push_back(cross);
}
}
if (shape == "Rectangle") {
vert = 4;
for (int v = 0; v < vert; v++) {
Point ordinates[v];
cout << "Please enter x-ordinate of pt. " << (v+1) << ":";
cin >> ordinates[v].x;
cout << "Please enter y-ordinate of pt. " << (v+1) << ":";
cin >> ordinates[v].y;
Rectangle rectangle(shape, containsWS, vert, ordinates[v]);
stdv.push_back(rectangle);
}
}
else {
shape = "Square";
vert = 4;
for (int v = 0; v < vert; v++) {
Point ordinates[v];
cout << "Please enter x-ordinate of pt. " << (v+1) << ":";
cin >> ordinates[v].x;
cout << "Please enter y-ordinate of pt. " << (v+1) << ":";
cin >> ordinates[v].y;
Square square(shape, containsWS, vert, ordinates[v]);
stdv.push_back(square);
}
}
cout << "Record successfully stored. Going back to main menu";
}
void option2() {
if (stdv.size() != 0) {
for (int count = 0; count < stdv.size(); count++) {
area = stdv.at(count).computeArea();
//Debugging purpose
cout << (count+1) << ")" << stdv.at(count).getName() << "\t" << area;
}
cout << "Computation completed! (" << stdv.size() << " records were updated)\n\n";
}
}
Here I'm trying to insert an array of the struct Point into my class constructors (Cross, Rectangle, Square). But it returned me some errors which I don't really get.
Assn2.cpp:113: error: no matching function for call to
`Cross::Cross(std::string&, bool&, int&, Point&)'
ShapeTwoD.h:41: note: candidates are: Cross::Cross(const Cross&)
ShapeTwoD.h:43: note: Cross::Cross(std::string, bool,
int, Point*)
Assn2.cpp:136: error: no matching function for call to
`Rectangle::Rectangle(std::string&, bool&, int&, Point&)
ShapeTwoD.h:56: note: candidates are: Rectangle::Rectangle(const
Rectangle&)
ShapeTwoD.h:58: note: Rectangle::Rectangle(std::string, bool, int,
Point*)
your function declaration won't even compile, the parameter with default value can't be in the front of argument without default value:
Cross(string shapename = "Cross", bool containsWS, int vertices = 12, Point ordinates[])
Rectangle(string shapename = "Rectangle", bool containsWS, int vertices = 4, Point ordinates[]):ShapeTwoD(shapename, containsWS){}
Square(string shapename = "Square", bool containsWS, int vertices = 4, Point ordinates[]):ShapeTwoD(shapename, containsWS){}
you either make all parameters having all default values or change the order, for example below is valid function declaration:
Cross(bool containsWS, Point ordinates[], string shapename = "Cross", int vertices = 12)
Related
I'm trying to solve this problem using the slicing technic.
But I just passed the first two test cases in this gym (Problem A)
2017-2018 ACM-ICPC East Central North America Regional Contest (ECNA 2017)
The whole step in my code looks like this:
calculate the total area using vector cross when inputting the polygon information.
find all the endpoints and intersection points, and record x value of them.
for each slice (sort x list and for each interval) find the lines from every polygon which crosses this interval and store this smaller segment.
sort segments.
for each trapezoid or triangle, calculate the area if this area is covered by some polygon.
sum them all to find the cover area.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template<typename T> using p = pair<T, T>;
template<typename T> using vec = vector<T>;
template<typename T> using deq = deque<T>;
// #define dbg
#define yccc ios_base::sync_with_stdio(false), cin.tie(0)
#define al(a) a.begin(),a.end()
#define F first
#define S second
#define eb emplace_back
const int INF = 0x3f3f3f3f;
const ll llINF = 1e18;
const int MOD = 1e9+7;
const double eps = 1e-9;
const double PI = acos(-1);
double fcmp(double a, double b = 0, double eps = 1e-9) {
if (fabs(a-b) < eps) return 0;
return a - b;
}
template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& a) { in >> a.F >> a.S; return in; }
template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> a) { out << a.F << ' ' << a.S; return out; }
struct Point {
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
Point operator+(const Point& src) {
return Point(src.x + x, src.y + y);
}
Point operator-(const Point& src) {
return Point(x - src.x, y - src.y);
}
Point operator*(double src) {
return Point(x * src, y * src);
}
//* vector cross.
double operator^(Point src) {
return x * src.y - y * src.x;
}
};
struct Line {
Point sp, ep;
Line() {}
Line(Point sp, Point ep) : sp(sp), ep(ep) {}
//* check if two segment intersect.
bool is_intersect(Line src) {
if (fcmp(ori(src.sp) * ori(src.ep)) < 0 and fcmp(src.ori(sp) * src.ori(ep)) < 0) {
double t = ((src.ep - src.sp) ^ (sp - src.sp)) / ((ep - sp) ^ (src.ep - src.sp));
return fcmp(t) >= 0 and fcmp(t, 1) <= 0;
}
return false;
}
//* if two segment intersect, find the intersection point.
Point intersect(Line src) {
double t = ((src.ep - src.sp) ^ (sp - src.sp)) / ((ep - sp) ^ (src.ep - src.sp));
return sp + (ep - sp) * t;
}
double ori(Point src) {
return (ep - sp) ^ (src - sp);
}
bool operator<(Line src) const {
if (fcmp(sp.y, src.sp.y) != 0)
return sp.y < src.sp.y;
return ep.y < src.ep.y;
}
};
int next(int i, int n) {
return (i + 1) % n;
}
int main()
{
yccc;
int n;
cin >> n;
//* the point list and the line list of polygons.
vec<vec<Point>> p_list(n);
vec<vec<Line>> l_list(n);
//* x's set for all endpoints and intersection points
vec<double> x_list;
//* initializing point list and line list
double total = 0, cover = 0;
for (int i = 0; i < n; i++) {
int m;
cin >> m;
p_list[i].resize(m);
for (auto &k : p_list[i]) {
cin >> k.x >> k.y;
x_list.eb(k.x);
}
l_list[i].resize(m);
for (int k = 0; k < m; k++) {
l_list[i][k].sp = p_list[i][k];
l_list[i][k].ep = p_list[i][next(k, m)];
}
//* calculate the polygon area.
double tmp = 0;
for (int k = 0; k < m; k++) {
tmp += l_list[i][k].sp.x * l_list[i][k].ep.y - l_list[i][k].sp.y * l_list[i][k].ep.x;
}
total += abs(tmp);
}
//* find all intersection points
for (int i = 0; i < n; i++)
for (int k = i+1; k < n; k++) {
for (auto li : l_list[i])
for (auto lk : l_list[k])
if (li.is_intersect(lk)) {
x_list.eb(li.intersect(lk).x);
}
}
sort(al(x_list));
auto same = [](double a, double b) -> bool {
return fcmp(a, b) == 0;
};
x_list.resize(unique(al(x_list), same) - x_list.begin());
//* for each slicing, calculate the cover area.
for (int i = 0; i < x_list.size() - 1; i++) {
vec<pair<Line, int>> seg;
for (int k = 0; k < n; k++) {
for (auto line : l_list[k]) {
//* check if line crosses this slicing
if (fcmp(x_list[i], min(line.sp.x, line.ep.x)) >= 0 and fcmp(max(line.sp.x, line.ep.x), x_list[i+1]) >= 0) {
Point sub = line.ep - line.sp;
double t_sp = (x_list[i] - line.sp.x) / sub.x, t_ep = (x_list[i+1] - line.sp.x) / sub.x;
seg.eb(Line(Point(x_list[i], line.sp.y + sub.y * t_sp), Point(x_list[i+1], line.sp.y + sub.y * t_ep)), k);
}
}
}
//* sort this slicing
sort(al(seg));
deq<bool> inside(n);
int count = 0;
Line prev;
// cout << x_list[i] << ' ' << x_list[i+1] << endl;
//* calculate cover area in this slicing.
for (int k = 0; k < seg.size(); k++) {
if (count)
cover += ((seg[k].F.sp.y - prev.sp.y) + (seg[k].F.ep.y - prev.ep.y)) * (x_list[i+1] - x_list[i]);
prev = seg[k].F;
// cout << seg[k].S << ": (" << seg[k].F.sp.x << ", " << seg[k].F.sp.y << "), (" << seg[k].F.ep.x << ", " << seg[k].F.ep.y << ")" << endl;
inside[k] = !inside[k];
count += (inside[k] ? 1 : -1);
}
}
//* answer
cout << total / 2 << ' ' << cover / 2;
}
I can't not figure out which part I made a mistake :(
I have a problem with my code, every time I use my arrays (vTab or eTab) of an object inside of cube:3D_obj it returns me pointer ID or nan. Well just for context here's the whole code, but those arrays are only the problem because the code is running fine.
For debugging purposes, I wrote cout's in some places. Also, I tried to init vTab[] as new vertice[8], but the same results.
I came up with one problem, that I might have to init verticle object outside of functions but i don't know actually how to handle it.
If you need to know this project have to represent simple 3D figures as data with classes/objects
Two vertices make an edge, edges make figures, etc.
IDE: I use Visual Studio on Windows
#define pi 3.14159265359
#define eps 0.0001
#include <iostream>
#include <math.h>
using namespace std;
double aprox(double x, double y) {
return round(10000 * x) / 10000;
}
class vertice {
double x;
double y;
double z;
friend ostream& operator<< (ostream& c, vertice& orig);
public:
vertice() {//init funciton
x = y = z = 0;
}
vertice(double ix, double iy, double iz) {//init function
x = ix;
y = iy;
z = iz;
}
vertice& operator- (vertice& orig) {
vertice temp = *this;
temp.x -= orig.x;
temp.y -= orig.y;
temp.z -= orig.z;
return temp;
}
vertice& operator+ (vertice& orig) {
vertice temp = *this;
temp.x += orig.x;
temp.y += orig.y;
temp.z += orig.z;
return temp;
}
void position(double ix, double iy, double iz) { //change the position of the vertice
x = ix;
y = iy;
z = iz;
}
void position(double ix) {
x = ix;
}
void rotate(double ax, double ay, double az, vertice anchorPoint = vertice(0, 0, 0)) { //rotate in 3D (angle) axis using anchor point
vertice tempVertice = *this - anchorPoint;
double cosX = cos(ax * pi / 180), cosY = cos(ay * pi / 180), cosZ = cos(az * pi / 180), sinX = sin(ax * pi / 180), sinY = sin(ay * pi / 180), sinZ = sin(az * pi / 180);
//rotate X
y = aprox(tempVertice.y * cosX - tempVertice.z * sinX, eps);
z = aprox(tempVertice.z * cosX + tempVertice.y * sinX, eps);
tempVertice = *this;
//rotate Y
x = aprox(tempVertice.x * cosY - tempVertice.z * sinY, eps);
z = aprox(tempVertice.z * cosY + tempVertice.x * sinY, eps);
tempVertice = *this;
//rotate Z
x = aprox(tempVertice.x * cosZ - tempVertice.y * sinZ, eps);
y = aprox(tempVertice.y * cosZ + tempVertice.x * sinZ, eps);
//tempVertice = *this;
*this = *this + anchorPoint;
}
//~vertice() {};
};
ostream& operator<< (ostream& c, vertice& orig) { //using << operator to stream data from vertice
cout << "x= " << orig.x << " | y= " << orig.y << " | z= " << orig.z;
return c;
}
class edge {
friend ostream& operator<< (ostream& c, edge& orig);
public:
vertice* v1;
vertice* v2;
edge() {
v1 = new vertice();
v2 = new vertice();
}
edge(vertice iv1, vertice iv2) {
v1 = &iv1;
v2 = &iv2;
}
};
ostream& operator<< (ostream& c, edge& orig) { //printing edges as two vertex
cout << "Edge: \n* " << *orig.v1 << "\n* " << *orig.v2 << endl;
return c;
}
class obj_3D {
vertice position;
vertice anchorPoint;
//material type; //not using
public:
void Draw() {}
//~obj_3D() {};
};
class cube : public obj_3D {
double a;
edge eTab[12];
vertice vTab[8];
public:
cube(double ia) { //creating vertices, edges according to object properaties.
a = ia;
double Ph = aprox(asin(sqrt(2) / 2), eps), Alph = aprox(asin(3 * sqrt(2) / 3), eps);
double TPh = 0, TAlph = 0;
double R = a * sqrt(2) / 2;
for (int i = 0; i < 8; i++) { //initializing vertices
vTab[i] = vertice();
vTab[i].position(R);
vTab[i].rotate(Ph + TPh, Alph+ TAlph, 0);
if (i == 3) {
TPh = 0;
TAlph = 180;
}
else TPh += 90;
cout << vTab[i] << endl; //for debuging purp.
}
for (int i = 0; i < 10; i++) { //initializing edges
if (i < 4) {
eTab[i] = edge(vTab[i], vTab[(i + 1) % 4]);
eTab[i + 4] = edge(vTab[i], vTab[i + 4]);
cout << eTab[i] << eTab[i + 4] << endl;
}
else {
eTab[i + 4] = edge(vTab[i], vTab[((i + 1) % 4) + 4]);
cout << eTab[i + 4] << endl;
}
}
}
void print() {
cout << "Cube: \n";
for (int i = 0; i < 12; i++) {
edge temp = eTab[i];
cout << i+1 << ". " << temp << endl;
}
}
};
int main() {
/*vertice a = vertice();
vertice b = vertice(4.2, 1.3, 2.2);
cout << b;
b = b + a;
b = b - a;
b.rotate(90, 90, 90);
cout << endl << a;
edge e1 = edge(a, b);
cout << endl << e1;*/
//vertice b = vertice();
//cout << b;
cube c1 = cube(4);
//c1.print();
}
I really will appreciate your help because I really am stuck here and don't know what to do...
Is there a way to execute this code without using vectors?
Can this program be run without vectors in the polygon class?
If possible, how should I modify the code?
And is it right to write the copy constructor and the move constructor as it is now?
It's so hard to do C++ while playing Python. Help me.
Thank you.
Polygon.h
#pragma once
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
struct C2D {
double x, y;
};
class Polygon {
int point;
vector<C2D> arr;
public:
Polygon(int point_, C2D arr_[]) : arr(point_) {
point = point_;
memcpy(arr.data(), arr_, sizeof(C2D) * point);
};
Polygon(Polygon& p) : arr(p.point) {
point = p.point;
memcpy(arr.data(), p.arr.data(), sizeof(C2D) * point);
};
Polygon(Polygon&& p) {
point = p.point;
memcpy(arr.data(), p.arr.data(), sizeof(C2D) * point);
p.point = 0;
delete[]p.arr.data();
};
void print() const {
cout << "Polygon information" << endl;
for (int i = 0; i < point; i++) {
cout << i + 1<< "point" << " : " << arr[i].x << ", " << arr[i].y << endl;
}
cout << endl;
};
double area_result() {
double sum = 0;
for (int i = 1; i < point; i++) {
sum += ccw(arr[0].x, arr[i - 1].x, arr[i].x, arr[0].y, arr[i - 1].y, arr[i].y);
}
return fabs(sum);
}
static double ccw(double x1, double x2, double x3, double y1, double y2, double y3) {
double res = x1 * y2 + x2 * y3 + x3 * y1;
res += (-y1 * x2 - y2 * x3 - y3 * x1);
return res / 2;
}
};
main.cpp
int main() {
int point;
C2D* c2d;
cout << "point : ";
cin >> point;
cout << endl;
c2d = new C2D[point];
for (int i = 0; i < point; i++) {
cout << i + 1 << "x : ";
cin >> c2d[i].x;
cout << i + 1 << "y : ";
cin >> c2d[i].y;
cout << endl;
}
cout << endl;
Polygon p(point, c2d);
p.print();
cout << "Polygon area : " << p.area_result() << endl;
return 0;
}
Don't.
Vectors are one of those no-brainer improvements of C++ over C. Don't try to code around them, learn how to use them properly. You will see that many lines of code and many sources of headaches go away when you actually code C++.
Polygon.hpp
#ifndef POLYGON_HPP
#define POLYGON_HPP
#include <iostream>
#include <vector>
#include <cmath>
struct C2D
{
double x, y;
};
class Polygon
{
public:
Polygon( unsigned points_, std::vector<C2D> const & arr_ ) : points( points_ ), arr( arr_ ) {}
Polygon( Polygon & p ) : points( p.points ), arr( p.arr ) {}
Polygon( Polygon && p ) : points( p.points )
{
arr.swap( p.arr );
}
friend std::ostream & operator<<( std::ostream & out, Polygon const & p );
double area_result()
{
double sum = 0;
for ( unsigned i = 1; i < points; ++i )
{
sum += ccw( arr[0].x, arr[i - 1].x, arr[i].x, arr[0].y, arr[i - 1].y, arr[i].y );
}
return std::fabs( sum );
}
static double ccw( double x1, double x2, double x3, double y1, double y2, double y3 )
{
double res = x1 * y2 + x2 * y3 + x3 * y1;
res += ( -y1 * x2 - y2 * x3 - y3 * x1 );
return res / 2;
}
private:
unsigned points;
std::vector<C2D> arr;
};
#endif
main.cpp
#include "Polygon.hpp"
#include <vector>
#include <iostream>
std::ostream & operator<<( std::ostream & out, Polygon const & p )
{
out << "Polygon information" << std::endl;
for ( unsigned i = 0; i < p.points; ++i )
{
out << ( i + 1 ) << "point : " << p.arr[i].x << ", " << p.arr[i].y << std::endl;
}
out << std::endl;
return out;
}
int main()
{
int points;
std::vector<C2D> c2d;
std::cout << "points : ";
std::cin >> points;
c2d.reserve( points );
for (int i = 0; i < points; i++) {
C2D coord;
std::cout << i + 1 << "x : ";
std::cin >> coord.x;
std::cout << i + 1 << "y : ";
std::cin >> coord.y;
c2d.push_back( coord );
}
Polygon p( points, c2d );
std::cout << p << "Polygon area : " << p.area_result() << std::endl;
return 0;
}
Your code is using vector exactly like a C style array, so you can replace it with such an array with minimum changes.
In fact, it will make your code simpler to read, since you will not be misusing a C++ object like a C variable.
class Polygon {
int point;
C2D *arr;
public:
Polygon(int point_, C2D arr_[]) {
point = point_;
arr = new C2D[point];
//you should check here allocation is successful
memcpy(arr, arr_, sizeof(C2D) * point);
};
Polygon(Polygon& p) {
point = p.point;
arr = new C2D[point];
memcpy(arr, p.arr, sizeof(C2D) * point);
};
Polygon(Polygon&& p) {
point = p.point;
arr = p.arr;
p.point = 0;
p.arr = null;
};
//you will need to add a destructor to clean up memory
~Polygon() {
delete [] arr;
}
};
That said, as the comments suggest, this is a bad practice.
If you have some constraints, such as a limited C++ environment lacking a vector implementation, a need to interface your code with another language / runtime, or homework requirement, you should add them to your question for suggestions on better solution.
I have a class that I'm trying to use, but in main function ёstartё doesn't execute with following error expression preceeding of apparent call must have pointer-to func type
#include <queue>
#include <limits>
#include <cmath>
#include <iostream>
// represents a single pixel
class Node {
public:
int idx; // index in the flattened grid
float cost; // cost of traversing this pixel
Node(int i, float c) : idx(i), cost(c) {}
};
bool operator<(const Node &n1, const Node &n2) {
return n1.cost > n2.cost;
}
bool operator==(const Node &n1, const Node &n2) {
return n1.idx == n2.idx;
}
// various grid heuristics:
// http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#S7
float linf_norm(int i0, int j0, int i1, int j1) {
return std::max(std::abs(i0 - i1), std::abs(j0 - j1));
}
// manhattan distance
float l1_norm(int i0, int j0, int i1, int j1) {
return std::abs(i0 - i1) + std::abs(j0 - j1);
}
// weights: flattened h x w grid of costs
// h, w: height and width of grid
// start, goal: index of start/goal in flattened grid
// diag_ok: if true, allows diagonal moves (8-conn.)
// paths (output): for each node, stores previous node in path
class Astar {
public:
float* weights = nullptr;
int h;
int w;
int start;
int goal;
bool diag_ok;
int* paths = nullptr;
void setVariables(float* weightsInput, int hInput, int wInput, int startInput, int goalInput, bool diag_okInput, int* pathsInput) {
weights = weightsInput;
h = hInput;
w = wInput;
start = startInput;
goal = goalInput;
diag_ok = diag_okInput;
paths = pathsInput;
}
void start() {
const float INF = std::numeric_limits<float>::infinity();
std::cout << "width : " << w << " " << "height : " << h << std::endl;
std::cout << "start : " << start << " goal : " << goal << std::endl;
Node start_node(start, 0.);
Node goal_node(goal, 0.);
float* costs = new float[h * w];
for (int i = 0; i < h * w; ++i)
costs[i] = INF;
costs[start] = 0.;
std::priority_queue<Node> nodes_to_visit;
nodes_to_visit.push(start_node);
int* nbrs = new int[3];
bool solution_found = false;
while (!nodes_to_visit.empty()) {
// .top() doesn't actually remove the node
Node cur = nodes_to_visit.top();
if (cur == goal_node) {
solution_found = true;
break;
}
nodes_to_visit.pop();
int row = cur.idx / w;
int col = cur.idx % w;
bool allowDiag;
// check bounds and find up to eight neighbors: top to bottom, left to right
// can move only right\down\down - right so we can max have 3 neighbours
nbrs[0] = (col + 1 < w) ? cur.idx + 1 : -1; // right
nbrs[1] = (row + 1 < h) ? cur.idx + w : -1; // down
allowDiag = (weights[cur.idx + w + 1] == 14) ? true : false;
nbrs[2] = (allowDiag) ? cur.idx + w + 1 : -1; // down-right
std::cout << "right-bottom node : " << weights[cur.idx + w + 1] << std::endl;
float heuristic_cost;
for (int i = 0; i < 3; ++i) {
std::cout << "neighbours : " << nbrs[i] << " ";
if (nbrs[i] >= 0) {
// the sum of the cost so far and the cost of this move
float new_cost = costs[cur.idx] + weights[nbrs[i]];
if (new_cost < costs[nbrs[i]]) {
// estimate the cost to the goal based on legal moves
if (allowDiag) {
heuristic_cost = linf_norm(nbrs[i] / w, nbrs[i] % w,
goal / w, goal % w);
}
else {
heuristic_cost = l1_norm(nbrs[i] / w, nbrs[i] % w,
goal / w, goal % w);
}
// paths with lower expected cost are explored first
float priority = new_cost + heuristic_cost;
nodes_to_visit.push(Node(nbrs[i], priority));
costs[nbrs[i]] = new_cost;
paths[nbrs[i]] = cur.idx;
}
}
}
std::cout << "\n";
}
delete[] costs;
delete[] nbrs;
//return solution_found;
}
};
int main() {
Astar astarPathfinding;
float* weights;
int h;
int w;
int start;
int goal;
bool diag_ok;
int* paths;
astarPathfinding.setVariables(weights, h, w, start, goal, diag_ok, paths);
astarPathfinding.start(); // error
return 0;
}
You have "start" as member and "start" as function.
Rename one of them will fix your error.
Here is the question:
There is a house with a backyard which is square bounded by
coordinates (0,0) in the southwest to (1000,1000) in
the northeast. In this yard there are a number of water sprinklers
placed to keep the lawn soaked in the middle of the summer. However,
it might or might not be possible to cross the yard without getting
soaked and without leaving the yard?
Input The input starts with a line containing an integer 1≤n≤1000, the
number of water sprinklers. A line follows for each sprinkler,
containing three integers: the (x,y)(x,y) location of the sprinkler
(0≤x,y,≤10000) and its range r (1≤r≤1000). The sprinklers will soak
anybody passing strictly within the range of the sprinkler (i.e.,
within distance strictly less than r).
The house is located on the west side (x=0) and a path is needed to
the east side of the yard (x=1000).
Output If you can find a path through the yard, output four real
numbers, separated by spaces, rounded to two digits after the decimal
place. These should be the coordinates at which you may enter and
leave the yard, respectively. If you can enter and leave at several
places, give the results with the highest y. If there is no way to get
through the yard without getting soaked, print a line containing
“IMPOSSIBLE”.
Sample Input
3
500 500 499
0 0 999
1000 1000 200
Sample output
0.00 1000.00 1000.00 800.00
Here is my thought process:
Define circle objects with x,y,r and write a function to determine if a given point is wet or not(inside the circle or not) on the circumference is not wet btw.
class circle {
int h;
int k;
int r;
public:
circle();
circle(int h, int k, int r){
this->h = h;
this->k = k;
this->r = r;
};
bool iswet(pair<int,int>* p){
if (pow(this->r - 0.001, 2) > (pow(p->first - this->h, 2) +
pow(p->second - this->k, 2) ) ) {
return true;
}
else
return false;
};
Then implement a depth first search, prioritizing to go up and right whenever possible.
However since circles are not guaranteed to be pass on integer coordinates an the result is expected in floats with double precision (xxx.xx). So if we keep everything in integers the grid suddenly becomes 100,000 x 100,000 which is way too big. Also the time limit is 1 sec.
So I thought ok lets stick to 1000x1000 and work with floats instead. Loop over int coordinates and whenever I hit a sprinkle just snap in the perimeter of the circle since we are safe in the perimeter. But in that case could not figure out how DFS work.
Here is the latest trial
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <utility>
#include <unordered_set>
#include <iomanip>
using namespace std;
const int MAXY = 1e3;
const int MAXX = 1e3;
const int MINY = 0;
const int MINX = 0;
struct pair_hash {
inline std::size_t operator()(const std::pair<int,int> & v) const {
return v.first*31+v.second;
}
};
class circle {
int h;
int k;
int r;
public:
circle();
circle(int h, int k, int r){
this->h = h;
this->k = k;
this->r = r;
};
bool iswet(pair<float,float>* p){
if (pow(this->r - 0.001, 2) > (pow(p->first - this->h, 2) + pow(p->second - this->k, 2) ) ) {
this->closest_pair(p);
return true;
}
else
return false;
};
void closest_pair(pair<float,float>* p){
float vx = p->first - this->h;
float vy = p->second - this->k;
float magv = sqrt(vx * vx + vy * vy);
p->first = this->h + vx / magv * this->r;
p->second = this->k + vy / magv * this->r;
}
};
static bool test_sprinkles(vector<circle> &sprinkles, pair<float,float>* p){
for (int k = 0; k < sprinkles.size(); k++)
if (sprinkles[k].iswet(p)) return false;
return true;
}
int main(){
int n; // number of sprinkles
while (cin >> n){
vector<circle> sprinkles_array;
sprinkles_array.reserve(n);
int h, k, r;
while (n--){
cin >> h >> k >> r;
sprinkles_array.push_back(circle(h, k, r));
}/* code */
pair<float,float> enter = make_pair(0, MAXY);
deque<pair<float,float>> mystack;
mystack.push_back(enter);
pair<float,float>* cp;
bool found = false;
unordered_set<pair<float, float>, pair_hash> visited;
while (!mystack.empty()){
cp = &mystack.back();
if (cp->first == MAXX) {
found = true;
break;
}
visited.insert(*cp);
if (cp->second > MAXY || cp->second < MINY || cp ->first < MINX ) {
visited.insert(*cp);
mystack.pop_back();
continue;
}
if (!test_sprinkles(sprinkles_array,cp)) {
continue;
}
pair<int,int> newpair = make_pair(cp->first, cp->second + 1);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
newpair = make_pair(cp->first + 1 , cp->second);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
newpair = make_pair(cp->first, cp->second - 1);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
newpair = make_pair(cp->first - 1, cp->second);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
mystack.pop_back();
}
cout << setprecision(2);
cout << fixed;
if (found){
double xin = mystack.front().first;
double yin = mystack.front().second;
pair <float, float> p = mystack.back();
p.second++;
for (int k = 0; k < sprinkles_array.size(); k++)
if (sprinkles_array[k].iswet(&p)) break;
double xout = p.first;
double yout = p.second;
cout << xin << " " << yin << " " << xout << " " << yout << endl;
}
else
{
cout << "IMPOSSIBLE" << endl;
}
}
}
Yes #JosephIreland is right. Solved it with grouping intersecting (not touching) circles. Then these groups have maxy and min y coordinates. If it exceeds the yard miny and maxy the way is blocked.
Then these groups also have upper and lower intersection points with x=0 and x=1000 lines. If the upper points are larger than the yard maxy then the maximum entry/exit points are lower entery points.
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include <iomanip>
using namespace std;
const int MAXY = 1e3;
const int MAXX = 1e3;
const int MINY = 0;
const int MINX = 0;
struct circle {
int h;
int k;
int r;
float maxy;
float miny;
circle();
circle(int h, int k, int r){
this->h = h;
this->k = k;
this->r = r;
this->miny = this->k - r;
this->maxy = this->k + r;
};
};
struct group {
float maxy = -1;
float miny = -1;
vector<circle*> circles;
float upper_endy = -1;
float upper_starty = -1;
float lower_endy = -1;
float lower_starty = -1;
void add_circle(circle& c){
if ((c.maxy > this->maxy) || this->circles.empty() ) this->maxy = c.maxy;
if ((c.miny < this->miny) || this->circles.empty() ) this->miny = c.miny;
this->circles.push_back(&c);
// find where it crosses x=minx and x= maxx
float root = sqrt(pow(c.r, 2) - pow(MINX - c.h, 2));
float y1 = root + c.k;
float y2 = -root + c.k;
if (y1 > this->upper_starty) this->upper_starty = y1;
if (y2 > this->lower_starty) this->lower_starty = y2;
root = sqrt(pow(c.r, 2) - pow(MAXX - c.h, 2));
y1 = root + c.k;
y2 = -root + c.k;
if (y1 > this->upper_endy) this->upper_endy = y1;
if (y2 > this->lower_endy) this->lower_endy = y2;
};
bool does_intersect(circle& c1){
for(circle* c2 : circles){
float dist = sqrt(pow(c1.h - c2->h,2)) + sqrt(pow(c1.k - c2->k,2));
(dist < (c1.r + c2->r)) ? true : false;
};
};
};
int main(){
int n; // number of sprinkles
while (cin >> n){
vector<circle> sprinkles_array;
sprinkles_array.reserve(n);
int h, k, r;
while (n--){
cin >> h >> k >> r;
sprinkles_array.push_back(circle(h, k, r));
}/* code */
vector<group> groups;
group newgroup;
newgroup.add_circle(sprinkles_array[0]);
groups.push_back(newgroup);
for (int i = 1; i < sprinkles_array.size(); i++){
bool no_group = true;
for (group g:groups){
if (g.does_intersect(sprinkles_array[i])){
g.add_circle(sprinkles_array[i]);
no_group = false;
break;
}
}
if (no_group) {
group newgroup;
newgroup.add_circle(sprinkles_array[i]);
groups.push_back(newgroup);
}
}
float entery = MAXY;
float exity = MAXY;
bool found = true;
for (group g : groups){
if ((g.miny < MINY) && (g.maxy > MAXY)){
found = false;
break;
}
if (g.upper_starty > entery)
entery = g.lower_starty;
if (g.upper_endy > exity)
exity = g.lower_endy;
}
cout << setprecision(2);
cout << fixed;
if (found){
cout << float(MINX) << " " << entery << " " << float(MAXX) << " " << exity << endl;
}
else
{
cout << "IMPOSSIBLE" << endl;
}
}
}