Blame generator.cpp

e31ea0
e31ea0
#include <cmath></cmath>
e31ea0
#include <iostream></iostream>
e31ea0
e31ea0
#include "generator.h"
e31ea0
e31ea0
1bcd85
void GeneratorRowsZAX::tool_point(Track &track, const TrackPoint &p) const {
1bcd85
    if (!track.points.empty()) {
1bcd85
        TrackPoint &last = track.points.back();
1bcd85
        if ( (last.position - p.position).len() <= precision
1bcd85
          && fabs(last.angle - p.angle) <= precision )
1bcd85
        {
1bcd85
            last.speed = p.speed;
1bcd85
            return;
1bcd85
        }
1bcd85
    }
1bcd85
    
1bcd85
    track.points.push_back(p);
1bcd85
}
1bcd85
e31ea0
void GeneratorRowsZAX::tool_up(Track &track, Real safe_z) const {
e31ea0
    if (track.points.empty()) return;
e31ea0
e31ea0
    const TrackPoint &prev = track.points.back();
e31ea0
    if (prev.position.z == safe_z) return;
e31ea0
    
e31ea0
    TrackPoint p;
e31ea0
    p.position = prev.position;
e31ea0
    p.position.z = safe_z;
e31ea0
    p.angle = prev.angle;
e31ea0
    p.speed = move_speed/60.0;
e31ea0
    
1bcd85
    tool_point(track, p);
e31ea0
}
e31ea0
e31ea0
void GeneratorRowsZAX::tool_feed(Track &track, Real safe_z, Real z1, Real z, Real a, Real x) const {
e31ea0
    TrackPoint p;
e31ea0
    p.position = Vector3(x, 0, safe_z);
e31ea0
    p.angle = a*180.0/M_PI;
e31ea0
    
e31ea0
    if (track.points.empty() || track.points.back().position.z == safe_z) {
e31ea0
        p.speed = move_speed/60.0;
1bcd85
        tool_point(track, p);
e31ea0
e31ea0
        if (safe_z > z1 && z1 > z) {
e31ea0
            p.position.z = z1;
1bcd85
            tool_point(track, p);
e31ea0
        }
e31ea0
    }
e31ea0
e31ea0
    p.position.z = z;
e31ea0
    p.speed = feed_speed/60.0;
1bcd85
    tool_point(track, p);
e31ea0
}
e31ea0
e31ea0
e31ea0
void GeneratorRowsZAX::touch(
e31ea0
    const Collider &collider,
e31ea0
    Track &track,
e31ea0
    Real safe_z, Real z1, Real z0,
b2ca59
    Real a, Real x,
b2ca59
    bool skip_z0 ) const
e31ea0
{
e31ea0
    Vector3 dir(0, sin(a), -cos(a));
e31ea0
    Vector3 pos(x, 0, 0);
e31ea0
e31ea0
    Real z = collider.distance_to_model(pos, dir);
0a0ecd
    if (std::isinf(z))
0a0ecd
        z = std::max(Real(0), z0);
0a0ecd
    
0a0ecd
    z = std::max(-z, z0);
0a0ecd
    if (z > z1 || (skip_z0 && z == z0))
e31ea0
        tool_up(track, safe_z);
0a0ecd
    else
0a0ecd
        tool_feed(track, safe_z, z1, z, a, x);
e31ea0
}
e31ea0
e31ea0
e31ea0
e31ea0
bool GeneratorRowsZAX::generate(const Collider &collider, Track &track) const {
e31ea0
    track.points.clear();
e31ea0
    
e31ea0
    const Real precision = 1e-3;
e31ea0
    
e31ea0
    if (collider.model.triangles.empty()) return false;
e31ea0
e31ea0
    if (step_z != 0 && step_z <= precision) return false;
e31ea0
    if (step_a <= precision) return false;
e31ea0
    if (step_x <= precision) return false;
e31ea0
    if (feed_speed <= precision) return false;
e31ea0
    if (move_speed <= precision) return false;
e31ea0
e31ea0
    std::cout << "GeneratorRowsZAX::generate" << std::endl;
e31ea0
e31ea0
    unsigned long long max_count = 100ull*1024*1024/sizeof(track.points.front());
e31ea0
    
e31ea0
    Real min_x = this->min_x;
e31ea0
    Real max_x = this->max_x;
0a0ecd
    Real min_z = this->min_z;
0a0ecd
    Real max_z = this->max_z;
e31ea0
    Real safe_z = this->safe_z;
e31ea0
e31ea0
    const TriangleList &triangles = collider.model.triangles;
e31ea0
    
e31ea0
    // calc bounds
e31ea0
    Real bx0 = INFINITY, bx1 = -INFINITY, bz1 = 0;
e31ea0
    for(TriangleList::const_iterator i = triangles.begin(); i != triangles.end(); ++i) {
e31ea0
        for(int j = 0; j < 3; ++j) {
e31ea0
            const Vector3 &v = i->vertices[j];
e31ea0
            const Real z = sqrt(v.y*v.y + v.z*v.z);
e31ea0
            bx0 = std::min(bx0, v.x);
e31ea0
            bx1 = std::max(bx1, v.x);
e31ea0
            bz1 = std::max(bz1, z);
e31ea0
        }
e31ea0
    }
e31ea0
e31ea0
    bx0 += collider.tool.get_radius();
e31ea0
    bx1 -= collider.tool.get_radius();
e31ea0
    if (bx1 + precision <= bx0 || bz1 + precision <= 0) {
e31ea0
        std::cout << "GeneratorRowsZAX::generate: zero bound" << std::endl;
e31ea0
        return false;
e31ea0
    }
e31ea0
    
e31ea0
    if (max_x <= min_x) {
e31ea0
        min_x = bx0;
e31ea0
        max_x = bx1;
e31ea0
    } else {
e31ea0
        min_x = std::max(min_x, bx0);
e31ea0
        max_x = std::min(max_x, bx1);
e31ea0
    }
e31ea0
    if (max_x + precision <= min_x) return false;
e31ea0
0a0ecd
    min_z = std::max(min_z, -max_z);
e31ea0
    max_z = std::max(max_z, bz1);
e31ea0
    safe_z = std::max(safe_z, max_z + 1);
e31ea0
    
e31ea0
    int count_z = step_z ? std::max(1, (int)ceil((max_z - min_z)/step_z - precision)) : 1;
e31ea0
    int count_x = std::max(1, (int)ceil((max_x - min_x)/step_x - precision)) + 1;
e31ea0
e31ea0
    bool forward_a = true;
e31ea0
    bool forward_x = true;
0a0ecd
    Real z1 = max_z + precision;
e31ea0
    for(int iz = 0; iz < count_z; ++iz) {
0a0ecd
        Real z0 = count_z <= 1 ? min_z : max_z - (iz+1)*(max_z - min_z)/count_z;
e31ea0
        
e31ea0
        int count_a = 3;
0a0ecd
        if (fabs(z1) > precision)
0a0ecd
            count_a = std::max(count_a, (int)ceil(2*M_PI*fabs(z1)/step_a - precision));
e31ea0
        Real sa = 2*M_PI/count_a;
e31ea0
e31ea0
        int count_aa = 0;
0a0ecd
        if (fabs(z1) > precision)
0a0ecd
            count_aa = (int)ceil(sa*fabs(z1)/step_x - precision);
e31ea0
        
e31ea0
        for(int ia = 0; ia < count_a; ++ia) {
e31ea0
            int iia = forward_a ? ia : count_a - ia - 1;
e31ea0
            Real a = iia*sa;
e31ea0
            
b2ca59
            
b2ca59
            if (feed_in_rotation && ia > 0) {
b2ca59
                for(int iaa = 1; iaa < count_aa; ++iaa) {
b2ca59
                    Real aa = sa - sa*iaa/count_a;
b2ca59
                    aa = forward_a ? a - aa : a + aa;
b2ca59
                    Real x = forward_x ? min_x : max_x;
b2ca59
                    touch(collider, track, safe_z, z1, z0, aa, x, skip_middle_layers);
b2ca59
                    if (track.points.size() >= max_count) break;
b2ca59
                }
e31ea0
            }
e31ea0
            
e31ea0
            for(int ix = 0; ix < count_x; ++ix) {
e31ea0
                int iix = forward_x ? ix : count_x - ix - 1;
e31ea0
                Real x = min_x + iix*(max_x - min_x)/(count_x - 1);
b2ca59
                touch(collider, track, safe_z, z1, z0, a, x, skip_middle_layers);
e31ea0
                if (track.points.size() >= max_count) break;
e31ea0
            }
b2ca59
            
b2ca59
            if (!feed_in_rotation)
b2ca59
                tool_up(track, safe_z);
e31ea0
e31ea0
            forward_x = !forward_x;
e31ea0
            if (track.points.size() >= max_count) break;
e31ea0
            std::cout << "." << std::flush;
e31ea0
        }
e31ea0
e31ea0
        forward_a = !forward_a;
e31ea0
        z1 = z0;
e31ea0
        if (track.points.size() >= max_count) break;
e31ea0
        std::cout << std::endl << std::flush;
e31ea0
    }
e31ea0
e31ea0
    tool_up(track, safe_z);
e31ea0
    
e31ea0
    if (track.points.size() >= max_count) {
e31ea0
        std::cout << "GeneratorRowsZAX::generate: reached memory limit" << std::endl;
e31ea0
        return false;
e31ea0
    }
e31ea0
    
e31ea0
    if (track.points.size() <= 1) {
e31ea0
        std::cout << "GeneratorRowsZAX::generate: generated track is empty" << std::endl;
e31ea0
        return false;
e31ea0
    }
e31ea0
e31ea0
    track.split(1, 0, 0);
e31ea0
    track.calc_length();
e31ea0
    track.split(0, 0.1, 0);
e31ea0
    
e31ea0
    std::cout << "GeneratorRowsZAX::generate: track dureation " << (track.points.back().time/60) << std::endl;
e31ea0
    std::cout << "GeneratorRowsZAX::generate: done" << std::endl;
e31ea0
    return true;
e31ea0
}
e31ea0