#include "StdAfx.h"
#include "CartoBaseElements.h"
#include "CartoBase.h"
#include "CartoBaseShpManager.h"
#include "GeometryFunction.h"
#include "dir_manager.h"
//*****************************************************************************************
CartoBaseInfoEntity::CartoBaseInfoEntity()
{
	i_entity = -1;
	ptr = 0;
}
//*****************************************************************************************
bool CartoBaseInfoEntity::isValid()
{
	return ptr && i_entity >= 0 && ptr->_entities.n > i_entity;
}
//*****************************************************************************************
CartoBaseInfoEntity CartoBaseInfoEntity::next()
{
	if(!isValid())
		return CartoBaseInfoEntity();
	return ptr->get(i_entity+1);
}
//*****************************************************************************************
CartoBasePoint* CartoBaseInfoEntity::pto()
{
	if(!fpto)
		return 0;
	return fpto(this);
}
//*****************************************************************************************
CartoBaseLine* CartoBaseInfoEntity::line()
{
	if(!fline)
		return 0;
	return fline(this);
}
//*****************************************************************************************
CartoBaseInfoEntity CartoBaseInfoEntity::prev()
{
	if(!isValid())
		return CartoBaseInfoEntity();
	return ptr->get(i_entity-1);
}
//*****************************************************************************************
CartoBaseEntity* CartoBaseInfoEntity::entity()
{
	if(!isValid())
		return NULL;
	return ptr->_entities.get(i_entity);
}
//*****************************************************************************************
CartoBasePaintedProps* CartoBaseInfoEntity::paintp()
{
	CartoBaseEntity* e = CartoBaseInfoEntity::entity();
		if(e)
			return ptr->_paintedProps.get(e->idPaintp);
	return NULL;
}
//*****************************************************************************************
int CartoBaseInfoEntity::getNumberPtos()
{
	CartoBaseLine* l = line();
	if(!l)//es un punto
		return 1;
	return l->n;
}
//*****************************************************************************************
double* CartoBaseInfoEntity::getPto(int i)
{
	CartoBasePoint* aux =pto();
	if(aux)
		return aux[i].pts;
	return 0;
}
//*****************************************************************************************
CartoBaseColor* CartoBaseInfoEntity::color()
{
	CartoBasePaintedProps* pp = paintp();
	if(pp)
		return ptr->_colors.get(pp->color);
	return NULL;	
}
//*****************************************************************************************
CartoBasePoint* CartoBaseInfoPto::pto(CartoBaseInfoEntity* c)
{
	CartoBaseEntity* e = c->entity();
	if(e)
		return c->ptr->_points.get(e->id);
	return NULL;
}
//*****************************************************************************************
CartoBasePoint* CartoBaseInfoLine::pto(CartoBaseInfoEntity* c)
{
	CartoBaseLine* l = c->line();
		if(l)
			return c->ptr->_points.get(l->ini);
	return NULL;
}
//*****************************************************************************************
CartoBaseInfoEntity EntitiesArray::getEntity(int i)
{
	CartoBaseInfoEntity* e = get(i);
	if(e)
		return *e;
	return CartoBaseInfoEntity();
}
//*****************************************************************************************
EntitiesArray* EntitiesArray::filter(EntitiesArray* dst, FilterEntities* filter)
{
	
	for(int i =0 ; i<n; i++)
	{
		CartoBaseInfoEntity* e = get(i);
		if(filter->IsSeletedEntity(e))
		{
			if(!((*dst)+(*e)))
				return 0;
		}
	}
	return dst;
}
//*****************************************************************************************
bool EntitiesArray::exportShp(char* path, int type)
{
	CartoBaseShpManager shp;
	char nshp[256];
	Cb_file f;
	Cb_file fshp;
	if(!f.abre(path,2,1))
		return false;
	if(!fshp.abre(Cdir_manager::cambia_extension_archivo(path,nshp,"shx"),2,1))
		return false;
	return shp.ExportShp(&f,&fshp, this, type);
}
//*****************************************************************************************
int EntitiesArray::getNumberEntities()
{
	return n;
}
//*****************************************************************************************
int EntitiesArray::getNumberPtos()
{
	int count =0;
	for(int i =0; i<n; i++)
	{
		count+=get(i)->getNumberPtos();
	}
	return count;
}
//*****************************************************************************************
double* EntitiesArray::getPto(int i)
{
	int count =0;

	for(int i =0; i<n; i++)
	{
		count=get(i)->getNumberPtos();
		if(i>=count)
			i -=count;
		else
			return get(i)->getPto(i);
	}
	return 0;
}
//*****************************************************************************************
CartoEntity* CartoBaseInfoEntity::getCopy(CartoEntity *buf)
{
	CartoBaseEntity* e = entity();
	CartoEntity * buff = NULL;
	if(!e)
		return NULL;
	if(!buf)
		buf = buff = CartoBaseInfoBuilder::get(e->type);
	if( buf->getType()!= e->type)
		return NULL;
	if(!buf->set(this))
	{
		if(buff)
			delete buff;
	}
	return buf;
}
//*****************************************************************************************
double CartoBaseInfoEntity::getLong()
{
	return GeometryFunction::LongLine2d(this);
}
//*****************************************************************************************
//la distancia media a una línea de longitud mayor que this, 
//partiendo de this y calculando la distancia de puntos equidistantes l_avan a los puntos
//más cercanos de line2
double CartoBaseInfoEntity::disMedLines(SetPtsR *line2, double l_avan, double *desv)
{
	return GeometryFunction::DisMedLines(this,line2,l_avan,desv);
}
//*****************************************************************************************
//la distancia media a una línea de longitud mayor que this,
//calculando la distancia de los puntos de this a line2
double CartoBaseInfoEntity::disMedLines(SetPtsR *line2, double *desv)
{
	return GeometryFunction::DisMedLines(this,line2);
}
//*****************************************************************************************
double *CartoBaseInfoEntity::GetPtoDis(double dis, double *dst, double *distTot)
{
	return GeometryFunction::GetPto(this, dis, dst, distTot);
}
//*****************************************************************************************
double CartoBaseInfoEntity::DisPtoLine(double*p, int* idpto, double *lamb)
{
	return GeometryFunction::DisPtoLine(this,p,idpto,lamb);
}
//*****************************************************************************************
double CartoBaseInfoEntity::DplineSeg(double* s1, double *s2,int *n, double *lamd1,double *lamb2)
{
	return GeometryFunction::DplineSeg(this,s1, s2,n, lamd1,lamb2);
}
//*****************************************************************************************
SetPtsW *CartoBaseInfoEntity::GetNPrimePtos(SetPtsW *ldst,  int nptos, double dis, BOOL avanza)
{
	return GeometryFunction::GetNPrimePtos(this,ldst,nptos,dis,avanza);
}
//*****************************************************************************************
double *CartoBaseInfoEntity::PtInLine(int ip, double lamb, double *pp )
{
	return GeometryFunction::PtInLine( this, ip, lamb , pp );
}
//*****************************************************************************************
bool CartoBaseInfoEntity::DivLine( SetPtsW* ldst1, SetPtsW* ldst2, int ip, double lamb )
{
	double dis=GeometryFunction::DisInLine(this,ip,lamb);
	if(dis<0)
		return false;
	return GeometryFunction::DivLine(this,ldst1,ldst2,dis);
}
//*****************************************************************************************
void* CartoBaseInfoEntity::getIa()
{
	CartoBaseEntity* e = entity();
	if(e)
		return ptr->getIa(e->ref);
	return NULL;
}

//*****************************************************************************************
CartoBaseLine* CartoBaseInfoLine::line(CartoBaseInfoEntity* c)
{
	CartoBaseEntity* e = c->entity();
		if(e)
			return c->ptr->_lines.get(e->id);
	return NULL;
}
//*****************************************************************************************
CartoBaseInfoEntity CartoBaseInfoBuilder::get(int i, CartoBase* ptr)
{
	CartoBaseInfoEntity res;
	if(!ptr)
		goto mal;
	if(i<0 || ptr->_entities.n<= i)
		goto mal;
	res.ptr = ptr;
	res.i_entity = i;
	switch(ptr->_entities[i].type)
	{
	case (CartoBaseTypes::Point):
		{
			res.fline= 0;
			res.fpto= CartoBaseInfoPto::pto;
			break;
		}
	case (CartoBaseTypes::Line):
		{
			res.fline= CartoBaseInfoLine::line;
			res.fpto= CartoBaseInfoLine::pto;
			break;
		}
	default:
		break;
	}
mal:
	return res;
}
//*****************************************************************************************
CartoEntity* CartoBaseInfoBuilder::get(int type)
{
	
	switch(type)
	{
	case (CartoBaseTypes::Point):
		return new CartoPto();
	case (CartoBaseTypes::Line):
		return new CartoLine();
	}
	return NULL;
}
//*****************************************************************************************