mslang.cpp 26.9 KB
Newer Older
1 2 3
#include "Algorithms/Vektor.h"
#include "Algorithms/Quaternion.h"
#include "AppTypes/Tenzor.h"
kraus's avatar
kraus committed
4 5
#include "Physics/Physics.h"

6 7
#include <boost/regex.hpp>

8 9
#include <gsl/gsl_rng.h>

10 11
#include <iostream>
#include <string>
12 13
#include <fstream>
#include <streambuf>
14
#include <cstdlib>
15
#include <cmath>
kraus's avatar
kraus committed
16
#include <tuple>
17 18 19 20 21 22

std::string UDouble("([0-9]+\\.?[0-9]*([Ee][+-]?[0-9]+)?)");
std::string Double("(-?[0-9]+\\.?[0-9]*([Ee][+-]?[0-9]+)?)");
std::string UInt("([0-9]+)");
std::string FCall("([a-z]*)\\((.*)");

kraus's avatar
kraus committed
23 24
typedef std::string::iterator iterator;

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
struct BoundingVolume {
    virtual bool isInside(const Vector_t &X) const = 0;
};

struct BoundingBox: public BoundingVolume {
    Vector_t center_m;
    double width_m;
    double height_m;

    BoundingBox():
        center_m(0.0),
        width_m(0.0),
        height_m(0.0)
    { }

    BoundingBox(const Vector_t &llc,
                const Vector_t &urc):
        center_m(0.5 * (llc + urc)),
        width_m(urc[0] - llc[0]),
        height_m(urc[1] - llc[1])
    { }

    virtual bool isInside(const Vector_t &X) const {
        if (2 * std::abs(X[0] - center_m[0]) <= width_m &&
            2 * std::abs(X[1] - center_m[1]) <= height_m)
            return true;

        return false;
    }

    virtual void writeGnuplot(std::ofstream &out) const {
        std::vector<Vector_t> pts({Vector_t(center_m[0] + 0.5 * width_m, center_m[1] + 0.5 * height_m, 0),
                                   Vector_t(center_m[0] - 0.5 * width_m, center_m[1] + 0.5 * height_m, 0),
                                   Vector_t(center_m[0] - 0.5 * width_m, center_m[1] - 0.5 * height_m, 0),
                                   Vector_t(center_m[0] + 0.5 * width_m, center_m[1] - 0.5 * height_m, 0)});
        unsigned int width = out.precision() + 8;
        for (unsigned int i = 0; i < 5; ++ i) {
            Vector_t & pt = pts[i % 4];

            out << std::setw(width) << pt[0]
                << std::setw(width) << pt[1]
                << std::endl;
        }
        out << std::endl;
    }
};

struct BoundingSphere: public BoundingVolume {
    Vector_t center_m;
    double radiusSqr_m;

    BoundingSphere(const Vector_t &c,
                   double r):
        center_m(c),
        radiusSqr_m(r*r)
    { }

    virtual bool isInside(const Vector_t &X) const {
        if (std::pow(X[0] - center_m[0], 2) +
            std::pow(X[1] - center_m[1], 2) < radiusSqr_m)
            return true;

        return false;
    }

};

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
struct AffineTransformation: public Tenzor<double, 3> {
    AffineTransformation(const Vector_t& row0,
                         const Vector_t& row1):
        Tenzor(row0[0], row0[1], row0[2], row1[0], row1[1], row1[2], 0.0, 0.0, 1.0) {
    }

    AffineTransformation():
        Tenzor(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) { }

    AffineTransformation getInverse() const {
        AffineTransformation Ret;
        double det = (*this)(0, 0) * (*this)(1, 1) - (*this)(1, 0) * (*this)(0, 1);

        Ret(0, 0) = (*this)(1, 1) / det;
        Ret(1, 0) = -(*this)(1, 0) / det;
        Ret(0, 1) = -(*this)(0, 1) / det;
        Ret(1, 1) = (*this)(0, 0) / det;

        Ret(0, 2) = - Ret(0, 0) * (*this)(0, 2) - Ret(0, 1) * (*this)(1, 2);
        Ret(1, 2) = - Ret(1, 0) * (*this)(0, 2) - Ret(1, 1) * (*this)(1, 2);
        Ret(2, 2) = 1.0;

        return Ret;
    }

    Vector_t getOrigin() const {
        return Vector_t(-(*this)(0, 2), -(*this)(1, 2), 0.0);
    }

    double getAngle() const {
        return atan2((*this)(1, 0), (*this)(0, 0));
    }

    Vector_t transformTo(const Vector_t &v) const {
        const Tenzor<double, 3> &A = *static_cast<const Tenzor<double, 3>* >(this);
        Vector_t b(v[0], v[1], 1.0);
128 129 130
        Vector_t w = dot(A, b);

        return Vector_t(w[0], w[1], 0.0);
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    }

    Vector_t transformFrom(const Vector_t &v) const {
        AffineTransformation inv = getInverse();
        return inv.transformTo(v);
    }

    AffineTransformation mult(const AffineTransformation &B) {
        AffineTransformation Ret;
        const Tenzor<double, 3> &A = *static_cast<const Tenzor<double, 3> *>(this);
        const Tenzor<double, 3> &BTenz = *static_cast<const Tenzor<double, 3> *>(&B);
        Tenzor<double, 3> &C = *static_cast<Tenzor<double, 3> *>(&Ret);

        C = dot(A, BTenz);

        return Ret;
    }
};

kraus's avatar
kraus committed
150
struct Base;
kraus's avatar
kraus committed
151

kraus's avatar
kraus committed
152 153
struct Function {
    virtual ~Function() {};
kraus's avatar
kraus committed
154

155
    virtual void print(int indent) = 0;
kraus's avatar
kraus committed
156
    virtual void apply(std::vector<Base*> &bfuncs) = 0;
157 158
};

kraus's avatar
kraus committed
159 160 161
bool parse(iterator &it, const iterator &end, Function* &fun);

struct Base: public Function {
162
    AffineTransformation trafo_m;
163
    BoundingBox bb_m;
kraus's avatar
kraus committed
164 165 166 167
    // std::tuple<unsigned int,
    //            double,
    //            double> repeat_m;
    Base():
168
        trafo_m()
kraus's avatar
kraus committed
169
        // , repeat_m(std::make_tuple(0u, 0.0, 0.0))
kraus's avatar
kraus committed
170 171
    { }

kraus's avatar
kraus committed
172
    virtual Base* clone() = 0;
173
    virtual void writeGnuplot(std::ofstream &out) const = 0;
174
    virtual void computeBoundingBox() = 0;
175
    virtual bool isInside(const Vector_t &R) const = 0;
kraus's avatar
kraus committed
176 177
};

kraus's avatar
kraus committed
178 179 180
struct Rectangle: public Base {
    double width_m;
    double height_m;
181

kraus's avatar
kraus committed
182 183 184 185
    Rectangle():
        Base(),
        width_m(0.0),
        height_m(0.0)
kraus's avatar
kraus committed
186 187
    { }

kraus's avatar
kraus committed
188
    virtual ~Rectangle() { }
kraus's avatar
kraus committed
189

190 191 192
    virtual void print(int indentwidth) {
        std::string indent(indentwidth, ' ');
        std::string indent2(indentwidth + 8, ' ');
kraus's avatar
kraus committed
193
        Vector_t origin = trafo_m.getOrigin();
194
        double angle = trafo_m.getAngle() * Physics::rad2deg;
195
        std::cout << indent << "rectangle, \n"
kraus's avatar
kraus committed
196 197
                  << indent2 << "w: " << width_m << ", \n"
                  << indent2 << "h: " << height_m << ", \n"
kraus's avatar
kraus committed
198
                  << indent2 << "origin: " << origin[0] << ", " << origin[1] << ",\n"
199 200 201 202
                  << indent2 << "angle: " << angle << "\n"
                  << indent2 << trafo_m(0, 0) << "\t" << trafo_m(0, 1) << "\t" << trafo_m(0, 2) << "\n"
                  << indent2 << trafo_m(1, 0) << "\t" << trafo_m(1, 1) << "\t" << trafo_m(1, 2) << "\n"
                  << indent2 << trafo_m(2, 0) << "\t" << trafo_m(2, 1) << "\t" << trafo_m(2, 2) << std::endl;
kraus's avatar
kraus committed
203 204
    }

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
    virtual void computeBoundingBox() {
        std::vector<Vector_t> corners({Vector_t(0.5 * width_m, 0.5 * height_m, 0),
                    Vector_t(-0.5 * width_m, 0.5 * height_m, 0),
                    Vector_t(-0.5 * width_m, -0.5 * height_m, 0),
                    Vector_t(0.5 * width_m, -0.5 * height_m, 0)});

        for (Vector_t &v: corners) {
            v = trafo_m.transformFrom(v);
        }

        Vector_t llc = corners[0], urc = corners[0];
        for (unsigned int i = 1; i < 4; ++ i) {
            if (corners[i][0] < llc[0]) llc[0] = corners[i][0];
            else if (corners[i][0] > urc[0]) urc[0] = corners[i][0];

            if (corners[i][1] < llc[1]) llc[1] = corners[i][1];
            else if (corners[i][1] > urc[1]) urc[1] = corners[i][1];
        }

        bb_m = BoundingBox(llc, urc);
    }

227 228 229 230 231 232 233 234 235 236
    virtual bool isInside(const Vector_t &R) const {
        if (!bb_m.isInside(R)) return false;

        Vector_t X = trafo_m.transformTo(R);
        if (2 * std::abs(X[0]) <= width_m &&
            2 * std::abs(X[1]) <= height_m) return true;

        return false;
    }

237
    virtual void writeGnuplot(std::ofstream &out) const {
kraus's avatar
kraus committed
238 239 240 241
        std::vector<Vector_t> pts({Vector_t(0.5 * width_m, 0.5 * height_m, 0),
                                   Vector_t(-0.5 * width_m, 0.5 * height_m, 0),
                                   Vector_t(-0.5 * width_m, -0.5 * height_m, 0),
                                   Vector_t(0.5 * width_m, -0.5 * height_m, 0)});
242 243 244
        unsigned int width = out.precision() + 8;
        for (unsigned int i = 0; i < 5; ++ i) {
            Vector_t pt = pts[i % 4];
kraus's avatar
kraus committed
245
            pt = trafo_m.transformFrom(pt);
246 247 248 249 250 251

            out << std::setw(width) << pt[0]
                << std::setw(width) << pt[1]
                << std::endl;
        }
        out << std::endl;
252 253

        bb_m.writeGnuplot(out);
254 255
    }

kraus's avatar
kraus committed
256
    virtual void apply(std::vector<Base*> &bfuncs) {
kraus's avatar
kraus committed
257 258 259
        bfuncs.push_back(this->clone());
    }

kraus's avatar
kraus committed
260 261 262 263 264
    virtual Base* clone() {
        Rectangle *rect = new Rectangle;
        rect->width_m = width_m;
        rect->height_m = height_m;
        rect->trafo_m = trafo_m;
kraus's avatar
kraus committed
265 266

        return rect;
267 268 269
    }

    static
kraus's avatar
kraus committed
270
    bool parse_detail(iterator &it, const iterator &end, Function* fun) {
271 272 273 274 275 276
        std::string str(it, end);
        boost::regex argumentList(UDouble + "," + UDouble + "(\\).*)");
        boost::smatch what;

        if (!boost::regex_match(str, what, argumentList)) return false;

kraus's avatar
kraus committed
277 278 279
        Rectangle *rect = static_cast<Rectangle*>(fun);
        rect->width_m = atof(std::string(what[1]).c_str());
        rect->height_m = atof(std::string(what[3]).c_str());
280 281 282 283 284 285 286 287 288 289

        std::string fullMatch = what[0];
        std::string rest = what[5];
        it += (fullMatch.size() - rest.size() + 1);

        return true;

    }
};

kraus's avatar
kraus committed
290 291 292
struct Ellipse: public Base {
    double width_m;
    double height_m;
293

kraus's avatar
kraus committed
294 295 296
    Ellipse():
        width_m(0.0),
        height_m(0.0)
kraus's avatar
kraus committed
297 298
    { }

kraus's avatar
kraus committed
299
    virtual ~Ellipse() { }
kraus's avatar
kraus committed
300

301 302 303
    virtual void print(int indentwidth) {
        std::string indent(indentwidth, ' ');
        std::string indent2(indentwidth + 8, ' ');
kraus's avatar
kraus committed
304
        Vector_t origin = trafo_m.getOrigin();
305
        double angle = trafo_m.getAngle() * Physics::rad2deg;
306
        std::cout << indent << "ellipse, \n"
kraus's avatar
kraus committed
307 308
                  << indent2 << "w: " << width_m << ", \n"
                  << indent2 << "h: " << height_m << ", \n"
kraus's avatar
kraus committed
309
                  << indent2 << "origin: " << origin[0] << ", " << origin[1] << ",\n"
310
                  << indent2 << "angle: " << angle << "\n"
311 312 313
                  << indent2 << std::setw(14) << trafo_m(0, 0) << std::setw(14) << trafo_m(0, 1) << std::setw(14) << trafo_m(0, 2) << "\n"
                  << indent2 << std::setw(14) << trafo_m(1, 0) << std::setw(14) << trafo_m(1, 1) << std::setw(14) << trafo_m(1, 2) << "\n"
                  << indent2 << std::setw(14) << trafo_m(2, 0) << std::setw(14) << trafo_m(2, 1) << std::setw(14) << trafo_m(2, 2)
314
                  << std::endl;
kraus's avatar
kraus committed
315 316
    }

317 318 319 320 321 322 323 324
    virtual void writeGnuplot(std::ofstream &out) const {
        const unsigned int N = 101;
        const double dp = Physics::two_pi / (N - 1);
        const unsigned int colwidth = out.precision() + 8;

        double phi = 0;
        for (unsigned int i = 0; i < N; ++ i, phi += dp) {
            Vector_t pt(0.0);
kraus's avatar
kraus committed
325 326 327
            pt[0] = std::copysign(sqrt(std::pow(height_m * width_m * 0.25, 2) /
                                       (std::pow(height_m * 0.5, 2) +
                                        std::pow(width_m * 0.5 * tan(phi), 2))),
328 329
                                  cos(phi));
            pt[1] = pt[0] * tan(phi);
kraus's avatar
kraus committed
330
            pt = trafo_m.transformFrom(pt);
331 332 333 334 335 336 337

            out << std::setw(colwidth) << pt[0]
                << std::setw(colwidth) << pt[1]
                << std::endl;
        }
        out << std::endl;

338
        bb_m.writeGnuplot(out);
339 340
    }

kraus's avatar
kraus committed
341
    virtual void apply(std::vector<Base*> &bfuncs) {
kraus's avatar
kraus committed
342 343 344
        bfuncs.push_back(this->clone());
    }

kraus's avatar
kraus committed
345 346 347 348 349
    virtual Base* clone() {
        Ellipse *elps = new Ellipse;
        elps->width_m = width_m;
        elps->height_m = height_m;
        elps->trafo_m = trafo_m;
kraus's avatar
kraus committed
350 351

        return elps;
352 353
    }

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
    virtual void computeBoundingBox() {
        Vector_t llc(0.0), urc(0.0);
        const Vector_t e_x(1.0, 0.0, 0.0), e_y(0.0, 1.0, 0.0);
        const Vector_t center = trafo_m.transformFrom(Vector_t(0.0));
        const Vector_t e_xp = trafo_m.transformFrom(e_x) - center;
        const Vector_t e_yp = trafo_m.transformFrom(e_y) - center;
        const double &M11 = e_xp[0];
        const double &M12 = e_yp[0];
        const double &M21 = e_xp[1];
        const double &M22 = e_yp[1];

        double t = atan2(height_m * M12, width_m * M11);
        double halfwidth = 0.5 * (M11 * width_m * cos(t) +
                                  M12 * height_m * sin(t));
        llc[0] = center[0] - std::abs(halfwidth);
        urc[0] = center[0] + std::abs(halfwidth);

        t = atan2(height_m * M22, width_m * M21);

        double halfheight = 0.5 * (M21 * width_m * cos(t) +
                                   M22 * height_m * sin(t));

        llc[1] = center[1] - std::abs(halfheight);
        urc[1] = center[1] + std::abs(halfheight);

        bb_m = BoundingBox(llc, urc);
    }

382 383 384 385 386 387 388 389 390 391
    virtual bool isInside(const Vector_t &R) const {
        if (!bb_m.isInside(R)) return false;

        Vector_t X = trafo_m.transformTo(R);
        if (4 * (std::pow(X[0] / width_m, 2) + std::pow(X[1] / height_m, 2)) <= 1)
            return true;

        return false;
    }

392
    static
kraus's avatar
kraus committed
393
    bool parse_detail(iterator &it, const iterator &end, Function* fun) {
394 395 396 397 398 399
        std::string str(it, end);
        boost::regex argumentList(UDouble + "," + UDouble + "(\\).*)");
        boost::smatch what;

        if (!boost::regex_match(str, what, argumentList)) return false;

kraus's avatar
kraus committed
400 401 402
        Ellipse *elps = static_cast<Ellipse*>(fun);
        elps->width_m = atof(std::string(what[1]).c_str());
        elps->height_m = atof(std::string(what[3]).c_str());
403 404 405 406 407 408 409 410 411

        std::string fullMatch = what[0];
        std::string rest = what[5];
        it += (fullMatch.size() - rest.size() + 1);

        return true;
    }
};

kraus's avatar
kraus committed
412 413 414 415 416
struct Repeat: public Function {
    Function* func_m;
    unsigned int N_m;
    double shiftx_m;
    double shifty_m;
417

kraus's avatar
kraus committed
418 419
    virtual ~Repeat() {
        delete func_m;
kraus's avatar
kraus committed
420 421
    }

422 423 424 425
    virtual void print(int indentwidth) {
        std::string indent(indentwidth, ' ');
        std::string indent2(indentwidth + 8, ' ');
        std::cout << indent << "repeat, " << std::endl;
kraus's avatar
kraus committed
426
        func_m->print(indentwidth + 8);
427
        std::cout << ",\n"
kraus's avatar
kraus committed
428 429 430
                  << indent2 << "N: " << N_m << ", \n"
                  << indent2 << "dx: " << shiftx_m << ", \n"
                  << indent2 << "dy: " << shifty_m;
kraus's avatar
kraus committed
431 432
    }

kraus's avatar
kraus committed
433
    virtual void apply(std::vector<Base*> &bfuncs) {
434 435 436
        AffineTransformation shift(Vector_t(1.0, 0.0, -shiftx_m),
                                   Vector_t(0.0, 1.0, -shifty_m));
        std::cout << shiftx_m << "\t" << shift(0, 2) << std::endl;
437

kraus's avatar
kraus committed
438
        func_m->apply(bfuncs);
kraus's avatar
kraus committed
439 440
        const unsigned int size = bfuncs.size();

441
        AffineTransformation current_shift = shift;
kraus's avatar
kraus committed
442
        for (unsigned int i = 0; i < N_m; ++ i) {
kraus's avatar
kraus committed
443
            for (unsigned int j = 0; j < size; ++ j) {
kraus's avatar
kraus committed
444
                Base *obj = bfuncs[j]->clone();
445
                obj->trafo_m = obj->trafo_m.mult(current_shift);
kraus's avatar
kraus committed
446 447 448
                bfuncs.push_back(obj);
            }

449
            current_shift = current_shift.mult(shift);
kraus's avatar
kraus committed
450
        }
451 452 453
    }

    static
kraus's avatar
kraus committed
454 455 456
    bool parse_detail(iterator &it, const iterator &end, Function* &fun) {
        Repeat *rep = static_cast<Repeat*>(fun);
        if (!parse(it, end, rep->func_m)) return false;
457 458 459 460 461 462 463

        boost::regex argumentList("," + UInt + "," + Double + "," + Double + "\\)(.*)");
        boost::smatch what;

        std::string str(it, end);
        if (!boost::regex_match(str, what, argumentList)) return false;

kraus's avatar
kraus committed
464 465 466
        rep->N_m = atof(std::string(what[1]).c_str());
        rep->shiftx_m = atof(std::string(what[2]).c_str());
        rep->shifty_m = atof(std::string(what[4]).c_str());
467 468 469 470 471 472 473 474 475 476

        std::string fullMatch = what[0];
        std::string rest = what[6];

        it += (fullMatch.size() - rest.size());

        return true;
    }
};

kraus's avatar
kraus committed
477 478 479 480
struct Translate: public Function {
    Function* func_m;
    double shiftx_m;
    double shifty_m;
481

kraus's avatar
kraus committed
482 483
    virtual ~Translate() {
        delete func_m;
kraus's avatar
kraus committed
484 485
    }

486 487 488 489
    virtual void print(int indentwidth) {
        std::string indent(indentwidth, ' ');
        std::string indent2(indentwidth + 8, ' ');
        std::cout << indent << "translate, " << std::endl;
kraus's avatar
kraus committed
490
        func_m->print(indentwidth + 8);
491
        std::cout << ",\n"
kraus's avatar
kraus committed
492 493
                  << indent2 << "dx: " << shiftx_m << ", \n"
                  << indent2 << "dy: " << shifty_m;
kraus's avatar
kraus committed
494 495
    }

kraus's avatar
kraus committed
496
    virtual void apply(std::vector<Base*> &bfuncs) {
497 498 499
        AffineTransformation shift(Vector_t(1.0, 0.0, -shiftx_m),
                                   Vector_t(0.0, 1.0, -shifty_m));

kraus's avatar
kraus committed
500
        func_m->apply(bfuncs);
kraus's avatar
kraus committed
501 502 503
        const unsigned int size = bfuncs.size();

        for (unsigned int j = 0; j < size; ++ j) {
kraus's avatar
kraus committed
504
            Base *obj = bfuncs[j];
505
            obj->trafo_m = obj->trafo_m.mult(shift);
kraus's avatar
kraus committed
506
        }
507 508 509
    }

    static
kraus's avatar
kraus committed
510 511 512
    bool parse_detail(iterator &it, const iterator &end, Function* &fun) {
        Translate *trans = static_cast<Translate*>(fun);
        if (!parse(it, end, trans->func_m)) return false;
513 514 515 516 517 518 519

        boost::regex argumentList("," + Double + "," + Double + "\\)(.*)");
        boost::smatch what;

        std::string str(it, end);
        if (!boost::regex_match(str, what, argumentList)) return false;

kraus's avatar
kraus committed
520 521
        trans->shiftx_m = atof(std::string(what[1]).c_str());
        trans->shifty_m = atof(std::string(what[3]).c_str());
522 523 524 525 526 527 528 529 530 531 532

        std::string fullMatch = what[0];
        std::string rest = what[5];

        it += (fullMatch.size() - rest.size());

        return true;
    }
};


kraus's avatar
kraus committed
533 534 535
struct Rotate: public Function {
    Function* func_m;
    double angle_m;
536

kraus's avatar
kraus committed
537 538
    virtual ~Rotate() {
        delete func_m;
kraus's avatar
kraus committed
539 540
    }

541 542 543 544
    virtual void print(int indentwidth) {
        std::string indent(indentwidth, ' ');
        std::string indent2(indentwidth + 8, ' ');
        std::cout << indent << "rotate, " << std::endl;
kraus's avatar
kraus committed
545
        func_m->print(indentwidth + 8);
546
        std::cout << ",\n"
kraus's avatar
kraus committed
547
                  << indent2 << "angle: " << angle_m;
kraus's avatar
kraus committed
548 549
    }

kraus's avatar
kraus committed
550
    virtual void apply(std::vector<Base*> &bfuncs) {
551 552 553
        AffineTransformation rotation(Vector_t(cos(angle_m), sin(angle_m), 0.0),
                                      Vector_t(-sin(angle_m), cos(angle_m), 0.0));

kraus's avatar
kraus committed
554
        func_m->apply(bfuncs);
kraus's avatar
kraus committed
555 556 557
        const unsigned int size = bfuncs.size();

        for (unsigned int j = 0; j < size; ++ j) {
kraus's avatar
kraus committed
558
            Base *obj = bfuncs[j];
559
            obj->trafo_m = obj->trafo_m.mult(rotation);
kraus's avatar
kraus committed
560
        }
561 562 563
    }

    static
kraus's avatar
kraus committed
564 565 566
    bool parse_detail(iterator &it, const iterator &end, Function* &fun) {
        Rotate *rot = static_cast<Rotate*>(fun);
        if (!parse(it, end, rot->func_m)) return false;
567

kraus's avatar
kraus committed
568
        boost::regex argumentList("," + Double + "\\)(.*)");
569 570 571 572 573
        boost::smatch what;

        std::string str(it, end);
        if (!boost::regex_match(str, what, argumentList)) return false;

kraus's avatar
kraus committed
574
        rot->angle_m = atof(std::string(what[1]).c_str());
575 576 577 578 579 580 581 582 583 584

        std::string fullMatch = what[0];
        std::string rest = what[3];

        it += (fullMatch.size() - rest.size());

        return true;
    }
};

kraus's avatar
kraus committed
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
struct Shear: public Function {
    Function* func_m;
    double angleX_m;
    double angleY_m;

    virtual ~Shear() {
        delete func_m;
    }

    virtual void print(int indentwidth) {
        std::string indent(indentwidth, ' ');
        std::string indent2(indentwidth + 8, ' ');
        std::cout << indent << "shear, " << std::endl;
        func_m->print(indentwidth + 8);
        if (std::abs(angleX_m) > 0.0) {
            std::cout << ",\n"
                      << indent2 << "angle X: " << angleX_m;
        } else {
            std::cout << ",\n"
                      << indent2 << "angle Y: " << angleY_m;
        }
    }

    virtual void apply(std::vector<Base*> &bfuncs) {
        AffineTransformation shear(Vector_t(1.0, tan(angleX_m), 0.0),
                                   Vector_t(-tan(angleY_m), 1.0, 0.0));

        func_m->apply(bfuncs);
        const unsigned int size = bfuncs.size();

        for (unsigned int j = 0; j < size; ++ j) {
            Base *obj = bfuncs[j];
            obj->trafo_m = obj->trafo_m.mult(shear);
        }
    }

    static
    bool parse_detail(iterator &it, const iterator &end, Function* &fun) {
        Shear *shr = static_cast<Shear*>(fun);
        if (!parse(it, end, shr->func_m)) return false;

        boost::regex argumentList("," + Double + "," + Double + "\\)(.*)");
        boost::smatch what;

        std::string str(it, end);
        if (!boost::regex_match(str, what, argumentList)) return false;

        shr->angleX_m = atof(std::string(what[1]).c_str());
        shr->angleY_m = atof(std::string(what[3]).c_str());

        if (std::abs(shr->angleX_m) > 0.0 && std::abs(shr->angleY_m) > 0.0)
            return false;

        std::string fullMatch = what[0];
        std::string rest = what[5];

        it += (fullMatch.size() - rest.size());

        return true;
    }
};

kraus's avatar
kraus committed
647 648
struct Union: public Function {
    std::vector<Function*> funcs_m;
649

kraus's avatar
kraus committed
650 651
    virtual ~Union () {
        for (Function* func: funcs_m) {
kraus's avatar
kraus committed
652 653 654 655
            delete func;
        }
    }

656 657 658 659 660 661
    virtual void print(int indentwidth) {
        std::string indent(indentwidth, ' ');
        std::string indent2(indentwidth + 8, ' ');
        std::string indent3(indentwidth + 16, ' ');
        std::cout << indent << "union, " << std::endl;
        std::cout << indent2 << "funcs: {\n";
kraus's avatar
kraus committed
662 663
        funcs_m.front()->print(indentwidth + 16);
        for (unsigned int i = 1; i < funcs_m.size(); ++ i) {
kraus's avatar
kraus committed
664 665
            std::cout << "\n"
                      << indent3 << "," << std::endl;
kraus's avatar
kraus committed
666
            funcs_m[i]->print(indentwidth + 16);
667 668
        }
        std::cout << "\n"
kraus's avatar
kraus committed
669 670 671
                  << indent2 << "} ";
    }

kraus's avatar
kraus committed
672 673 674 675
    virtual void apply(std::vector<Base*> &bfuncs) {
        for (unsigned int i = 0; i < funcs_m.size(); ++ i) {
            std::vector<Base*> children;
            Function *func = funcs_m[i];
676
            func->apply(children);
kraus's avatar
kraus committed
677
            bfuncs.insert(bfuncs.end(), children.begin(), children.end());
kraus's avatar
kraus committed
678
        }
679 680 681
    }

    static
kraus's avatar
kraus committed
682 683 684 685
    bool parse_detail(iterator &it, const iterator &end, Function* &fun) {
        Union *unin = static_cast<Union*>(fun);
        unin->funcs_m.push_back(NULL);
        if (!parse(it, end, unin->funcs_m.back())) return false;
686 687 688 689 690 691 692 693

        boost::regex argumentList("(,[a-z]+\\(.*)");
        boost::regex endParenthesis("\\)(.*)");
        boost::smatch what;

        std::string str(it, end);
        while (boost::regex_match(str, what, argumentList)) {
            iterator it2 = it + 1;
kraus's avatar
kraus committed
694
            unin->funcs_m.push_back(NULL);
695

kraus's avatar
kraus committed
696
            if (!parse(it2, end, unin->funcs_m.back())) return false;
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713

            it = it2;
            str = std::string(it, end);
        }

        str = std::string(it, end);
        if (!boost::regex_match(str, what, endParenthesis)) return false;

        std::string fullMatch = what[0];
        std::string rest = what[1];

        it += (fullMatch.size() - rest.size());

        return true;
    }
};

kraus's avatar
kraus committed
714 715

bool parse(std::string str, Function* &fun) {
716
    str = boost::regex_replace(str, boost::regex("//.*?\\n"), std::string(""), boost::match_default | boost::format_all);
717 718 719 720 721 722 723 724 725 726 727
    str = boost::regex_replace(str, boost::regex("\\s"), std::string(""), boost::match_default | boost::format_all);
    iterator it = str.begin();
    iterator end = str.end();
    if (!parse(it, end, fun)) {
        std::cout << "parsing failed here:" << std::string(it, end) << std::endl;
        return false;
    }

    return true;
}

kraus's avatar
kraus committed
728
bool parse(iterator &it, const iterator &end, Function* &fun) {
729 730 731 732 733 734 735 736 737 738 739
    boost::regex functionCall(FCall);
    boost::smatch what;

    std::string str(it, end);
    if( !boost::regex_match(str , what, functionCall ) ) return false;

    std::string identifier = what[1];
    std::string arguments = what[2];
    unsigned int shift = identifier.size() + 1;

    if (identifier == "rectangle") {
kraus's avatar
kraus committed
740
        fun = new Rectangle;
kraus's avatar
kraus committed
741 742
        /*iterator it2 = */it += shift;
        if (!Rectangle::parse_detail(it, end, fun)) return false;
743

kraus's avatar
kraus committed
744
        // it = it2;
745 746
        return true;
    } else if (identifier == "ellipse") {
kraus's avatar
kraus committed
747
        fun = new Ellipse;
kraus's avatar
kraus committed
748 749
        /*iterator it2 = */it += shift;
        if (!Ellipse::parse_detail(it, end, fun)) return false;
750

kraus's avatar
kraus committed
751
        // it = it2;
752 753
        return true;
    } else if (identifier == "repeat") {
kraus's avatar
kraus committed
754
        fun = new Repeat;
kraus's avatar
kraus committed
755 756
        /*iterator it2 = */it += shift;
        if (!Repeat::parse_detail(it, end, fun)) return false;
757

kraus's avatar
kraus committed
758
        // it = it2;
759 760 761

        return true;
    } else if (identifier == "rotate") {
kraus's avatar
kraus committed
762
        fun = new Rotate;
kraus's avatar
kraus committed
763 764
        // iterator it2 =
            it += shift;
kraus's avatar
kraus committed
765
        if (!Rotate::parse_detail(it, end, fun)) return false;
766

kraus's avatar
kraus committed
767
        // // it = it2;
768 769 770

        return true;
    } else if (identifier == "translate") {
kraus's avatar
kraus committed
771
        fun = new Translate;
kraus's avatar
kraus committed
772 773
        /*iterator it2 = */it += shift;
        if (!Translate::parse_detail(it, end, fun)) return false;
774

kraus's avatar
kraus committed
775 776 777 778 779 780 781 782 783
        // it = it2;

        return true;
    } else if (identifier == "shear") {
        fun = new Shear;
        /*iterator it2 = */it += shift;
        if (!Shear::parse_detail(it, end, fun)) return false;

        // it = it2;
784 785 786

        return true;
    } else if (identifier == "union") {
kraus's avatar
kraus committed
787
        fun = new Union;
kraus's avatar
kraus committed
788 789
        /*iterator it2 = */it += shift;
        if (!Union::parse_detail(it, end, fun)) return false;
790

kraus's avatar
kraus committed
791
        // it = it2;
792 793 794 795 796 797 798 799 800

        return true;
    }


    return (it == end);

}

801
int main(int argc, char *argv[])
802
{
803 804 805 806
    if (argc < 2) {
        std::cout << "please provide the name of the file that contains your code" << std::endl;
        return 1;
    }
kraus's avatar
kraus committed
807
    Function *fun;
808 809 810 811 812 813

    std::ifstream t(argv[1]);
    std::string str((std::istreambuf_iterator<char>(t)),
                    std::istreambuf_iterator<char>());

    // std::string str("repeat( translate(union(rectangle(0.1, 0.1), ellipse(0.1, 0.1)), -0.01, -0.02), 2, 0.1, 0.2)");
814 815 816

    if (parse(str, fun)) {
        fun->print(0);
kraus's avatar
kraus committed
817 818
        std::cout << "\n" << std::endl;

kraus's avatar
kraus committed
819
        std::vector<Base*> baseBlocks;
kraus's avatar
kraus committed
820 821
        fun->apply(baseBlocks);

822
        std::ofstream out("test.gpl");
kraus's avatar
kraus committed
823
        for (Base* bfun: baseBlocks) {
kraus's avatar
kraus committed
824
            bfun->print(0);
825
            bfun->computeBoundingBox();
kraus's avatar
kraus committed
826
            std::cout << std::endl;
827
            bfun->writeGnuplot(out);
kraus's avatar
kraus committed
828
        }
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
        out.close();

        out.open("particles.gpl");
        if (baseBlocks.size() > 0) {
            Vector_t llc, urc;
            Base* first = baseBlocks.front();
            const BoundingBox &bb = first->bb_m;
            llc = Vector_t(bb.center_m[0] - 0.5 * bb.width_m,
                           bb.center_m[1] - 0.5 * bb.height_m,
                           0.0);
            urc = Vector_t(bb.center_m[0] + 0.5 * bb.width_m,
                           bb.center_m[1] + 0.5 * bb.height_m,
                           0.0);

            for (unsigned int i = 1; i < baseBlocks.size(); ++ i) {
                const BoundingBox &bb = baseBlocks[i]->bb_m;
                llc[0] = std::min(llc[0], bb.center_m[0] - 0.5 * bb.width_m);
                llc[1] = std::min(llc[1], bb.center_m[1] - 0.5 * bb.height_m);
                urc[0] = std::max(urc[0], bb.center_m[0] + 0.5 * bb.width_m);
                urc[1] = std::max(urc[1], bb.center_m[1] + 0.5 * bb.height_m);
            }

            gsl_rng *rng = gsl_rng_alloc(gsl_rng_default);

            for (unsigned int i = 0; i < 100000; ++ i) {
                Vector_t X(0.0);
                X[0] = llc[0] + (urc[0] - llc[0]) * gsl_rng_uniform(rng);
                X[1] = llc[1] + (urc[1] - llc[1]) * gsl_rng_uniform(rng);

                for (Base* func: baseBlocks) {
                    if (func->isInside(X)) {
                        out << std::setw(14) << X[0]
                            << std::setw(14) << X[1]
                            << std::endl;
                        break;
                    }
                }
            }

            gsl_rng_free(rng);

        }
kraus's avatar
kraus committed
871

kraus's avatar
kraus committed
872
        for (Base* func: baseBlocks) {
kraus's avatar
kraus committed
873 874
            delete func;
        }
875
    }
kraus's avatar
kraus committed
876 877 878

    delete fun;

879 880
    return 0;
}