From c1e9e2e83f266425158e9a1b766d9145a3078417 Mon Sep 17 00:00:00 2001 From: polinalex000 <60269227+polinalex000@users.noreply.github.com> Date: Mon, 25 May 2020 20:14:57 +0300 Subject: [PATCH] Project done --- .DS_Store | Bin 0 -> 12292 bytes Makefile | 30 +++++++++++++ headers/common.h | 86 ------------------------------------- headers/figure3d.h | 27 ++++++++++++ headers/point3d.h | 26 ++++++++++++ headers/quaternion.h | 24 +++++++++++ src/figure3d.cpp | 39 +++++++++++++++++ src/point3d.cpp | 85 +++++++++++++++++++++++++++++++++++++ src/quaternion.cpp | 46 ++++++++++++++++++++ tests/main.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 375 insertions(+), 86 deletions(-) create mode 100644 .DS_Store create mode 100644 Makefile delete mode 100644 headers/common.h create mode 100644 headers/figure3d.h create mode 100644 headers/point3d.h create mode 100644 headers/quaternion.h create mode 100644 src/figure3d.cpp create mode 100644 src/point3d.cpp create mode 100644 src/quaternion.cpp create mode 100644 tests/main.cpp diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..15a6332bf9eb44592a568098545ab562ce7fc8d7 GIT binary patch literal 12292 zcmeHNO>h)N6n-y1WI7NsAdn2Ou#y4-1_((YMETid0}_6Oaubs9W0>6;$dsFzurs?0 z#8}ZnPl6>U#fz2)3#jsh2QR1xEyXJF5KFMigI+vZT3Y4F@^$xY5;kCYh!z#PtGZwJ zd;O-T-}dzTUiSh3c4V#10QCT%QRY;i2T)cC5S>enDT&K@o|a09gOo`RsICK~(ta+U zOnb>`eHBAlKw047vOo#F4*!13D3^i{nW^7z$>rp5+VO+N#yeP2T2?-%LSt;MvA1jA z{sCRj`u4MS+6NX<++D5cFwW$y(ur99db#sAZ4agS?X-Jr_%}N zyzTb|_St~fj{06Eh>MPW4(W2cDX zSL+KFGIrFlY&URDId-Ne?^wZLzv-uJ*K*v`y*bBsl4-l!HHYj4*udEMlA78oW2v#c zASzbT^g69Cn{>`(o#31pW5r5?9k=Ms4|*0K#nM02n2^-1G>l_h63^IFTADVl&#$gx z^~QRpn_9O|Gm)GPY!lOc*8RNWT7qLVu@+6YSWnta+G)vZWo??ipY`VCbR}~k+o7?( zls7a)lk~-~yJCj%93S?8=?8~~ZI@o@3mUtsrgljuy;47ywObZ{A+0XPw{=Rw26eGU z+0v1=a|0S+C+vZvkOCL-@ETl%OK=6=gAd>a+=S2JEBG32!#8jjeuSUlSNIKnhdZzG8BE}DJb?pv5>KIr!+0(v2{?vAq1Cm z2q6;HDGm_4Xh>rr9g|e3l8#U%Dpk2pl5(L={Ak#Yg>+0(sSYUB0mG3oj8IUj14c!6 zz?h_}R2EPcm~MeN#G1tZGYK$e5c}VqCjtLsix#h_tKZPnx;-`li;K|kR7@^FxJ20k zeHYNRfW!B|dL9}WOP8@o4}o<1Y;j;v2pIGV9!O~82BGapG_pz~K&pq$)seLtMF)C` zc-Ff05vG??ARwX+W8)?k(aQ<*YeL%G!kAu0L4lNRYa{6#g8%YSY#G}{auCC?)sZ;U zbbJt)e;|~97p}oa@EP192>&ho06)Pm@F&6dGMrEFy%v|@a*W^_T#M^)JvQJL+!_M; zPTYfgv5UZb0(-C*`>-FAXc3e@je~fGpnMi{n8z`E3122qe-SScsDA@5500TJVNp0fW9d1xq<1pc19>u=ty0T_tG!!#}x7nEPX|JpB1@c>1>VPY3m6=eZs0c8PY z0c8PYftj#CIX$H4qG7g%Uq#bYA(*=Ae0Z-qr+=0+eE+A8=hX2W-0yg8o?P@y8cju$d<6;HhI|7L<0qwZX9Oj4mnZK?LZ{Ru!_&vEm^KVHu%|3CS6&slsg F{5K$__!0mB literal 0 HcmV?d00001 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4118343 --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +# source, object and header files +SRC := $(wildcard src/*.cpp) +OBJ := $(SRC:src/%.cpp=obj/%.o) +HEADER := $(wildcard headers/*.h) + +# preprocessor flags +CPPFLAGS := -Iheaders + +# compiler flags +CXXFLAGS := -Wall -std=c++17 + +all : main + +main : $(OBJ) obj/main.o + $(CXX) -o $@ $^ $(LDLIBS) + +obj/main.o : tests/main.cpp $(HEADERS) | obj + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< + +obj/%.o : src/%.cpp $(HEADER) | obj + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< + +obj : + mkdir $@ + +clean : + $(RM) -r obj main + +.PHONY : clean all + diff --git a/headers/common.h b/headers/common.h deleted file mode 100644 index 6e79f51..0000000 --- a/headers/common.h +++ /dev/null @@ -1,86 +0,0 @@ -/*** -The MIT License (MIT) -Copyright (c) 2014 Viktor Borodin (borodin@mail.univ.kiev.ua) -21.06.2014 - - * Basic types definitions and functions - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -***/ -#ifndef __COMMON__ -#define __COMMON__ - -#include -#include -#include -#include -#include - -#include - -typedef DType double; /* Double real type for application */ - -typedef IType int; /* Integer type for application */ - -typedef NType unsigned; /* Unsigned type for application */ - -//TODO: v.b.: correct it with limits and float -#define EQ_EPS 0.000001 // epsilon : presision of arithmetics - -#define MAX((a),(b)) (a)<(b)?(a):(b) -#define MIN((a),(b)) (a)>(b)?(a):(b) - -#define PD_EQL((a),(b)) fabs((a)-(b)) < EQ_EPS - - -/* Basic types definitions */ - -/* Point type as vector of two reals */ -typedef struct DPoint_ -{ - union //classical and vector representation - { - struct - { - DType x; - DType y; - }; - DType ptr[2]; - }; -} DPoint; - - -typedef struct DLine_ -{ - DType a; - DType b; - DType c; -} DLine; - - -// real function R^1 -> R^1 -typedef R1R_Finc (*DType)(Dtype); - - -void* memzero(void* ptr, size_t n) -{ - memset(ptr, 0, n); -} - -#endif /* __COMMON__ end */ diff --git a/headers/figure3d.h b/headers/figure3d.h new file mode 100644 index 0000000..3185890 --- /dev/null +++ b/headers/figure3d.h @@ -0,0 +1,27 @@ +#ifndef _FIGURE3D_H_ +#define _FIGURE3D_H_ + + +#include "point3d.h" +#include +#include + +using std::vector; +using std::pair; +typedef pair pii; + +struct Figure3D { + int num_points, num_edges; + vector points; + vector edges; + Figure3D(): num_points(0), num_edges(0) {} + Figure3D(vector points, vector edges): + num_points(points.size()), num_edges(edges.size()), + points(points), edges(edges) {} + void turn3D(Angle3D a, Point3D p); + void project(Point3D p); + friend ostream& operator<<(ostream& os, const Figure3D& f); + friend istream& operator>>(istream& is, Figure3D& f); +}; + +#endif diff --git a/headers/point3d.h b/headers/point3d.h new file mode 100644 index 0000000..85299e5 --- /dev/null +++ b/headers/point3d.h @@ -0,0 +1,26 @@ +#ifndef _POINT3D_H_ +#define _POINT3D_H_ + +#include "quaternion.h" +#include + +typedef std::tuple Angle3D; + +struct Point3D { + double x, y, z; + Point3D from_spherical() const; + Point3D from_cylinder() const; + Point3D to_spherical() const; + Point3D to_cylinder() const; + Point3D operator+(Point3D p2) const; + Point3D operator*(double a) const; + bool operator==(Point3D p2) const; + Point3D turn3D(Quaternion q) const; + Point3D turn3D(Angle3D a, Point3D p) const; + Point3D project(Point3D normal) const; + friend ostream& operator<<(ostream& os, Point3D p); + friend istream& operator>>(istream& is, Point3D& p); +}; + + +#endif diff --git a/headers/quaternion.h b/headers/quaternion.h new file mode 100644 index 0000000..e5ba3ae --- /dev/null +++ b/headers/quaternion.h @@ -0,0 +1,24 @@ +#ifndef _QUATERNION_H_ +#define _QUATERNION_H_ + +#include + +using std::ostream; +using std::istream; + +struct Quaternion { + double s, x, y, z; + Quaternion(): s(0), x(0), y(0), z(0) {} + Quaternion(double s): s(s), x(0), y(0), z(0) {} + Quaternion(double s, double x, double y, double z): + s(s), x(x), y(y), z(z) {} + Quaternion operator+(Quaternion q2) const; + Quaternion operator-(Quaternion q2) const; + Quaternion operator*(Quaternion q2) const; + Quaternion operator/(Quaternion q2) const; + bool operator==(Quaternion q2) const; + friend ostream& operator<<(ostream& os, Quaternion q); + friend istream& operator>>(istream& is, Quaternion& q); +}; + +#endif diff --git a/src/figure3d.cpp b/src/figure3d.cpp new file mode 100644 index 0000000..e360eb1 --- /dev/null +++ b/src/figure3d.cpp @@ -0,0 +1,39 @@ +#include "figure3d.h" +#include + +void Figure3D::turn3D(Angle3D a, Point3D p) { + for (auto& v : points) { + v = v.turn3D(a, p); + } +} + +void Figure3D::project(Point3D normal) { + for (auto& v : points) { + v = v.project(normal); + } +} + +ostream& operator<<(ostream& os, const Figure3D& f) { + os << "Points:\n"; + for (int i = 0; i < (int)f.points.size(); i++) { + os << i << ": " << f.points[i] << '\n'; + } + os << "Edges:\n"; + for (auto& e: f.edges) { + os << e.first << " <-> " << e.second << '\n'; + } + return os; +} + +istream& operator>>(istream& is, Figure3D& f) { + is >> f.num_points >> f.num_edges; + f.points.resize(f.num_points); + f.edges.resize(f.num_edges); + for (int i = 0; i < f.num_points; i++) { + is >> f.points[i]; + } + for (int i = 0; i < f.num_edges; i++) { + is >> f.edges[i].first >> f.edges[i].second; + } + return is; +} diff --git a/src/point3d.cpp b/src/point3d.cpp new file mode 100644 index 0000000..d989b66 --- /dev/null +++ b/src/point3d.cpp @@ -0,0 +1,85 @@ +#include "point3d.h" +#include + +static const double EPS = 1e-6; + +Point3D Point3D::to_spherical() const { + double r = sqrt(x*x + y*y + z*z); + double phi = atan(y/x); + double theta = acos(z/r); + return {r, phi, theta}; +} + +Point3D Point3D::from_spherical() const { + double r = this->x; + double phi = this->y; + double theta = this->z; + double x = r*sin(theta)*cos(phi); + double y = r*sin(theta)*sin(phi); + double z = r*cos(theta); + return {x, y, z}; +} + +Point3D Point3D::from_cylinder() const { + double rho = this->x; + double phi = this->y; + double x = rho*cos(phi); + double y = rho*sin(phi); + return {x, y, z}; +} + +Point3D Point3D::to_cylinder() const { + double rho = sqrt(x*x + y*y); + double phi = 0; + if (x >= 0) phi = asin(y/rho); + if (x < 0) phi = -asin(y/rho) + M_PI; + return {rho, phi, z}; +} + +Point3D Point3D::operator+(Point3D p) const { + return {x + p.x, y + p.y, z + p.z}; +} + +Point3D Point3D::operator*(double a) const { + return {a*x, a*y, a*z}; +} + +Point3D Point3D::turn3D(Quaternion q) const { + Quaternion v = {0, x, y, z}; + Quaternion q_inv = Quaternion(1)/q; + Quaternion r = q*v*q_inv; + return {r.x, r.y, r.z}; +} + +Point3D Point3D::turn3D(Angle3D a, Point3D p) const { + Point3D result = (*this) + p*(-1); + auto [ax, ay, az] = a; + Quaternion qx = {cos(ax/2), sin(ax/2), 0, 0}; + Quaternion qy = {cos(ay/2), 0, sin(ay/2), 0}; + Quaternion qz = {cos(az/2), 0, 0, sin(az/2)}; + result = result.turn3D(qx).turn3D(qy).turn3D(qz); + return result + p; +} + +Point3D Point3D::project(Point3D normal) const { + auto [a, b, c] = normal; + double norm2 = (a*a + b*b + c*c); + double x0 = -(b*(a*y - b*x) + c*(a*z - c*x))/norm2; + double y0 = (a*a*y - a*b*x - b*c*z + c*c*y)/norm2; + double z0 = (a*a*z - a*c*x + b*b*z - b*c*y)/norm2; + return {x0, y0, z0}; +} + +bool Point3D::operator==(Point3D p) const { + return fabs(x - p.x) < EPS && + fabs(y - p.y) < EPS && + fabs(z - p.z) < EPS; +} + +ostream& operator<<(ostream& os, Point3D p) { + return os << "x=" << p.x << " y=" << p.y << " z=" << p.z; +} + +istream& operator>>(istream& is, Point3D& p) { + return is >> p.x >> p.y >> p.z; +} diff --git a/src/quaternion.cpp b/src/quaternion.cpp new file mode 100644 index 0000000..aa75710 --- /dev/null +++ b/src/quaternion.cpp @@ -0,0 +1,46 @@ +#include "quaternion.h" +#include + +static const double EPS = 1e-6; + +Quaternion Quaternion::operator+(Quaternion q2) const { + return {s + q2.s, x + q2.x, y + q2.y, z + q2.z}; +} + +Quaternion Quaternion::operator-(Quaternion q2) const { + return {s - q2.s, x - q2.x, y - q2.y, z - q2.z}; +} + +Quaternion Quaternion::operator*(Quaternion q2) const { + return {s * q2.s - x * q2.x - y * q2.y - z * q2.z, + s * q2.x + q2.s * x + y * q2.z - q2.y * z, + s * q2.y + q2.s * y + q2.x * z - x * q2.z, + s * q2.z + q2.s * z + x * q2.y - q2.x * y}; +} + +Quaternion Quaternion::operator/(Quaternion q2) const { + Quaternion invQ2; + double norm2 = q2.s * q2.s + q2.x * q2.x + q2.y * q2.y + q2.z * q2.z; + double invNorm2 = 1.0 / norm2; + invQ2.s = q2.s * invNorm2; + invQ2.x = -q2.x * invNorm2; + invQ2.y = -q2.y * invNorm2; + invQ2.z = -q2.z * invNorm2; + return (*this * invQ2); +} + +bool Quaternion::operator==(Quaternion q2) const { + return fabs(x - q2.x) < EPS && + fabs(y - q2.y) < EPS && + fabs(z - q2.z) < EPS && + fabs(s - q2.s) < EPS; +} + +ostream& operator<<(ostream& os, Quaternion q) { + return os << q.s << " + " << q.x << "i + " + << q.y << "j + " << q.z << "k"; +} + +istream& operator>>(istream& is, Quaternion& q) { + return is >> q.s >> q.x >> q.y >> q.z; +} diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 0000000..b58a9c7 --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,98 @@ +#include +#include "quaternion.h" +#include "point3d.h" +#include "figure3d.h" + +using namespace std; + +void testQuaternion() { + cerr << "QUATERNIONS:\n"; + Quaternion i = {0, 1, 0, 0}; + Quaternion j = {0, 0, 1, 0}; + Quaternion k = {0, 0, 0, 1}; + int passed = 0; + int total_tests = 6; + + // test 1 + passed += (i*i == Quaternion(-1)); + // test 2 + passed += (i*j*k == Quaternion(-1)); + // test 3 + passed += (i+j-Quaternion(2)*k == Quaternion(0, 1, 1, -2)); + // test 4 + passed += (i*j == k); + // test 5 + passed += (Quaternion(1)/i == Quaternion(-1)*i); + // test 6 + passed += (Quaternion(24)/Quaternion(1, 2, 1, 0) == Quaternion(4, -8, -4, 0)); + + cerr << "PASSED " << passed << " OUT OF " << total_tests << " TESTS\n"; +} + +void testPoint3D() { + cerr << "POINT3D:\n"; + Point3D p1 = {1, 0, 0}; + Point3D p2 = {2, 2, 1}; + Point3D p3 = {3, 4, -5}; + int passed = 0; + int total_tests = 6; + + // test 1 + passed += (p2.to_spherical() == Point3D{3, atan(1), acos(1.0/3)}); + // test 2 + passed += (p3.to_cylinder() == Point3D{5, asin(4.0/5), -5}); + // test 3 + passed += (p1 + p2 == Point3D{3, 2, 1}); + // test 4 + passed += (p2 * 2.0 == Point3D{4, 4, 2}); + // test 5 + passed += (Point3D{0, 0, 1} == p1.from_spherical()); + // test 6 + passed += (p3 == Point3D{5, asin(4.0/5), -5}.from_cylinder()); + + cerr << "PASSED " << passed << " OUT OF " << total_tests << " TESTS\n"; +} + +void testFigure3D() { + cerr << "FIGURE3D:\n"; + Point3D p1 = {0, 0, 0}; + Point3D p2 = {3, 4, 5}; + Point3D p3 = {1, 1, -1}; + int passed = 0; + int total_tests = 6; + Figure3D f1 = { + {p1, p2, p3}, + {{0, 1}, {1, 2}, {0, 2}} + }; + f1.project(Point3D{1, 1, 1}); + + // test 1 + passed += (f1.points[0] == Point3D{0, 0, 0}); + // test 2 + passed += (f1.points[1] == Point3D{-1, 0, 1}); + // test 3 + passed += (f1.points[2] == Point3D{2.0/3, 2.0/3, -4.0/3}); + + f1 = { + {p1, p2, p3}, + {{0, 1}, {1, 2}, {0, 2}} + }; + f1.turn3D({M_PI/2, -M_PI/2, M_PI}, {1, 2, 3}); + + // test 4 + passed += (f1.points[0] == Point3D{-1, -1, 2}); + // test 5 + passed += (f1.points[1] == Point3D{3, 4, 5}); + // test 6 + passed += (f1.points[2] == Point3D{0, -2, 3}); + + cerr << "PASSED " << passed << " OUT OF " << total_tests << " TESTS\n"; +} + +int main(int argc, char **argv) { + testQuaternion(); + testPoint3D(); + testFigure3D(); + return 0; +} +