#include "StdAfx.h"
#include "Fshape.h"
#include <float.h>
//**************************************************************************
int  Fshape::inv_4(int *pb)
{
	char (*pc)[],(*pd)[];
	int j,dw;

	dw = *pb;
	pc = (char (*)[]) &dw;
	pd = (char (*)[]) pb;
	for (j=0; j<4; j++)
		(*pd)[j] = (*pc)[3-j];

	return(dw);
}
//**************************************************************************
Fshape::Fshape(void)
{
}
//**************************************************************************
Fshape::~Fshape(void)
{
}
//**************************************************************************
bool Fshape::leeHead(Cb_file *file)
{
	f = file;
	if(!f->lee(&head, sizeof(head)))
		return false;
	inv_4(&head.code);
	inv_4(&head.nb);

	head.nb = 2 * head.nb- sizeof(head);
	switch(head.tipo)
	{
	case(Point):
		nc = 2;
		ReadType = Rpoint;
		break;
	case(PolyLine):
		nc = 2;
		ReadType = RPolyLine;
		break;
	case(Polygon):
		nc = 2;
		ReadType = Rpolygon;
		break;
	case(MultiPoint):
		nc = 2;
		ReadType = RMpoint;
		break;

	case(PointZ):
		nc = 4;
		ReadType = Rpoint;
		break;
	case(PolyLineZ):
		nc = 4;
		ReadType = RPolyLine;
		break;
	case(PolygonZ):
		nc = 4;
		ReadType = Rpolygon;
		break;
	case(MultiPointZ):
		nc = 4;
		ReadType = RMpoint;
		break;

	case(PointM):
		nc = 3;
		ReadType = Rpoint;
		break;
	case(PolyLineM):
		nc = 3;
		ReadType = RPolyLine;
		break;
	case(PolygonM):
		nc = 3;
		ReadType = Rpolygon;
		break;
	case(MultiPointM):
		nc = 3;
		ReadType = RMpoint;
		break;
	default:
		return false;
	}
	return true;
}
//**************************************************************************
bool Fshape::LeeRecord()
{
	//lee cab
	int nb;
	if(head.nb<=0)
		return false;
	if(!f->lee(&headr, sizeof(headr)))
		return false;
	head.nb-=sizeof(headr);
	inv_4(&headr.nrec);
	inv_4(&headr.nb);
	//tipo incluido en cabecera
	headr.nb = 2 * headr.nb-sizeof(int);
	//lee contenido record;
	bufRecord.n = 0;
	if(!(bufRecord+= headr.nb))
		return false;
	bufRecord.n = headr.nb;
	if(!f->lee(&bufRecord[0], bufRecord.n))
		return false;
	head.nb-=bufRecord.n;
	numPart = 0;
	nb = 0;
	maxC = NULL;
	mimC = NULL;
	mimaM = NULL;
	mimaZ = NULL;
	ptosM = NULL;
	ptos = NULL;
	ptosZ = NULL;

	switch (ReadType)
	{
		case Rpoint:
			numPart = 0;
			ptos = (double*)&bufRecord[nb];//salta el tipo
			tc = (bufRecord.n-nb)/sizeof(double);
			npt =tc/nc;
		break;
		case RMpoint:
			mimC = (double*)&bufRecord[nb];
			nb +=2*sizeof(double);
			maxC = (double*)&bufRecord[nb];
			nb +=2*sizeof(double);
			npt = *(int*)&bufRecord[nb];
			nb += sizeof(int);
			ptos = (double*)&bufRecord[nb];//salta el tipo
			nb+=sizeof(double)*2*npt;
			if(nc>2)
			{
				if(nc<4)
				{
					mimaM =  (double*)&bufRecord[nb];
					nb+=2*sizeof(double);
					ptosM = (double*)&bufRecord[nb];
					nb+=npt*sizeof(double);
				}
				else
				{
					mimaZ =  (double*)&bufRecord[nb];
					nb+=2*sizeof(double);
					ptosZ = (double*)&bufRecord[nb];
					nb+=npt*sizeof(double);

					mimaM =  (double*)&bufRecord[nb];
					nb+=2*sizeof(double);
					ptosM = (double*)&bufRecord[nb];
					nb+=npt*sizeof(double);	
				}
			}
			tc = npt*2;
		break;

		case RPolyLine:
		case Rpolygon:
			mimC = (double*)&bufRecord[nb];
			nb +=2*sizeof(double);
			maxC = (double*)&bufRecord[nb];
			nb +=2*sizeof(double);
			numPart = *(int*)&bufRecord[nb];
			nb += sizeof(int);
			npt = *(int*)&bufRecord[nb];
			nb += sizeof(int);

			part = (int*)&bufRecord[nb];
			nb += sizeof(int)*numPart;
			ptos = (double*)&bufRecord[nb];//salta el tipo
			nb+=sizeof(double)*2*npt;
			if(nc>2)
			{
				if(nc<4)
				{
					mimaM =  (double*)&bufRecord[nb];
					nb+=2*sizeof(double);
					ptosM = (double*)&bufRecord[nb];
					nb+=npt*sizeof(double);
				}
				else
				{
					mimaZ =  (double*)&bufRecord[nb];
					nb+=2*sizeof(double);
					ptosZ = (double*)&bufRecord[nb];
					nb+=npt*sizeof(double);

					mimaM =  (double*)&bufRecord[nb];
					nb+=2*sizeof(double);
					ptosM = (double*)&bufRecord[nb];
					nb+=npt*sizeof(double);	
				}
			}
			tc = npt*2;
		break;
		default:
			return false;
	}
	
	return true;
}
//**************************************************************************
double* Fshape::get(int ip, int i)
{
	if(ip>numPart)
		return NULL;
	int nn = part[ip]*2+i*2;
	if((nn+2)>tc)
		return NULL;
	return &ptos[nn];
}
//**************************************************************************
double* Fshape::get( int i)
{
	if(i>=npt)
		return NULL;
	return &ptos[i*2];
}
//**************************************************************************
int Fshape::getNp()
{
	return numPart;
}
//**************************************************************************
int Fshape::getType()
{
	return ReadType;
}
//**************************************************************************
int Fshape::getNcoord()
{
	return nc;
}
//**************************************************************************
int Fshape::getNPt(int ip)
{
	if(ip>numPart)
		return -1;
	if((numPart-1)>ip)
		return part[ip+1]-part[ip];
	return npt - part[ip];
}
//**************************************************************************
int Fshape::getNPt()
{
	return npt;
}
//**************************************************************************
bool Fshape::set(int type/*FshpReadType*/,int ncoord, Cb_file *file, Cb_file *file_shx)
{
	f_shx = file_shx;
	memset(&head,0,sizeof(head));
	head.mima[0][0] = head.mima[0][1]= DBL_MAX;
	head.mima[1][0] = head.mima[1][1]= -DBL_MAX;
	ReadType=type;
	nc = ncoord;
	head.mimam[0]=head.mimam[1]=0;
	head.mimaz[0]=head.mimam[1]=0;
	head.ver =1000;
	head.code = 9994;
	//inv_4(&head.ver);
	inv_4(&head.code);
	head.nb = sizeof(head);
	headr.nb = 0;
	headr.nrec=0;
	f = file;
	if(nc<2 || nc>4)
		return false;
	switch(type)
	{
	case(Rpoint):
		if(nc<=2)
			head.tipo = Point;
		else if(nc<=3)
			head.tipo = PointM;
		else
			head.tipo = PointZ;
		break; 
	case(RMpoint):
		if(nc<=2)
			head.tipo = MultiPoint;
		else if(nc<=3)
			head.tipo = MultiPointM;
		else
			head.tipo = MultiPointZ;
		break; 
	case(RPolyLine):
		if(nc<=2)
			head.tipo = PolyLine;
		else if(nc<=3)
			head.tipo = PolyLineM;
		else
			head.tipo = PolyLineZ;
		break;
	case(Rpolygon):
		if(nc<=2)
			head.tipo = Polygon;
		else if(nc<=3)
			head.tipo = PolygonM;
		else
			head.tipo = PolygonZ;
		break; 
	default:
			return false;
	}
	headr.tipo = head.tipo;
	if(f_shx && !f_shx->escribe(&head, sizeof(head)))
		return false;
	return (f->escribe(&head, sizeof(head))==TRUE);
}
//**************************************************************************
bool Fshape::grabaRecord(Cgarray<double> *pts)
{
	int aux;
	npt = pts->n/nc;
	if(npt<=0)
		return false;

	double mimaxr[2][2];
	mimaxr[0][0] = mimaxr[0][1]= DBL_MAX;
	mimaxr[1][0] = mimaxr[1][1]= -DBL_MAX;
	double mimaxZ[2];
	double mimaxM[2];
	mimaxZ[0] = mimaxM[0]= DBL_MAX;
	mimaxZ[1] = mimaxM[1]= -DBL_MAX;
	ptosM = NULL;
	ptosZ = NULL;
	int ii = 0;
	switch(ReadType)
	{
	case(Rpoint):
		{
			headr.nb =sizeof(int)+sizeof(double)*nc;
			headr.nb = headr.nb/2;
			inv_4(&headr.nb);
			for(int i=0; i<npt; i++)
			{
				headr.nrec++; 
				inv_4(&headr.nrec);
				if(!f->escribe(&headr, sizeof(headr)))
					return false;
				inv_4(&headr.nrec);
				aux = head.nb/2;
				inv_4(&aux);
				if(f_shx && !f_shx->escribe(&aux, sizeof(aux)))
					return false;
				head.nb+=sizeof(headr);
				//graba offset
				aux = headr.nb;
				inv_4(&aux);
				if(f_shx && !f_shx->escribe(&aux, sizeof(aux)))
					return false;
				ii = i*nc;
				ptos = &(*pts)[ii];
				//pilla minimo y maximo
				if(mimaxr[0][0]>ptos[0])
					mimaxr[0][0]=ptos[0];
				if(mimaxr[0][1]>ptos[1])
					mimaxr[0][1]=ptos[1];
				if(mimaxr[1][0]<ptos[0])
					mimaxr[1][0]=ptos[0];
				if(mimaxr[1][1]<ptos[1])
					mimaxr[1][1]=ptos[1];
				if(!f->escribe(ptos, sizeof(double)*nc))
					return false;
				head.nb+=sizeof(double)*nc;
			}
		}
		break;
	case(RMpoint):
		{
			headr.nb = sizeof(double)*nc*npt+sizeof(int);
			headr.nb = inv_4(&headr.nb);
			headr.nrec++; 
			headr.nrec=inv_4(&headr.nrec);
			if(!f->escribe(&headr, sizeof(headr)))
				return false;
			headr.nrec=inv_4(&headr.nrec);

			aux = head.nb/2;
			inv_4(&aux);
			if(f_shx && !f_shx->escribe(&aux, sizeof(aux)))
				return false;
			head.nb+=sizeof(headr);
			//graba offset
			aux = headr.nb;
			inv_4(&aux);
			if(f_shx && !f_shx->escribe(&aux, sizeof(aux)))
				return false;
			if(nc>3)
			{
					ptosZ = &(*pts)[npt*3];
					ptosM = &(*pts)[npt*3];
			}
			else if(nc>2)
			{
					ptosM = &(*pts)[npt*2];
					//mimam
			}

			for(int i=0; i<npt; i++)
			{
				ii = i*2;
				ptos = &(*pts)[ii];
				//pilla minimo y maximo
				if(mimaxr[0][0]>ptos[0])
					mimaxr[0][0]=ptos[0];
				if(mimaxr[0][1]>ptos[1])
					mimaxr[0][1]=ptos[1];
				if(mimaxr[1][0]<ptos[0])
					mimaxr[1][0]=ptos[0];
				if(mimaxr[1][1]<ptos[1])
					mimaxr[1][1]=ptos[1];
				if(ptosM)
				{
					if(mimaxM[0]>ptosM[i])
						mimaxM[0]=ptosM[i];
					if(mimaxM[1]<ptosM[i])
						mimaxM[1]=ptosM[i];
				}
				if(ptosZ)
				{
					if(mimaxZ[0]>ptosZ[i])
						mimaxZ[0]=ptosZ[i];
					if(mimaxZ[1]<ptosZ[i])
						mimaxZ[1]=ptosZ[i];
				}
				
			}
			if(!f->escribe(mimaxr, sizeof(double)*4))
				return false;
			head.nb+=sizeof(double)*4;

			if(!f->escribe(&npt, sizeof(npt)))
				return false;
			head.nb+=sizeof(npt);
			if(!f->escribe(&(*pts)[0], sizeof(double)*nc*npt))
				return false;
			head.nb+=sizeof(double)*2*npt;
			if(ptosZ)
			{
				if(!f->escribe(mimaxZ, sizeof(double)*2))
					return false;
				head.nb+=sizeof(double)*2;
				if(!f->escribe(ptosZ, sizeof(double)*npt))
					return false;
				head.nb+=sizeof(double)*npt;
			}
			if(ptosM)
			{
				if(!f->escribe(mimaxM, sizeof(double)*2))
					return false;
				head.nb+=sizeof(double)*2;
				if(!f->escribe(ptosM, sizeof(double)*npt))
					return false;
				head.nb+=sizeof(double)*npt;
			}
		}
		break;
	default:
		return false;
	}
	//pilla coordenadas maximas y minimas totales del shp
	if(head.mima[0][0]>mimaxr[0][0])
		head.mima[0][0]=mimaxr[0][0];
	if(head.mima[0][1]>mimaxr[0][1])
		head.mima[0][1]=mimaxr[0][1];
	if(head.mima[1][0]<mimaxr[1][0])
		head.mima[1][0]=mimaxr[1][0];
	if(head.mima[1][1]<mimaxr[1][1])
		head.mima[1][1]=mimaxr[1][1];

	return true;
}
//**************************************************************************
bool Fshape::grabaRecord(Cgarray<double> *pts, Cgarray<int>*parts)
{
	int aux;
	npt = pts->n/nc;
	if(npt<=0)
		return false;

	double mimaxr[2][2];
	mimaxr[0][0] = mimaxr[0][1]= DBL_MAX;
	mimaxr[1][0] = mimaxr[1][1]= -DBL_MAX;

	double mimaxZ[2];
	double mimaxM[2];
	mimaxZ[0] = mimaxM[0]= DBL_MAX;
	mimaxZ[1] = mimaxM[1]= -DBL_MAX;
	ptosM = NULL;
	ptosZ = NULL;
	headr.tipo = head.tipo;
	int ii = 0;
	switch(ReadType)
	{
	case(RPolyLine):
	case(Rpolygon):
	{
			headr.nrec++; 
			inv_4(&headr.nrec);
			
			headr.nb = sizeof(int)+sizeof(double)*4+2*sizeof(int)+ 
				+sizeof(int)*parts->n+sizeof(double)*2*npt;
			if(nc>3)
			{
				ptosZ = &(*pts)[npt*3];
				ptosM = &(*pts)[npt*3];
				headr.nb+=2*(sizeof(double)*2+sizeof(double)*npt);
			}
			else if(nc>2)
			{
					headr.tipo = PolyLineZ;
					ptosM = &(*pts)[npt*2];
					headr.nb+=sizeof(double)*2+sizeof(double)*npt;
					//mimam
			}
			headr.nb = headr.nb/2;
			inv_4(&headr.nb);
			if(!f->escribe(&headr, sizeof(headr)))
				return false;
			inv_4(&headr.nrec);
			inv_4(&headr.nb);
			aux = head.nb/2;
			inv_4(&aux);
			if(f_shx && !f_shx->escribe(&aux, sizeof(aux)))
				return false;
			head.nb+=sizeof(headr);
			//graba offset
			aux = headr.nb;
			inv_4(&aux);
			if(f_shx && !f_shx->escribe(&aux, sizeof(aux)))
				return false;
			for(int i=0; i<npt; i++)
			{
				ii = i*nc;
				ptos = &(*pts)[ii];
				//pilla minimo y maximo
				if(mimaxr[0][0]>ptos[0])
					mimaxr[0][0]=ptos[0];
				if(mimaxr[0][1]>ptos[1])
					mimaxr[0][1]=ptos[1];
				if(mimaxr[1][0]<ptos[0])
					mimaxr[1][0]=ptos[0];
				if(mimaxr[1][1]<ptos[1])
					mimaxr[1][1]=ptos[1];
				if(ptosM)
				{
					if(mimaxM[0]>ptosM[i])
						mimaxM[0]=ptosM[i];
					if(mimaxM[1]<ptosM[i])
						mimaxM[1]=ptosM[i];
				}
				if(ptosZ)
				{
					if(mimaxZ[0]>ptosZ[i])
						mimaxZ[0] = ptosZ[i];
					if(mimaxZ[1]<ptosZ[i])
						mimaxZ[1]=ptosZ[i];
				}
			}
			if(!f->escribe(mimaxr, sizeof(double)*4))
				return false;
			head.nb+=sizeof(double)*4;
			if(!f->escribe(&parts->n, sizeof(parts->n)))
				return false;
			head.nb+=sizeof(parts->n);
			if(!f->escribe(&npt, sizeof(npt)))
				return false;
			head.nb+=sizeof(npt);
			if(!f->escribe(&(*parts)[0], sizeof(int)*parts->n))
				return false;
			head.nb+=sizeof(int)*parts->n;

			if(!f->escribe(&(*pts)[0], sizeof(double)*2*npt))
				return false;
			head.nb+=sizeof(double)*2*npt;
			if(ptosZ)
			{
				if(!f->escribe(mimaxZ, sizeof(double)*2))
					return false;
				head.nb+=sizeof(double)*2;
				if(!f->escribe(ptosZ, sizeof(double)*npt))
					return false;
				head.nb+=sizeof(double)*npt;
			}
			if(ptosM)
			{
				if(!f->escribe(mimaxM, sizeof(double)*2))
					return false;
				head.nb+=sizeof(double)*2;
				if(!f->escribe(ptosM, sizeof(double)*npt))
					return false;
				head.nb+=sizeof(double)*npt;
			}
		}
		break;
	default:
		return false;
	}
	//pilla coordenadas maximas y minimas totales del shp
	if(head.mima[0][0]>mimaxr[0][0])
		head.mima[0][0]=mimaxr[0][0];
	if(head.mima[0][1]>mimaxr[0][1])
		head.mima[0][1]=mimaxr[0][1];
	if(head.mima[1][0]<mimaxr[1][0])
		head.mima[1][0]=mimaxr[1][0];
	if(head.mima[1][1]<mimaxr[1][1])
		head.mima[1][1]=mimaxr[1][1];

	return true;
}
//**************************************************************************
bool Fshape::FinGraba()
{
	if(!f->irAini())
		return false;
	if(f_shx && !f_shx->irAini())
		return false;
	head.nb = head.nb/2;
	inv_4(&head.nb);
	head.ver =1000;
	head.code =9994;
	inv_4(&head.code);

	if(!f->escribe(&head, sizeof(head)))
		return false;
	int auxi = head.nb;
	head.nb = 100+headr.nrec*2*sizeof(int);
	head.nb = head.nb/2;
	inv_4(&head.nb);
	if(f_shx && !f_shx->escribe(&head, sizeof(head)))
		return false;
	if(f_shx && !f_shx->irAfin())
		return false;
	return (f->irAfin()== TRUE);
}
//**************************************************************************