// Vorosweep - Copyright (C) 2010-2014 T. Mouton
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <thibaud.mouton@gmail.com>.

#include "generator.h"

using namespace vorosweep;

Convex_generator::Convex_generator ( double *pt, double t0, int nface, double a, double v1, double v2, int index )
{
    apex = basic_type::pcontainer->get();
    apex->set ( pt );
    int id = basic_type::pcontainer->get_index();
    apex->set_index ( id );
    apex->p[2] = t0;
    angle = a;
    v[0] = v1;
    v[1] = v2;
//     xyspeed = 1.0; // default value
    initnf = nf = nface;
    se.resize ( nf );
    sf.resize ( nf );
    state = Convex_generator::NOACTIVE;
}

void Convex_generator::generate ( )
{
    for ( int i = 0; i < nf; i++ )
    {
        se[i] = new SweepEdge ( apex, get_start_time() );
        se[i]->set_init ();
    }

    double asub = 2.0*M_PI / ( double ) nf; // angle subdivision

    dbgprintf ( 2, "nf --> %d, angle subd --> %lf\n", nf, asub );

//     angle = 0.0;
//     v[1] = v[0] = 1.0;;
          
    A = new matrix ( angle, v[0], v[1] );

    for ( int i = 0; i < nf; i++ )
    {
        double t = i* asub;
        
//         printf("t --> %lf\n", t);

        double x = apex->p[0] + cos(A->angle)*(A->v[0]*cos(t)) - sin(A->angle)*(A->v[1]*sin(t));
        double y = apex->p[1] + cos(A->angle)*(A->v[1]*sin(t)) + sin(A->angle)*(A->v[0]*cos(t));
        
//         double x = copysign(1.0, cos(t))*pow( fabs(cos(t)), 1.0/p);
//         double y = copysign(1.0, sin(t))*pow( fabs(sin(t)), 1.0/p);
//         double x = cos(t);
//         double y = sin(t);

//         printf("x y : %lf %lf\n", x, y);

        double plane[3];
        compute_normal_plane(x, y, plane);

        geom::normalize3d ( plane );

        double tangent[3];
        tangent[0] = plane[1];
        tangent[1] = -plane[0];
        tangent[2] = 0.0;

        double dir[3];
        geom::cross_product3d ( tangent, plane, dir );
        geom::normalize3d ( dir );

        dbgprintf ( 2, "plane %d --> %lf %lf %lf\n", i, plane[0], plane[1], plane[2] );
        dbgprintf ( 2, "dir %d --> %lf %lf %lf\n", i, dir[0], dir[1], dir[2] );
        sf[i] = new SweepFacet ( apex, plane, dir, get_start_time() );
        sf[i]->set_pos ( i );
        double xys = sf[i]->compute_squared_speeds ( dir );
        sf[i]->set_xyspeed ( sqrt ( xys ) );
        sf[i]->set_generator ( this );
        /*FrontLine *fl = */
        new FrontLine ( sf[i], se[i], se[ ( i+ ( nf-1 ) ) % nf] );
    }

    for ( int i = 0; i < nf; i++ )
    {
        double dir[3];
//         printf("cross --> %lf %lf %lf /\\ %lf %lf %lf\n", sf[i]->get_plane()[0], sf[i]->get_plane()[1], sf[i]->get_plane()[2], sf[( i+1 ) % nf]->get_plane()[0], sf[( i+1 ) % nf]->get_plane()[1], sf[( i+1 ) % nf]->get_plane()[2] );
        geom::cross_product3d ( sf[ i]->get_plane(), sf[ ( i+1 ) % nf]->get_plane(), dir );
        geom::normalize3d ( dir );
        dbgprintf ( 2, "edge %d dir --> %lf %lf %lf\n", i, dir[0], dir[1], dir[2] );
        se[i]->set_dir ( dir );
    }

    for ( int i = 0; i < nf; i++ )
    {
        SweepFacet *sf = get_sweepfacet ( i );
        SweepEdge *se = get_sweepedge ( i );
        se->update_speeds ( sf );

//         double dir[3] = {0.0, 0.0, 0.0};
//         geom::addvec3d ( dir, sf->get_frontline()->get_initial_sweepedge ( 0 )->get_dir3d(), 0.5 );
//         geom::addvec3d ( dir, sf->get_frontline()->get_initial_sweepedge ( 1 )->get_dir3d(), 0.5 );
//         sf->set_bisect ( dir );

//         printf("dir : %lf %lf\n", dir[0], dir[1]);

//         double x = apex->p[0] + dir[0];
//         double y = apex->p[1] + dir[1];

//         printf("x y : %lf %lf\n", x, y);

//         double normal[2];
//         compute_normal_plane(x, y, normal);
// 
//         double tangent[2];
//         tangent[0] = normal[1];
//         tangent[1] = -normal[0];

//         printf ( "--> %lf %lf %lf : %lf\n", sf->get_bisect() [0], sf->get_bisect() [1], sf->get_bisect() [2], geom::scalar_product2d ( A->m[0], A->m[1], A->m[2], tangent, sf->get_bisect() ) );
    }
//     getchar();
}

void Convex_generator::update_current ( double time )
{
    if ( !is_active() )
        return;
    for ( int i = 0; i < nf; i++ )
    {
        sf[i]->update_current ( time );
        FrontLine *fl = sf[i]->get_frontline();
        fl->update_current ( time );
    }
}
