#include #include #include #include #include #include #include #include #include #include #include using namespace std; typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; static const double EPS = 1e-9; static const double PI = acos(-1.0); #define REP(i, n) for (int i = 0; i < (int)(n); i++) #define FOR(i, s, n) for (int i = (s); i < (int)(n); i++) #define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++) #define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++) #define MEMSET(v, h) memset((v), h, sizeof(v)) #include typedef complex Point; typedef vector Polygon; static const double INF = 1e+10; #define CURR(P, i) (P[i]) #define NEXT(P, i) (P[(i + 1) % P.size()]) struct Line : public vector { Line() {;} Line(Point a, Point b) { push_back(a); push_back(b); } }; struct Circle { Point p; double r; Circle() {;} Circle(Point p, double r) : p(p), r(r) {;} }; namespace std { bool operator<(const Point &lhs, const Point &rhs) { return lhs.real() == rhs.real() ? lhs.imag() < rhs.imag() : lhs.real() < rhs.real(); } } inline double cross(const Point &a, const Point &b) { return imag(conj(a) * b); } inline double dot(const Point &a, const Point &b) { return real(conj(a) * b); } inline int ccw(Point a, Point b, Point c) { b -= a; c -= a; if (cross(b, c) > 0) { return 1; } if (cross(b, c) < 0) { return -1; } if (dot(b, c) < 0) { return 2; } if (norm(b) < norm(c)) { return -2; } return 0; } Point projection(const Line &l, const Point &p) { double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]); return l[0] + t * (l[0] - l[1]); } vector crosspointLC(const Line &l, const Circle &c) { vector ret; Point center = projection(l, c.p); double d = abs(center - c.p); double t = sqrt(c.r * c.r - d * d); if (isnan(t)) { return ret; } Point vect = (l[1] - l[0]); vect /= abs(vect); ret.push_back(center - vect * t); if (t > EPS) { ret.push_back(center + vect * t); } return ret; } // valarrayはサイズが同じでないとコピーが上手く働かないので注意。 // Point p; // p = a - b; // といったコードはバグる。 // グローバル変数にも注意。 template struct Vector { vector vect; Vector() {;} explicit Vector(int length) : vect(length) {;} Vector(T x, T y) : vect(2) { vect[0] = x; vect[1] = y; } Vector(T x, T y, T z) : vect(3) { vect[0] = x; vect[1] = y; vect[2] = z; } Vector(T x, T y, T z, T w) : vect(4) { vect[0] = x; vect[1] = y; vect[2] = z; vect[3] = w; } int size() const { return vect.size(); } T operator[](int index) const { assert(index >= 0 && index < size()); return vect[index]; } T &operator[](int index) { assert(index >= 0 && index < size()); return vect[index]; } Vector operator+(const Vector &rhs) const { assert(size() == rhs.size()); Vector ret = *this; for (int i = 0; i < size(); i++) { ret.vect[i] += rhs.vect[i]; } return ret; } Vector operator-(const Vector &rhs) const { assert(size() == rhs.size()); Vector ret = *this; for (int i = 0; i < size(); i++) { ret.vect[i] -= rhs.vect[i]; } return ret; } Vector operator+(const T &rhs) const { Vector ret = *this; for (int i = 0; i < size(); i++) { ret.vect[i] += rhs; } return ret; } Vector operator-(const T &rhs) const { Vector ret = *this; for (int i = 0; i < size(); i++) { ret.vect[i] -= rhs; } return ret; } Vector operator*(const T &rhs) const { Vector ret = *this; for (int i = 0; i < size(); i++) { ret.vect[i] *= rhs; } return ret; } Vector operator/(const T &rhs) const { Vector ret = *this; for (int i = 0; i < size(); i++) { ret.vect[i] /= rhs; } return ret; } Vector operator%(const T &rhs) const { Vector ret = *this; for (int i = 0; i < size(); i++) { ret.vect[i] %= rhs; } return ret; } Vector &operator+=(const Vector &rhs) { return *this = *this + rhs; } Vector &operator-=(const Vector &rhs) { return *this = *this - rhs; } Vector &operator+=(const T &rhs) { return *this = *this + rhs; } Vector &operator-=(const T &rhs) { return *this = *this - rhs; } Vector &operator*=(const T &rhs) { return *this = *this * rhs; } Vector &operator/=(const T &rhs) { return *this = *this / rhs; } Vector &operator%=(const T &rhs) { return *this = *this % rhs; } Vector operator-() const { return *this * -1; } T X() const { assert(size() >= 1); return vect[0]; } T Y() const { assert(size() >= 2); return vect[1]; } T Z() const { assert(size() >= 3); return vect[2]; } T W() const { assert(size() >= 4); return vect[3]; } T &X() { assert(size() >= 1); return vect[0]; } T &Y() { assert(size() >= 2); return vect[1]; } T &Z() { assert(size() >= 3); return vect[2]; } T &W() { assert(size() >= 4); return vect[3]; } T dot(const Vector &rhs) const { assert(size() == rhs.size()); T ret = 0; for (int i = 0; i < size(); i++) { ret += vect[i] * rhs.vect[i]; } return ret; } Vector cross(const Vector &rhs) const { assert(size() == 3); assert(rhs.size() == 3); Vector ret = Vector(3); ret.X() = this->Y() * rhs.Z() - this->Z() * rhs.Y(); ret.Y() = this->Z() * rhs.X() - this->X() * rhs.Z(); ret.Z() = this->X() * rhs.Y() - this->Y() * rhs.X(); return ret; } T norm() const { return dot(*this); } double abs() const { return sqrt(norm()); } Vector &normalize() { return *this/ abs(*this); } void Print() const { for (int i = 0; i < size(); i++) { cout << vect[i] << " "; } cout << endl; } }; template ostream &operator<<(ostream &os, const Vector &rhs) { for (int i = 0; i < rhs.size(); i++) { os << rhs.vect[i] << " "; } os << endl; return os; } template T dot(const Vector &lhs, const Vector &rhs) { return lhs.dot(rhs); } template Vector cross(const Vector &lhs, const Vector &rhs) { return lhs.cross(rhs); } typedef Vector Point3D; inline double Norm(const Point3D &p) { return dot(p, p); } inline double Abs(const Point3D &p) { return sqrt(dot(p, p)); } //=================================================================== void OutputPly(const string &filename, const vector &cloud) { FILE *fp = fopen(filename.c_str(), "w"); if (fp == NULL) { fprintf(stderr, "Can'g open %s\n", filename.c_str()); exit(1); } fprintf(fp, "ply\n"); fprintf(fp, "format ascii 1.0\n"); fprintf(fp, "element vertex %d\n", (int)cloud.size()); fprintf(fp, "property float x\n"); fprintf(fp, "property float y\n"); fprintf(fp, "property float z\n"); fprintf(fp, "property uchar diffuse_red\n"); fprintf(fp, "property uchar diffuse_green\n"); fprintf(fp, "property uchar diffuse_blue\n"); fprintf(fp, "end_header\n"); REP(i, cloud.size() / 2) { fprintf(fp, "%f %f %f 255 0 0\n", cloud[i].X(), cloud[i].Y(), cloud[i].Z()); } FOR(i, cloud.size() / 2, cloud.size()) { fprintf(fp, "%f %f %f 0 255 0\n", cloud[i].X(), cloud[i].Y(), cloud[i].Z()); } fclose(fp); } void GetRing(Point3D &c, Point3D e[3]) { double x, y, z; scanf("%lf %lf %lf", &x, &y, &z); c = Point3D(x, y, z); scanf("%lf %lf %lf", &x, &y, &z); e[0] = Point3D(x, y, z); scanf("%lf %lf %lf", &x, &y, &z); e[1] = Point3D(x, y, z); e[2] = cross(e[0], e[1]); } void Usage(int argc, char *argv[]) { fprintf(stderr, "Usage: OutputFilename"); exit(1); } int main(int argc, char *argv[]) { if (argc < 1) { Usage(argc, argv); } string filename = argv[1]; Point3D c1, c2; Point3D e1[3]; Point3D e2[3]; GetRing(c1, e1); GetRing(c2, e2); vector cloud; for (int i = 0; i < 1000; i++) { double theta = 2 * PI * i / 1000; Point3D p = e1[0] * cos(theta) + e1[1] * sin(theta) + c1; cloud.push_back(p); } for (int i = 0; i < 1000; i++) { double theta = 2 * PI * i / 1000; Point3D p = e2[0] * cos(theta) + e2[1] * sin(theta) + c2; cloud.push_back(p); } OutputPly(filename, cloud); }