/////////////////////////////////////////////////////////////////////////////
// Name:        BgEdgeList.cpp
// Purpose:     BgEdgeList class functions
// Author:      Bogdan Georgescu
// Modified by:
// Created:     06/22/2000
// Copyright:   (c) Bogdan Georgescu
// Version:     v0.1
/////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "BgDefaults.h"
#include "BgImage.h"
#include "BgEdge.h"
#include "BgEdgeList.h"

BgEdgeList::BgEdgeList()
{
   nEdges_ = 0;
   edgelist_ = 0;
   crtedge_ = 0;
}

BgEdgeList::~BgEdgeList()
{
   if (nEdges_>0)
   {
      BgEdge* edge;
      for (int i=0; i<nEdges_; i++)
      {
         edge = edgelist_->next_;
         delete edgelist_;
         edgelist_=edge;
      }
   }
}

void BgEdgeList::AddEdge(float* edge, int nPoints)
{
   BgEdge* tedge;
   tedge = new BgEdge();
   tedge->SetPoints(edge, nPoints);
   if (nEdges_==0)
   {
      nEdges_ = 1;
      edgelist_ = tedge;
      crtedge_ = tedge;
   }
   else
   {
      nEdges_++;
      crtedge_->next_ = tedge;
      crtedge_ = tedge;
   }
}

void BgEdgeList::AddEdge(int* edge, int nPoints)
{
   BgEdge* tedge;
   tedge = new BgEdge();
   tedge->SetPoints(edge, nPoints);
   if (nEdges_==0)
   {
      nEdges_ = 1;
      edgelist_ = tedge;
      crtedge_ = tedge;
   }
   else
   {
      nEdges_++;
      crtedge_->next_ = tedge;
      crtedge_ = tedge;
   }
}

void BgEdgeList::SetGradient(float* grx, float* gry, float* mark, int ncol)
{
   BgEdge* it;
   int i;

   it=edgelist_;
   for (i=0; i<nEdges_; i++)
   {
      it->SetGradient(grx, gry, mark, ncol);
      it = it->next_;
   }
}

void BgEdgeList::RemoveShortEdges(int minp)
{
   if (nEdges_==0)
      return;

   int nEdges=nEdges_;
   BgEdge* it1;
   BgEdge* it2;
   it1 = edgelist_;
   it2 = it1->next_;

   for (int i=1; i<nEdges_; i++)
   {
      if (it2->nPoints_ < minp)
      {
         it1->next_ = it2->next_;
         delete it2;
         it2 = it1->next_;
         nEdges--;
      }
      else
      {
         it1 = it2;
         it2 = it1->next_;
      }
   }

   if (edgelist_->nPoints_ < minp)
   {
      it1 = edgelist_;
      edgelist_ = edgelist_->next_;
      delete it1;
      nEdges--;
   }
   nEdges_=nEdges;
}

void BgEdgeList::SetBinImage(BgImage* image)
{
   int i, j;
   int ix, iy;
   int x, y;
   
   x = image->x_;
   y = image->y_;
   unsigned char* im=image->im_;
   
   for (i=0; i<x; i++)
   {
      for (j=0;j<y;j++)
      {
         *(im++) = 0;
      }
   }
   
   im = image->im_;
   int* ite;
   crtedge_=edgelist_;
   for (i=0; i<nEdges_; i++)
   {
      ite = crtedge_->edge_;
      for (j=0; j<crtedge_->nPoints_; j++)
      {
         ix = *(ite++);
         iy = *(ite++);
         *(im+iy*x+ix) = 255;
      }
      crtedge_=crtedge_->next_;
   }
}

bool BgEdgeList::SaveEdgeList(char* edgeFile)
{
   int length;
   int i,j;
   BgEdge *crtedge;
   
   FILE* fp;
   fp=fopen(edgeFile,"wb");
   crtedge = edgelist_;
   for (i=0; i<nEdges_; i++)
   {
      length = crtedge->nPoints_;
      for (j=0; j<length; j++)
      {
         fprintf(fp, "%d %d %d\n", *((crtedge->edge_)+2*j), *((crtedge->edge_)+2*j+1), i);
      }
      crtedge = crtedge->next_;
   }
   fclose(fp);
   return true;
}

void BgEdgeList::GetAllEdgePoints(int* x, int* y, int* n)
{
   int length;
   int i,j;
   BgEdge *crtedge;
   int *edgep;
   
   crtedge = edgelist_;
   *n = 0;
   for (i=0; i<nEdges_; i++)
   {
      length = crtedge->nPoints_;
      edgep = crtedge->edge_;
      for (j=0; j<length; j++)
      {
         x[*n] = edgep[2*j];
         y[*n] = edgep[2*j+1];
         (*n)++;
      }
      crtedge = crtedge->next_;
   }
}

void BgEdgeList::SetNoMark(void)
{
   int length;
   int i,j;
   BgEdge* crtedge;
   unsigned char* mark;
   crtedge = edgelist_;
   for (i=0; i<nEdges_; i++)
   {
      length = crtedge->nPoints_;
      mark = crtedge->mark_ = new unsigned char[length];
      crtedge->isMarkSet_ = true;
      for (j=0; j<length; j++)
      {
         *(mark+j) = 0;
      }
      crtedge = crtedge->next_;
   }
}
