/* 
 * Thomas Pantzer: t_path.cc, v0.1b  23.9.97 22:29 
 * 
 * 
 * Copyright 1997 by Thomas Pantzer
 * 
 * Permission to use, copy, modify, and distribute this software for noncommercial 
 * use and without fee is hereby granted, provided that the above copyright notice 
 * appear in all copies and that both that copyright notice and this permission 
 * notice appear in supporting documentation, and that the name of the Author not be 
 * used in advertising or publicity pertaining to distribution of the software 
 * without specific, written prior permission. The Author makes no representations about
 * the suitability of this software for any purpose.  It is provided "as is" 
 * without expressed or implied warranty. 
 * 
 * 
 * pantec@aix520.informatik.uni-leipzig.de   (Thomas Pantzer) 
 * 
 */


#include <math.h>
#include <fcntl.h>
#include <unistd.h>

#include "copyright.h"

#include "forms.h"
#include "graphix.h"

#define T_PATH_G
//#include "floatsize.h"
#include "t_path.h"



void t_PATH::Init(t_vector *center)
{
  way.Init(*center);	
  block = 0.0;  /* degree where the blocks lay */ 
  border = 0;
  end = false;
  adjusted = false;
  next = NULL;
}

t_vector *t_PATH::LastPos(void)
{
//   if (next == NULL)
   return &way; 
//    else
//      return next->LastPos();  
}


int t_PATH::Length(void)
{
    t_PATH *p = this;
    int i = 0;
   
    while (p != NULL)
      {
       i++;
       p = p->next; 
      }
/*
	if (next == NULL)
	   return 1;
         else 
           return (1 + next->Length());  
 */
    return i;
}

int t_PATH::Length(t_PATH *v)
{
    t_PATH *p = this;
    int i = 0;
   
    while ((p != NULL) && (p != v))
      {
       i++;
       p = p->next; 
      }
/*
	if (next == NULL)
	   return 1;
         else 
           return (1 + next->Length());  
 */
    return i;
/*
	if ((next == NULL) || (next == p))
	   return 1;
         else 
           return (1 + next->Length());  
 */ 
}

t_PATH *t_PATH::LastPos(int pre)
{
	if (pre == 0)
   	    return this; 
	 else
	   {
	    if (next == NULL)
	       return NULL;
             else
	       return next->LastPos(pre -1);
	   }
}

t_PATH *t_PATH::Last_not_Adjusted(void)
{
	if (next == NULL)
	   return NULL;
	
	if (next->adjusted == true)
	   return NULL;

	if (next->next == NULL)
	   return NULL;
	
	if (next->next->adjusted == true) 
	   return this;

//	fprintf(stderr,"adjust_iteration\n");
	return next->Last_not_Adjusted();
}


void t_PATH::Save(char *fn)
{
    int fd = open(fn,O_RDWR|O_CREAT|O_TRUNC,0600);
	
    Save(fd); 	

    close(fd);	
}

void t_PATH::Save(int fd)
{
    char st[256];
 	
    int L = Length() + 4;
    fprintf(stderr,"pathlen:%d allocating %d kByte\n",L,L*sizeof(t_PATH)/1024);

    t_PATH *p = this;
    t_PATH **P;

    P = new t_PATH*[L];
    int i = 0;   
    while (p != NULL)   
      {
       P[i] = p;
       i++;
       p = p->next;
      }

    for (int j=i-1; j>=0; j--)
      { 
       sprintf(st,"%g %g\n",P[j]->way.x,P[j]->way.y);
       write(fd,st,strlen(st));	
      }
//      P[j]->Save(fd,st);

    delete [] P;
}
// int rekcnt = 0;
 
void t_PATH::Save(int fd,char *st)
{
//     rekcnt++;
//     fprintf(stderr,"%ld. %ld\n",rekcnt,sysconf(	_SC_AVPHYS_PAGES));	
//     long MA = sysconf(_SC_AVPHYS_PAGES);

//     if (MA < 200)
//   	fprintf(stderr,"%ld. %ld\n",rekcnt,MA);
    
   
//     if (next != NULL)
//	next->Save(fd,st);	

//     {
//      char st[256];	
//      sprintf(st,"%g %g\n",way.x,way.y);
//      write(fd,st,strlen(st));	
//     }
}

/*
void t_PATH::Load(char *fn)
{
    int fd = open(fn,O_RDWR);
    Load(fd);
    close(fd);	
}
*/

char t_PATH::Load(FILE *fs)
{
//    char st[256];
//    int rd = read(fd,&st[0],128);	
    if (fs == NULL)
    	return false;

    float a,b;//,c;

    border = false;
    adjusted = false;	
    end = false;

    block = 0.0;
    next = NULL;

    if (fscanf(fs,"%f %f\n",&a,&b) == 2)
       { 
   	way.x = (double)a;
	way.y = (double)b;
//	info = (double)c;
	return true;
       }
     
    end = true; 	
    return false;	
}

t_PATH *t_PATH::NextPos(FILE *fs)
{
  t_PATH *N;
//  O = this;
  
  if (fs == NULL)
     return this;
  
  N = new t_PATH;

  if (N->Load(fs) == true)
     N->next = this;
   else
     {
      delete N;
      return this;	
     }
  
  return N;
}

void t_PATH::Done(void)
{
	fprintf(stderr,"t_path::Done()\n");

	int L = Length() + 4;

    	t_PATH *p,*dP;

    	int i = 0;   
	p = next;	
	
	while (p != NULL)   	// sort the list into an array
	  {				// to avoid the recursive structure
	   dP = p;
       	   p = p->next;

	   dP->next = NULL;
	   delete dP;
          }

	fprintf(stderr,"t_path::Done(i:%d, L:%d)\n",i,L);
	next = NULL;
}


t_PATH *t_PATH::Add(t_vector *np)
{
  t_PATH *N;
  
//  O = this;
  
  N = new t_PATH;
  N->Init(np);
  N->next = this;
  
  return N;
}

void t_PATH::Draw(t_world *W)
{
   if (next == NULL)
      return;    

   if ((W->size.x == 0) || (W->size.y == 0))
      return;

// initialisaton of locals after that recursive stuff

   double S_zoom,W_zoom;
   int x1,y1,x2,y2;
   t_vector  D1,D2;

   S_zoom = VScr.size;
 
   if (W->size.x > W->size.y)
      W_zoom = W->size.x;
    else
      W_zoom = W->size.y;   

   D1.x = (way.x - W->min.x) / W_zoom;
   D1.y = (way.y - W->min.y) / W_zoom;      

   x1 = (int)(D1.x * S_zoom);
   y1 = (int)(D1.y * S_zoom);

   D2.x = (next->way.x - W->min.x) / W_zoom;
   D2.y = (next->way.y - W->min.y) / W_zoom;      

   x2 = (int)(D2.x * S_zoom);           
   y2 = (int)(D2.y * S_zoom);


   if ((border == true) && (next->border == true))
      SetColor(FL_DOGERBLUE);
    else
      SetColor(FL_MCOL);
 	
   drawline(x1,VScr.height - y1,x2,VScr.height - y2);

   if (border == true)
      {
       SetColor(FL_WHITE);
       FillRectangle(x1,VScr.height - y1,4,4);		
      }	
         
}

void t_PATH::Draw(t_world *W, int dc)
{
   	if (dc == 0)
	   return; 
   
	if (next != NULL)
	    next->Draw(W,dc-1);

	Draw(W);
}

/*     
  if (border == true)
     {

      int dx,dy,dx2,dy2;
      
      dx = (int)(8.0 * cos(block));
      dy = (int)(8.0 * sin(block));

//      SetColor(FL_YELLOW);
//      drawline(x1,y1,x1+dx,y1+dy);
      
      SetColor(FL_YELLOW); 
      drawline(x1,VScr.height - y1,x2 + dx ,VScr.height - y2 + dy);
      
      SetColor(FL_RED);
      FillRectangle(x1 + dx ,VScr.height - y1 + dy,3,3);
     }
*/











/**/
/**/
/**/
/**/
/**/
/**/
/**/
/**/
/*****  End Of File  ****************************/
