/*
 *  
 *  $Id: wpoligono.cpp $
 *  Ginkgo CADx Project
 *
 *  Copyright 2008-14 MetaEmotion S.L. All rights reserved.
 *  http://ginkgo-cadx.com
 *
 *  This file is licensed under LGPL v3 license.
 *  See License.txt for details
 *
 *
 */
//#define _GINKGO_TRACE
#include <wx/xml/xml.h>
#include <api/globals.h>
#include <api/icontexto.h>
#include "wpoligono.h"
#include <api/internationalization/internationalization.h>
#include <api/iwidgetsrenderer.h>
#include <api/ievento.h>
#include "main/managers/widgetsmanager.h"


#include <iterator>
#include <vtkgl.h>
#include <api/westilo.h>
#include <cmath>

//region "Implementacion de WPoligonoBuilder"

GNC::GCS::Widgets::WPoligonoBuilder::WPoligonoBuilder(ModoPoligono modo, GNC::GCS::IWidgetsManager* pManager, const GNC::GCS::TriggerButton& buttonMask, GNC::GCS::Widgets::Observadores::IObservadorPoligono* pObservador) : GNC::GCS::Widgets::IWidgetBuilder(pManager, buttonMask), GNC::GCS::Widgets::Notificadores::INotificadorPoligono(pObservador)
{
	m_NumNodos = 0;
	m_MouseDown = false;
	m_Estado = WBS_Ninguno;
	SetRadioNodo(5.0f);
	m_pPoligonoCreado = NULL;
	m_Modo = modo;
}

GNC::GCS::Widgets::WPoligonoBuilder::~WPoligonoBuilder()
{
	m_Vertices.clear();
	if (m_Modo == MP_Lazo) {
		if (m_pPoligonoCreado) {
			NotificarDestruccion(m_pPoligonoCreado);
			m_pManager->EliminarWidget(m_pPoligonoCreado, false);
			m_pPoligonoCreado = NULL;
		}
	}
}

void GNC::GCS::Widgets::WPoligonoBuilder::OnMouseEvents(GNC::GCS::Events::EventoRaton& evento)
{
	if (!m_pManager) {
		return;
	}
	if (m_MouseDown && evento.ButtonUp(m_ButtonMask)) {
		m_MouseDown = false;
		if (m_Estado != WBS_Creando) {
			m_Estado = WBS_Ninguno;
			return;
		}
		m_Estado = WBS_Ninguno;
		m_PosCursor= evento.iP;

		if (m_Modo == MP_Lazo && m_pPoligonoCreado != NULL) {
			NotificarDestruccion(m_pPoligonoCreado);
			m_pManager->EliminarWidget(m_pPoligonoCreado, false);
			m_pPoligonoCreado = NULL;
		}
		if(m_Vertices.size()>2){
			m_pPoligonoCreado = new WPoligono(m_Modo, m_pManager, evento.c->GetRenderer()->GetVID(), m_Vertices, m_RadioNodo, "Polígono");
			m_pManager->InsertarWidget(m_pPoligonoCreado);
			NotificarCreacion(m_pPoligonoCreado);
			m_pManager->LanzarEventoCreacion(m_pPoligonoCreado);
			ConsumirEvento();
		}
		m_Vertices.clear();
		m_pManager->Modificado();

	}
	else if (evento.ButtonDown(m_ButtonMask)) {
		if (m_Estado != WBS_Ninguno) {
			return;
		}

		m_MouseDown = true;
		if (m_Modo == MP_Lazo && m_pPoligonoCreado != NULL) {
			NotificarDestruccion(m_pPoligonoCreado);
			m_pManager->EliminarWidget(m_pPoligonoCreado, false);
			m_pPoligonoCreado = NULL;
		}

		//aviso que han soltado
		m_pManager->Modificado();
		m_Estado = WBS_Creando;
		ConsumirEvento();

	}
	else if (evento.Dragging() && m_MouseDown) {

		if (m_Estado != WBS_Creando) {
			return;
		}

		GTRACE(" ---->"<<(evento.iP - m_PosCursor).Norma2Cuadrado()<<" minimo= " << m_DistanciaMinimaCuadrado);

		if (!m_Vertices.empty() && ((evento.iP - m_PosCursor)/evento.c->RelacionImagenPantalla()).Norma2Cuadrado() < m_DistanciaMinimaCuadrado) {
			return;
		}
		m_PosCursor = evento.iP;
		m_Vertices.push_back(m_PosCursor);
		m_pManager->Modificado();
		ConsumirEvento();
	}
	else if( evento.Moving() ){
		m_PosCursor= evento.iP;
		m_Estado = WBS_Ninguno;
		ConsumirEvento();
	}
}

void GNC::GCS::Widgets::WPoligonoBuilder::OnKeyEvents(GNC::GCS::Events::EventoTeclado& /*evento*/)
{
	GTRACE("GNC::GCS::Widgets::WPoligonoBuilder::OnKeyEvents(wxKeyEvent&)");
}

void GNC::GCS::Widgets::WPoligonoBuilder::Render(GNC::GCS::Contexto3D* /*c*/)
{

	if (m_Estado != WBS_Creando) {
		return;
	}

	glLineWidth(WIDGET_GROSOR_LINEA);
	wColorNormal.Aplicar();

	VerticesPoligono::iterator prev = m_Vertices.begin();
	if (prev != m_Vertices.end()) {
		VerticesPoligono::iterator curr = prev;
		++curr;
		for (; curr != m_Vertices.end(); ++curr) {
			glBegin(GL_LINES);
			glVertex2d((*prev).x, (*prev).y);
			glVertex2d((*curr).x, (*curr).y);
			glEnd();
			prev = curr;
		}
	}


	if (m_Vertices.size() > 2) {
		glEnable(GL_LINE_STIPPLE);
		glColor4f(0.7f, 0.7f, 0.0f, 1.0);
		glLineStipple(3, 0xAAAA);
		glBegin(GL_LINES);
		glVertex2d(m_Vertices.front().x, m_Vertices.front().y);
		glVertex2d(m_Vertices.back().x, m_Vertices.back().y);
		glEnd();
		glDisable(GL_LINE_STIPPLE);
	}


	glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
	glPointSize(m_RadioNodo);
	glBegin(GL_POINTS);
	for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); ++it) {
		glVertex2d((*it).x, (*it).y);
	}
	glEnd();

}

GNC::GCS::Widgets::TipoCursor GNC::GCS::Widgets::WPoligonoBuilder::GetCursor()
{
	return GNC::GCS::Widgets::CUR_CREAR_POLIGONO;
}

//endregion

//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//region "Constructor y destructor"

GNC::GCS::Widgets::WPoligono::WPoligono(GNC::GCS::Widgets::ModoPoligono modo, IWidgetsManager* pManager, unsigned int vid, VerticesPoligono& vertices, float radioNodo, const char* nombre) : GNC::GCS::Widgets::IWidget(pManager, vid, nombre,0,TID_USER_ANNOTATION_WIDGET), GNC::GCS::Widgets::IWidgetSerializable()
{
	m_Vertices = vertices;

	m_RadioNodo = radioNodo;
	m_Modo = modo;
	Recalcular();
	m_MouseDown = false;
	m_PosCursor = m_Centro;
}

GNC::GCS::Widgets::WPoligono::~WPoligono()
{
	if(m_Modo != GNC::GCS::Widgets::MP_Lazo){
		LanzarEventoDestruccion();
	}
}

//endregion

//region "Serializado y desserializado"
GNC::GCS::Widgets::WPoligono::WPoligono(IWidgetsManager* pManager, long vid, wxXmlNode* nodo, float radioNodo): GNC::GCS::Widgets::IWidget(pManager, vid, "Polígono"), GNC::GCS::Widgets::IWidgetSerializable(nodo), m_AreaMetrica(0)
{
	if(nodo->GetName() != wxT("poligono_widget")){
		std::cerr<< "Ha ocurrido un error al desserializar el widget poligono"<<std::endl;
	}

	if(nodo->GetAttribute(wxT("mode"),wxT("normal")) == wxT("lazo")){
		m_Modo = MP_Lazo;
	} else {
		m_Modo = MP_Normal;
	}

	wxXmlNode *child = nodo->GetChildren();
	GNC::GCS::Nodo nodoTmp;
	while (child) {
		nodoTmp = GNC::GCS::Nodo::Deserializar(child);
		GNC::GCS::Vector v(nodoTmp);
		m_Vertices.push_back(v);
		child = child->GetNext();
	}

	m_RadioNodo = radioNodo;
	m_MouseDown = false;
	Recalcular();
	m_PosCursor = m_Centro;
}

wxXmlNode* GNC::GCS::Widgets::WPoligono::Serializar(const std::string& nombreMedico)
{
	wxXmlNode* resultado = new wxXmlNode(NULL,wxXML_ELEMENT_NODE,wxT("poligono_widget"));
	if(m_Modo == MP_Lazo){
		resultado->AddAttribute(wxT("mode"),wxT("lazo"));
	} else {
		resultado->AddAttribute(wxT("mode"),wxT("normal"));
	}

	int i=0;
	for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); ++it) {
		wxXmlNode* nodo = new wxXmlNode(NULL,wxXML_ELEMENT_NODE,wxString::Format(wxT("nodo%d"), (int) i));
		nodo->AddAttribute(new wxXmlProperty(wxT("x"),wxString::Format(wxT("%f"),(*it).x)));
		nodo->AddAttribute(new wxXmlProperty(wxT("y"),wxString::Format(wxT("%f"),(*it).y)));
		resultado->AddChild(nodo);
		i++;
	}
	//metadatos
	SerializarMetadatos(resultado,nombreMedico);
	return resultado;
}
//endregion

void GNC::GCS::Widgets::WPoligono::OnMouseEvents(GNC::GCS::Events::EventoRaton& evento)
{
	if(EstaOculto()){
		return;
	}
	//------------------------------------------------------
	// Leaving
	if (evento.Leaving()){
		Iluminar(false);
	}
	//------------------------------------------------------
	// Entering
	else if (evento.Entering() ) {
		if (m_MouseDown) {
			Iluminar(true);
		}
	}
	//------------------------------------------------------
	// Dragging
	else if (evento.Dragging() && m_MouseDown) {
		Vector delta = evento.iP - m_PosCursor;
		m_PosCursor = evento.iP;

		if (EstaSeleccionado()) {
			for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); ++it) {
				(*it) += delta;
			}

			Recalcular();

			Modificar(true);

			LanzarEventoModificacion();
		}

		ConsumirEvento();

		return;
	}
	//------------------------------------------------------
	// LeftDown
	else if (evento.LeftDown()) {

		if (EventoConsumido() && !evento.m_controlDown) {
			Seleccionar(false);
			return;
		}

		bool dentro = false;

		if (evento.iP.DentroDePoligono2(m_Vertices)) {
			dentro = true;
			if (evento.m_controlDown) { // Inversion de seleccion
				InvertirSeleccion();
			}
			else{
				Seleccionar(true);
			}
		}
		else {
			if (!evento.m_controlDown) {
				Seleccionar(false);
			}
			else {
				ConsumirEvento();
				if (EstaSeleccionado()) {
					m_MouseDown = true;
					m_PosCursor= evento.iP;
				}
			}
		}

		if (dentro) {
			m_MouseDown = true;
			m_PosCursor= evento.iP;
			m_Modificado = true;
			ConsumirEvento();
		}

		return;
	}
	//------------------------------------------------------
	// LeftUP
	else if (evento.LeftUp()) {
		if (m_MouseDown) {
			ActualizarTimestampModificacion();
			m_MouseDown = false;
			ConsumirEvento();
		}
	}
	//------------------------------------------------------
	// Moving
	else if (evento.Moving()) {

		if (EventoConsumido()) {
			Iluminar(false);
			return;
		}

		bool dentro = false;

		m_PosCursor= evento.iP;

		if (evento.iP.DentroDePoligono2(m_Vertices)) {
			Iluminar(true);
			dentro = true;
		}
		else {
			Iluminar(false);
		}
		if (dentro)
		{
			ConsumirEvento();
		}
	}

}

void GNC::GCS::Widgets::WPoligono::OnKeyEvents(GNC::GCS::Events::EventoTeclado& evento)
{
	if (evento.GetKeyCode() == WXK_ESCAPE) {
		Seleccionar(false);
	}
}

bool GNC::GCS::Widgets::WPoligono::HitTest(float x, float y, const GNC::GCS::Vector& u)
{
	GNC::GCS::Vector umbral(u.x * u.x, u.y * u.y);
	GNC::GCS::Vector punto(x, y);

	bool hits = punto.DentroDePoligono2(m_Vertices);

	if (! hits ) {
		punto.Asignar(x - umbral.x, y - umbral.y);
		hits = punto.DentroDePoligono2(m_Vertices);
	}
	if (! hits ) {
		punto.Asignar(x, y - umbral.y);
		hits = punto.DentroDePoligono2(m_Vertices);
	}
	if (! hits ) {
		punto.Asignar(x + umbral.x, y + umbral.y);
		hits = punto.DentroDePoligono2(m_Vertices);
	}
	if (! hits ) {
		punto.Asignar(x + umbral.x, y);
		hits = punto.DentroDePoligono2(m_Vertices);
	}
	if (! hits ) {
		punto.Asignar(x + umbral.x, y - umbral.y);
		hits = punto.DentroDePoligono2(m_Vertices);
	}
	if (! hits ) {
		punto.Asignar(x , y - umbral.y);
		hits = punto.DentroDePoligono2(m_Vertices);
	}
	if (! hits ) {
		punto.Asignar(x - umbral.x, y - umbral.y);
		hits = punto.DentroDePoligono2(m_Vertices);
	}
	if (! hits ) {
		punto.Asignar(x - umbral.x, y);
		hits = punto.DentroDePoligono2(m_Vertices);
	}
	return hits;
}

bool GNC::GCS::Widgets::WPoligono::HitTest(GNC::GCS::Vector* vertices, int numVertices)
{
	bool hits = true;

	for (VerticesPoligono::iterator it = m_Vertices.begin(); hits && it != m_Vertices.end(); ++it) {
		if (!(*it).DentroDePoligono2(vertices, numVertices) ) {
			hits = false;
		}
	}

	return hits;
}

void GNC::GCS::Widgets::WPoligono::Render(GNC::GCS::Contexto3D* c)
{
	if(m_Oculto){
		return;
	}


	GNC::GCS::Vector escala = c->RelacionImagenPantalla();
	glLineWidth(WIDGET_GROSOR_LINEA);

	float fsombrax, fsombray;

	if (m_Seleccionado && m_MouseDown)
	{
		fsombrax = WIDGET_OFFSET_X_SOMBRA_SELECCIONADO * escala.x;
		fsombray = WIDGET_OFFSET_Y_SOMBRA_SELECCIONADO * escala.y;
	}
	else
	{
		fsombrax = WIDGET_OFFSET_X_SOMBRA * escala.x;
		fsombray = WIDGET_OFFSET_Y_SOMBRA * escala.y;
	}

	wColorSombra.Aplicar();
	glBegin(GL_LINE_LOOP);
	for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); ++it) {
		glVertex2d((*it).x + fsombrax, (*it).y - fsombray);
	}
	glEnd();

	glBegin(GL_POINTS);
	for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); ++it) {
		glVertex2d((*it).x + fsombrax, (*it).y - fsombray);
	}
	glEnd();

	// Dibujo el poligono
	wAplicarColor(m_Iluminado, m_MouseDown, m_Seleccionado);
	glBegin(GL_LINE_LOOP);
	for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); ++it) {
		glVertex2d((*it).x, (*it).y);
	}
	glEnd();


	// Dibujo los puntos
	glPointSize(WIDGET_SIZE_PUNTO);
	for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); ++it) {
		glBegin(GL_POINTS);
			glVertex2d((*it).x, (*it).y);
		glEnd();
	}

	m_Modificado = false;
}

void GNC::GCS::Widgets::WPoligono::Seleccionar(bool seleccionado)
{
	if (m_Seleccionado != seleccionado) {
		m_Seleccionado = seleccionado;
		m_Modificado = true;
	}
}

void GNC::GCS::Widgets::WPoligono::Iluminar(bool iluminado)
{
	if (m_Iluminado != iluminado) {
		m_Iluminado = iluminado;
		m_Modificado = true;
	}
}

void GNC::GCS::Widgets::WPoligono::Ocultar(bool oculto){
	if(oculto != m_Oculto){
		m_Oculto = oculto;
		m_Modificado = true;
	}
}

void GNC::GCS::Widgets::WPoligono::Recalcular()
{
	m_Centro = GNC::GCS::Vector::Centroide(m_Vertices);
	m_Perimetro = GNC::GCS::Vector::PerimetroDePoligono(m_Vertices);

}

//endregion
void GNC::GCS::Widgets::WPoligono::InsertarPropiedades(TListaMapasPropiedades &listaMapaPropiedades)
{
	TMapaPropiedades& primerMapa = listaMapaPropiedades.front();
	{
		std::ostringstream ostr;
		ostr <<  m_Centro;
		primerMapa[_Std("Center (I)")] = ostr.str();
	}

	{
		std::stringstream out;
		out << PuntoToStringMundo(m_Centro);
		primerMapa[_Std("Center (M)")] = out.str();
	}

	{
		std::ostringstream ostr;
		ostr <<  m_Vertices.size();
		primerMapa[_Std("Number of Vertex")] = ostr.str();
	}
}

void GNC::GCS::Widgets::WPoligono::OffscreenRender(GNC::GCS::Contexto3D* c)
{
	if(m_Vertices.size() < 2) {
		return;
	}

	//const GNC::GCS::Vector& escala = c->RefRelacionMundoPantallaOffscreen();

	VerticesPoligono Vertices;

	for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); ++it)
	{
		Vertices.push_back( c->Reproyectar(*it) * c->factorReescalado );
	}

	cairo_set_line_width(c->cr, WIDGET_GROSOR_LINEA);

	// Color del cuerpo
	wColorNormal.AplicarCairo(c->cr);

	// Dibujado del cuerpo
	for (VerticesPoligono::iterator it = Vertices.begin(); it != Vertices.end(); ++it) {
		if(it == Vertices.begin()) {
			cairo_move_to(c->cr, (*it).x, (*it).y);
		}
		cairo_line_to(c->cr, (*it).x, (*it).y);
	}
	cairo_line_to(c->cr, Vertices.front().x, Vertices.front().y);
	cairo_stroke(c->cr);
}

float GNC::GCS::Widgets::WPoligono::GetAreaMetrica() const
{
	/*
	{
		const VerticesPoligono& lista = m_Vertices;
		bool simple = true;
		if (lista.size() > 3) {

			std::list<GNC::GCS::Vector>::const_iterator i = lista.begin();
			std::list<GNC::GCS::Vector>::const_iterator j = i; j++;

			std::list<GNC::GCS::Vector>::const_iterator k;
			std::list<GNC::GCS::Vector>::const_iterator l;

			GNC::GCS::Vector inter;
			GNC::GCS::Vector bbox[2][2];

			glPointSize(5.0f);
			glBegin(GL_POINTS);
			glColor3f(1.0f, 0.0f, 0.0f);
			glVertex2f( (*i).x, (*i).y );

			glColor3f(0.0f, 0.0f, 1.0f);
			glVertex2f( (*j).x, (*j).y );

			glEnd();

			const unsigned long nl = lista.size() - 1;
			unsigned long ni = 0;
			unsigned long nj = 0;

			std::cout << "Poligono: numNodos = " << nl << std::endl;

			for (ni = 0; simple && ni < nl; ni++, i++, j++) {

				(*i).IniciarBoundingBox(bbox[0][0],bbox[0][1]);
				(*j).ExtenderBoundingBox(bbox[0][0],bbox[0][1]);

				k = j; k++;

				nj = ni + 2;

				while (k != lista.end()) {
					l = k;
					l++;

					if (l == lista.end()) {
						l = lista.begin();
						if (l == i) {
							break;
						}
					}

					(*k).IniciarBoundingBox(bbox[1][0], bbox[1][1]);
					(*l).ExtenderBoundingBox(bbox[1][0], bbox[1][1]);

					GNC::GCS::Vector::IntersectarBoundingBox(bbox[0], bbox[1], bbox[1]);

					if ( GNC::GCS::Vector::BoundingBoxValido(bbox[1]) ) {
						std::cout << "Intersección: [ " << ni << ", " << ni + 1 << " ] x [" << nj << ", ";
						if (nj == nl) {
							std::cout << "0 ]" << std::endl;
						}
						else {
							std::cout << nj + 1 << " ]" << std::endl;
						}

						inter = GNC::GCS::Vector::InterseccionEntreRectas(*i, *j, *k, *l);

						//if ( inter.DistanciaARecta(*i, *j) < GNC::GCS::Vector::EpsilonDeComponentes() && inter.DistanciaARecta(*k, *l) < inter.DistanciaARecta(*k, *l) ) {
						if (
							(inter.x + 1e-13) >= bbox[1][0].x &&
							(inter.x - 1e-13) <= bbox[1][1].x && 
							(inter.y + 1e-13) >= bbox[1][0].y &&
							(inter.y - 1e-13) <= bbox[1][1].y
						) {

						//if (inter.DentroDeBoundingBoxCerradoConUmbral(bbox[1][0], bbox[1][1]) ) {
							//simple = false;

							glColor3f(0.0f, 0.0f, 1.0f);
							glLineWidth(1.0f);
							glBegin(GL_LINE_LOOP);
							glVertex2f(bbox[1][0].x, bbox[1][0].y);
							glVertex2f(bbox[1][1].x, bbox[1][0].y);
							glVertex2f(bbox[1][1].x, bbox[1][1].y);
							glVertex2f(bbox[1][0].x, bbox[1][1].y);
							glEnd();

							glColor3f(1.0f, 1.0f, 1.0f);
							glBegin(GL_LINES);
							glVertex2f((*i).x, (*i).y);
							glVertex2f((*j).x, (*j).y);
							glEnd();

							glBegin(GL_POINTS);
							glPointSize(2.0f);
							glColor3f(1.0f, 0.0f, 1.0f);
							glVertex2f(inter.x, inter.y);
							glEnd();

						}
						else {
							GNC::GCS::Vector diff1 = inter - bbox[1][0];
							GNC::GCS::Vector diff2 = bbox[1][1] - inter;
							*/
							/*

							std::cout << "Diff1,2: " << diff1 << ", " << diff2 << std::endl;

							double diff3 = inter.DistanciaARecta(*i, *j);
							double diff4 = inter.DistanciaARecta(*k, *l);

							std::cout << "Diff2,3" << diff3 << ", " << diff4 << std::endl;

							GNC::GCS::Vector inter2 = GNC::GCS::Vector::InterseccionEntreRectas(*i, *j, *k, *l);

							std::cout << inter2 << std::endl;
							
							glColor3f(0.0f, 0.0f, 0.5f);
							glLineWidth(1.0f);
							glBegin(GL_LINE_LOOP);
							glVertex2f(bbox[1][0].x, bbox[1][0].y);
							glVertex2f(bbox[1][1].x, bbox[1][0].y);
							glVertex2f(bbox[1][1].x, bbox[1][1].y);
							glVertex2f(bbox[1][0].x, bbox[1][1].y);
							glEnd();

							glColor3f(1.0f, 0.0f, 0.0f);
							glBegin(GL_LINES);
							glVertex2f((*i).x, (*i).y);
							glVertex2f((*j).x, (*j).y);
							glEnd();

							glBegin(GL_POINTS);
							glPointSize(2.0f);
							glColor3f(0.5f, 0.5f, 0.5f);
							glVertex2f(inter.x, inter.y);
							glEnd();
							*/
							/*
						}
					}
					k++;
					nj++;
				}
				*/
				/*
				for (unsigned long nj = 2; simple && (ni + nj) < lista.size(); nj++, k++, l++) {
					//inter = GNC::GCS::Vector::InterseccionEntreRectas((*i), (*j), (*k), (*l));
					//if ( 1 || inter.DentroDeBoundingBoxCerrado(bbox[0][0], bbox[0][1])) {
					(*k).IniciarBoundingBox(bbox[1][0],bbox[1][1]);
					(*l).ExtenderBoundingBox(bbox[1][0],bbox[1][1]);
					GNC::GCS::Vector::IntersectarBoundingBox(bbox[0], bbox[1], bbox[1]);
					if ( GNC::GCS::Vector::BoundingBoxValido(bbox[1]) && GNC::GCS::Vector::InterseccionEntreRectas(*i, *j, *k, *l).DentroDeBoundingBoxCerrado(bbox[1][0], bbox[1][1]) ) {
						//simple = false;
						GNC::GCS::Vector inter = GNC::GCS::Vector::InterseccionEntreRectas(*i, *j, *k, *l);

						

						glColor3f(0.0f, 0.0f, 1.0f);
						glLineWidth(1.0f);
						glBegin(GL_LINE_LOOP);
						glVertex2f(bbox[1][0].x, bbox[1][0].y);
						glVertex2f(bbox[1][1].x, bbox[1][0].y);
						glVertex2f(bbox[1][1].x, bbox[1][1].y);
						glVertex2f(bbox[1][0].x, bbox[1][1].y);
						glEnd();

						glColor3f(1.0f, 1.0f, 1.0f);
						glBegin(GL_LINES);
						glVertex2f((*i).x, (*i).y);
						glVertex2f((*j).x, (*j).y);
						glEnd();
						glBegin(GL_LINES);
						glVertex2f((*k).x, (*k).y);
						glVertex2f((*l).x, (*l).y);
						glEnd();

						glBegin(GL_POINTS);
						glPointSize(2.0f);
						glColor3f(1.0f, 1.0f, 1.0f);
						glVertex2f(inter.x, inter.y);
						glEnd();
						
					}
				}

				if ( (++i) == lista.end() ) {
					i = lista.begin();
					glPointSize(2.0f);
					glBegin(GL_POINTS);
					glColor3f(1.0f, 0.0f, 1.0f);
					glVertex2f( (*i).x, (*i).y );
					glEnd();
				}
				j++;
				*/
				/*
			}
		}
	}
	*/

	if (GNC::GCS::Vector::EsPoligonoSimple(m_Vertices)) {
		return GNC::GCS::Vector::AreaDePoligono(m_Vertices);
	}
	else {
		return std::numeric_limits<float>::quiet_NaN();
	}
}

