From da743e0e16f93475da650878c1aaed36cfd3d2a4 Mon Sep 17 00:00:00 2001 From: nedko Date: Tue, 13 Sep 2022 17:54:19 +0300 Subject: [PATCH] Added initial path implementation. Needs stroke width fixing --- .gitignore | 1 + main_path.cpp | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 main_path.cpp diff --git a/.gitignore b/.gitignore index 6c08583..953d70e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ polygon polygon.exe path path.exe +.vscode/* diff --git a/main_path.cpp b/main_path.cpp new file mode 100644 index 0000000..3986b01 --- /dev/null +++ b/main_path.cpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include + +#include + +using namespace std; + +struct Point +{ + double x; + double y; + + Point& operator/=(const double& val) + { + x /= val; + y /= val; + return *this; + } +}; + +Point operator-(const Point& p1, const Point& p2) +{ + return Point{.x = p1.x - p2.x, .y = p1.y - p2.y}; +} + +Point operator+(const Point& p1, const Point& p2) +{ + return Point{.x = p1.x + p2.x, .y = p1.y + p2.y}; +} + +double radians(double degrees) +{ + return degrees * M_PI / 180.0; +} + +double degrees(double radians) +{ + return radians * 180.0 / M_PI; +} + +Point& vec_normalize(Point& vec) +{ + double len = sqrt(vec.x * vec.x + vec.y * vec.y); + vec /= len; + return vec; +} + +double get_angle(Point start, Point end) +{ + double angle; + Point vec; + double dot; + + vec = end - start; + vec_normalize(vec); + + angle = degrees(acos(vec.x)); + + if (vec.y < 0) + { + angle += 180.0; + } + + return angle; +} + +double get_stroke_angle(double prev_angle, double curr_angle) +{ + double angle; + + angle = (curr_angle - prev_angle) / 2 + prev_angle + 90; + + return angle; +} + +pair perform_stroke(double stroke_size, double stroke_angle, Point point) +{ + pair result; + Point add; + + add.x = cos(radians(stroke_angle)) * stroke_size / 2; + add.y = sin(radians(stroke_angle)) * stroke_size / 2; + + result.first = point + add; + result.second = point - add; + + return result; +} + +void usage(const string& name) +{ + cout << "Usage: " << name << " [ ...]" << endl; + cout << "\tstroke size - how big the stroke should be" << endl; + cout << "\tx1 - x coordinate of first point" << endl; + cout << "\ty1 - y coordinate of first point" << endl; +} + +void get_polygon(double stroke_size, const vector& points) +{ + double prev_angle; + double curr_angle; + vector forward; + vector backward; + pair tmp; + + for (int i = 1; i < points.size(); ++i) + { + prev_angle = curr_angle; + curr_angle = get_angle(points[i - 1], points[i]); + + if (1 == i) + { + // First angle is end cap + tmp = perform_stroke(stroke_size, curr_angle + 90, points[i - 1]); + } + else + { + tmp = perform_stroke(stroke_size, get_stroke_angle(prev_angle, curr_angle), points[i - 1]); + } + + forward.push_back(tmp.first); + backward.push_back(tmp.second); + } + + // Last angle is end cap + tmp = perform_stroke(stroke_size, curr_angle + 90, points[points.size() - 1]); + forward.push_back(tmp.first); + backward.push_back(tmp.second); + + for (int i = 0; i < forward.size(); ++i) + { + cout << forward[i].x << "," << forward[i].y << " "; + } + + for (int i = backward.size() - 1; i >= 0; --i) + { + cout << backward[i].x << "," << backward[i].y << " "; + } + + cout << endl; +} + +int main(int argc, char **argv) +{ + double stroke_size; + Point tmp; + vector points; + int last_idx; + + if (argc < 5) + { + usage(argv[0]); + cout << "Insufficient arguments" << endl; + return -1; + } + + stroke_size = stod(argv[1]); + + last_idx = argc; + if (0 != last_idx % 2) + { + --last_idx; + } + + for (int i = 2; i < last_idx; i += 2) + { + tmp.x = stod(argv[i]); + tmp.y = stod(argv[i + 1]); + points.push_back(tmp); + } + + get_polygon(stroke_size, points); + + return 0; +}