/*
 *  triangle.cpp
 *  TriInterx
 *
 *  Created by Chema on 8/9/10.
 *  Copyright 2010 __MyCompanyName__. All rights reserved.
 *
 */

#include <utility>
#include <algorithm>
#include "basicas.h"
#include "segment.h"
#include "triangle.h"

namespace {
    Edge* getEdge(Edge* eg[], const DReal3* a, const DReal3* b) {
        Edge* ret=0;
        unsigned i=0;
        while (i<3 && !(((*eg[i]).vx_[0]==a && (*eg[i]).vx_[1]==b) || ((*eg[i]).vx_[1]==a && (*eg[i]).vx_[0]==b) ) ) {
            i++;
        }
        if(i<3) {
            ret = eg[i];
        }
        return ret;
    }
}



void Triangle::init(Segment* seg, const DReal3* a, const DReal3* b, const DReal3* c, Edge* e0, Edge* e1, Edge* e2, const DReal3* normal,const Color3* rgb) {

    seg_=seg;
    normal_=normal;
    rgb_=rgb;
    
    eg_[0] = e0;
    eg_[1] = e1;
    eg_[2] = e2;

    vx_[0] = a;
    vx_[1] = b;
    vx_[2] = c;
}

void Triangle::reset(Triangle::list& at) {
    std::sort(vx_,vx_+3,ptr_lessLexicoOrderYXZ<dreal,3>);
    aitr_= at.end();
}


bool Triangle::setlevel(dreal level) {
    bool ret = false;

    const DReal3& b = *vx_[0];
    const DReal3& m = *vx_[1];
    const DReal3& t = *vx_[2];
    
    // pathological cases:

    // level does not cut triangle
    if (level>t[1] || level<b[1]) return ret;

    // no area triangle
    DReal3 area = crossProd(DReal3(m-t),DReal3(b-t));
    if ( area.sqrnorm() == 0) return ret;
    dreal pgarea = pgArea( DReal2(b[0],b[1]),DReal2(m[0],m[1]),DReal2(t[0],t[1]) );
    if (pgarea == 0) return ret;    
    
    bool m_right = pgarea >0;
    if(level<=m[1]) {
        const DReal3& l = m_right?t:m;
        const DReal3& r = m_right?m:t;
        (*seg_).init(getEdge(eg_,&l,&b),getEdge(eg_,&r,&b));
    }
    else {
        const DReal3& l = m_right?b:m;
        const DReal3& r = m_right?m:b;
        (*seg_).init(getEdge(eg_,&t,&l),getEdge(eg_,&t,&r));
    }
    return ret=true;
}
