Page d'accueil Description du projet
/*********************************************
 *
 * Cedric Pradalier
 * DEA 2000/2001 
 * INRIA Rhones Alpes
 * http://cedric.pradalier.free.fr/index.html
 * mail : http://cedric.pradalier.free.fr/mail.html
 *
 * *******************************************/
#include "LocalisationGraph.h"
#include "Polygon.h"
#include <stack.h>
#include <math.h>
#include "Balise.h"
#include "TriangleStrip.h"


void LocalisationGraph::Node::PrintConfiguration(FILE * fp)
{
    fprintf(fp,"Theta = %e\n",theta);
    poly->Print(fp);
}

void LocalisationGraph::Node::Print(FILE * fp)
{
    int i;
    fprintf(fp,"Address = %p\n",this);
    fprintf(fp,"Theta = %e\n",theta);
    fprintf(fp,"Connex Id = %d\n",connId);
    poly->Print(fp);
    fprintf(fp,"Connections[%d] : ",connection.size());
    for (i=0;i<connection.size();i++)
            fprintf(fp,"%p ",connection.elementAt(i));
    fprintf(fp,"\n\n");
}


void LocalisationGraph::Node::exploreAndMark(int mark)
{
    queue<Node*> Q;
    Node *current, *son;
    connId = mark;
    Q.push(this);
    int i;

    while (!Q.empty())
    {
        current = Q.front();
        Q.pop();
        for (i=0;i<current->connection.size();i++)
        {
            son = (Node*)(current->connection.elementAt(i));
            if (son->connId < 0)
            {
                son->connId = mark;
                Q.push(son);
            }
        }
    }
}

void LocalisationGraph::Layer::Print(FILE*fp)
{
        int j;
        fprintf(fp,"Layer %f : %d\n",theta,nodes->size());
        for (j=0;j<nodes->size();j++)
                ((Node *)(nodes->elementAt(j)))->Print(fp);
}

LocalisationGraph::LocalisationGraph(Polygon *ws,double tstep)
{
        if (ws == NULL) {printf("Unexpected Null workspace\n");}
        if (tstep == 0) {printf("Unexpected zero theta step\n");}
        workSpace = ws;
        theta_step = tstep;
        ConnexParts = -1;
        graph = new Vector();
}

void LocalisationGraph::buildTriStrips()
{
        int i;
        for (i=0;i<graph->size();i++)
                ((Layer*)(graph->elementAt(i)))->buildTriStrips();
}

void LocalisationGraph::Layer::buildTriStrips()
{
        int i;
        for (i=0;i<nodes->size();i++)
                ((Node*)(nodes->elementAt(i)))->buildTriStrips();
}

void LocalisationGraph::Node::buildTriStrips()
{
        poly->buildTriStrips();
}

LocalisationGraph::LocalisationGraph(FILE * fp)
{
        int i,n;
        address_mapper amap;
        fscanf(fp," #Layers = %d ",&n);
        fscanf(fp," Theta step = %le ",&theta_step);
        fscanf(fp," Connex Parts = %d ",&ConnexParts);
        fscanf(fp," Work space = ");
        workSpace = new Polygon();
        workSpace->Read(fp);
        graph = new Vector();
        for (i=0;i<n;i++)
                graph->addElement(new Layer(fp,&amap));
        // update pointer links
        for (i=0;i<n;i++)
                ((Layer*)(graph->elementAt(i)))->updateLinks(&amap);
}

LocalisationGraph::Layer::Layer(FILE * fp,address_mapper* amap)
{
        int j,n;
        fscanf(fp," Layer %le : %d ",&theta,&n);
        nodes = new Vector();
        for (j=0;j<n;j++)
                nodes->addElement(new Node(fp,amap));
}

LocalisationGraph::Node::Node(FILE * fp,address_mapper* amap)
{
    int i,a,n;
    score = -1;
    fscanf(fp," Address = %x ",&a);
    (*amap)[a]=this;
    fscanf(fp,"Theta = %le\n",&theta);
    fscanf(fp," Connex Id = %d ",&connId);
    poly=new VisibilityPolygon(fp);
    fscanf(fp," Connections[ %d ] : ",&n);
    for (i=0;i<n;i++)
    {
            fscanf(fp," %x ",&a);
            connection.addElement((Object*)(a));
    }
}

void LocalisationGraph::Layer::updateLinks(address_mapper* amap)
{
        int j;
        for (j=0;j<size();j++)
                getNode(j)->updateLinks(amap);
}

void LocalisationGraph::Node::updateLinks(address_mapper* amap)
{
        int i;
        for (i=0;i<connection.size();i++)
                connection.setElement(i,(*amap)[(int)(connection[i])]);
}

LocalisationGraph::~LocalisationGraph()
{
        graph->deleteAll();
        delete graph;
        graph = NULL;
        VisibilityPolygon::deleteVisibilityInformations();
        delete workSpace;
}
                

Vector* LocalisationGraph::partitionne(Vector *balisesList,Polygon * workSpace)
{
        Polygon * ws = new Polygon(workSpace);
        Balise* balise;
        VisibilityPolygon * P = new VisibilityPolygon(ws);
        Vector *part, *nextPart;
        int i,j;
        part = new Vector();
        part->addElement(P);
        for (i=0;i<balisesList->size();i++)
        {
                balise = (Balise*)(balisesList->elementAt(i));
                nextPart = new Vector();
                for(j=0;j<part->size();j++)
                {
                        P = (VisibilityPolygon*)(part->elementAt(j));
                        P->split(balise,nextPart);
                }
                part->deleteAll();
                delete part;
                part = nextPart;
                nextPart = NULL;
        }
        return part;                
}

void LocalisationGraph::filterPartition(Vector * partition,Vector * usable)
{
        int i;

        for (i=partition->size()-1;i>=0;i--)
        {
                VisibilityPolygon * MP;
                Polygon * P;
                int m;
                MP = ((VisibilityPolygon*)(partition->elementAt(i)));
                P = MP->getPolygon();
                m = MP->getMark();
                if ((m >= 2)&&(P->getArea()>5))
                {
                        partition->deleteElement(i);
                        usable->addElement(MP);
                }
        }
}


void LocalisationGraph::addLayer(Vector *balisesList,
                double theta,Polygon *workSpace)
{
        Layer *layer=new Layer(theta);
        Vector *partition;
        Vector *usable=new Vector();
        int i;
        partition = partitionne(balisesList,workSpace);
        filterPartition(partition,usable);
        for (i=0;i<usable->size();i++)
                layer->addNode(new Node((VisibilityPolygon*) 
                                        (usable->elementAt(i)),theta));
        graph->addElement(layer);
        // Destruction du vecteur, pas des elements car ils sont
        // dans le graphe
        delete usable;
        // Destruction des polygones non utilises dans le graphe
        partition->deleteAll();
        // Destruction du vecteur cree dans partitionne
        delete partition;
}


void LocalisationGraph::Layer::buildLinks()
{
    int i,j;
    for (i=0;i<nodes->size();i++)
    {
        Node * Pi = (Node*)(nodes->elementAt(i));
        for (j=0;j<i;j++)
        {
            Node * Pj = (Node*)(nodes->elementAt(j));
            Polygon *pi, *pj;
            pi = Pi->poly->getPolygon();
            pj = Pj->poly->getPolygon();
            Polygon * Union = pi->Union(pj);
            if (Union->numPartConnex() == 1)
                Union->cut();
            if (Union->numPartConnex() == 1)
            {
                Pi->connection.addElement(Pj);
                Pj->connection.addElement(Pi);
            }
            delete Union;
        }
    }
}
            

    


    
void LocalisationGraph::computeGraphInterLayer(int indexNew,int indexRef)
{
    int i,j;
    Layer * layerNew = (Layer *)(graph->elementAt(indexNew));
    Layer * layerRef = (Layer *)(graph->elementAt(indexRef));
    for (i=0;i<layerNew->size();i++)
    {
        Node * Pi = layerNew->getNode(i);
        for (j=0;j<layerRef->size();j++)
        {
            Node * Pj = layerRef->getNode(j);
            Polygon *pi, *pj;
            pi = Pi->poly->getPolygon();
            pj = Pj->poly->getPolygon();
            Polygon * inter = pi->Intersection(pj);
            if (!inter->isEmpty())
            {
                    Pi->connection.addElement(Pj);
                    Pj->connection.addElement(Pi);
            }
            delete inter;
        }
    }
}



void LocalisationGraph::buildGraphLinks()
{
    int i;
    for (i=0;i<graph->size();i++)
    {
        printf(".");fflush(stdout);
        ((Layer*)(graph->elementAt(i)))->buildLinks();
    }
    printf("\n");
    
    if (graph->size()>=2)
        computeGraphInterLayer(0,graph->size()-1);

    if (graph->size()>2)
        for (i=0;i<graph->size()-1;i++)
        {
            printf(".");fflush(stdout);
            computeGraphInterLayer(i+1,i);
        }
    printf("\n");
}

void LocalisationGraph::buildSecureArea(Polygon * workSpace,char * filename)
{
    Polygon *U, *I, *tmp; 
    Layer *layer;
    Node *N;
    int i,j;
    I = new Polygon(workSpace);
    for (i=0;i<graph->size();i++)
    {
        layer = (Layer*)(graph->elementAt(i));
        U = new Polygon();
        for (j=0;j<layer->size();j++)
        {
            N = layer->getNode(j);
            tmp = U;
            U = U->Union(N->poly->getPolygon());
            delete tmp;
        }
        tmp = I;
        I = I->Intersection(U);
        delete tmp;
        delete U;
    }
    printf("Zone securisee : %f / %f - %f %%\n",I->getArea(),workSpace->getArea(),I->getArea() / workSpace->getArea());
    FILE * fp = fopen(filename,"w");
    if (fp != NULL)
    {
        I->Print(fp);
        fclose(fp);
    }
    else
        printf("Unable to save secure area in %s\n",filename);
    delete I;
}


int LocalisationGraph::markConnexPart()
{
    int mark = 0;
    int maxId = -1;
    int i,j;
    Node * n;
    Layer * level;
    for (i=0;i<graph->size();i++)
    {
        level = (Layer*)(graph->elementAt(i));
        for (j=0;j<level->size();j++)
        {
            n = level->getNode(j);
            if (n->connId > maxId) maxId=n->connId;
            if (n->connId<0)
            {
                n->exploreAndMark(mark);
                mark += 1;
            }
        }
    }
    // Nombre des parties connexes
    if ((mark == 0) && (maxId>-1))
        // Le graphe etait deja marqué (relecture par ex)
        ConnexParts = maxId + 1; 
    else
        ConnexParts = mark;
    return mark;
}       


double LocalisationGraph::computeVolume()
{
        double Volume = 0;
        int i,j;
        for (i=0;i<graph->size();i++)
        {
                Layer * layer = (Layer*)(graph->elementAt(i));
                for (j=0;j<layer->size();j++)
                {
                        Node * N = layer->getNode(j);
                        Polygon * P = N->poly->getPolygon();
                        Volume += P->getArea()*theta_step;
                }
        }
//      cout << "Volume occupe : " << Volume << " / " << 
//              workSpace.getArea()*2*M_PI << endl;
        return Volume/(workSpace->getArea()*2*M_PI);
}


void LocalisationGraph::Print(FILE * fp)
{
        int i;
        fprintf(fp,"#Layers = %d\n",graph->size());
        fprintf(fp,"Theta step = %f\n",theta_step);
        fprintf(fp,"Connex Parts = %d\n",ConnexParts);
        fprintf(fp,"Work space = ");
        workSpace->Print(fp);
        for (i=0;i<graph->size();i++)
                ((Layer*)(graph->elementAt(i)))->Print(fp);
}


// theta en radian entre 0 et 2Pi
LocalisationGraph::Configuration 
LocalisationGraph::getConfiguration(double x,
                double y,double theta)
{
        double t = atan2(sin(theta),cos(theta));
        if (t<0) t = t + 2* M_PI;
        int layer = (int)(rint(t / theta_step));
        return ((Layer*)(graph->elementAt(layer)))->getConfiguration(x,y);
}

LocalisationGraph::Configuration 
LocalisationGraph::Layer::getConfiguration(double x,double y)
{
        int i;
        for (i=0;i<nodes->size();i++)
        {
                Node * n = (Node*)(nodes->elementAt(i));
                if (n->contains(x,y))
                        return n;
        }
        return NULL;
}

                        


void LocalisationGraph::resetPath()
{
        int i;
        for (i=0;i<graph->size();i++)
                ((Layer*)(graph->elementAt(i)))->resetPath();
}


void LocalisationGraph::Layer::resetPath()
{
        int i;
        for (i=0;i<nodes->size();i++)
                ((Node*)(nodes->elementAt(i)))->resetPath();
}


void LocalisationGraph::Node::resetPath()
{
        score = -1;
        predecessorInPath = NULL;
}



LocalisationGraph::Path 
LocalisationGraph::findPath(Configuration init,Configuration end)
{

        if (init == end)
        {
            Path path = new Vector();
            path->addElement(init);
            return path;
        }
        
        // recherche du plus court chemin : disjkstra
        int i;
        Heap heap;
        Heap::iterator it;

        resetPath();
        heap.insert(HeapElt(0,init));
        init->score = 0;

        while (!heap.empty())
        {
                Node * pit;
                it = heap.begin();
                heap.erase(it);
                pit = ((*it).second);
#ifdef DEBUG
                pit->Print();
#endif
                for (i=0;i<pit->connection.size();i++)
                {
                        Node * p = (Node*)(pit->connection.elementAt(i));
#ifdef DEBUG
                        printf("\tSon : ");
#endif
                        if ((pit->score + 1 < p->score) || (p->score < 0))
                        {
#ifdef DEBUG
                                printf("****** ");
#endif
                                p->score = pit->score + 1;
                                p->predecessorInPath = pit;
                                heap.insert(HeapElt(p->score,p));
                        }
#ifdef DEBUG
                        p->Print();
#endif
                }
        }
        
        if (end->predecessorInPath == NULL)
                return NULL;
            
        // S'il existe un chemin : extraction
        Vector reverse;
        Vector * result = new Vector();
        Node * tmp = end;
        while (tmp != NULL)
        {
                reverse.addElement(tmp);
                tmp = tmp->predecessorInPath;
        }
        for (i=reverse.size()-1;i>=0;i--)
                result->addElement(reverse.elementAt(i));

        return (Path)result;
}

void LocalisationGraph::printPath(FILE *fp,Path path)
{
        int i;
        if (path == NULL)
        {
                fprintf(fp,"Path length : 0\n");
                return;
        }
        fprintf(fp,"Path length : %d\n",path->size());
        for (i=0;i<path->size();i++)
        {
                fprintf(fp,"Step %d : \n",i);
                ((Node*)(path->elementAt(i)))->PrintConfiguration(fp);
        }
        // fprintf(fp,"Path end\n");
}

void LocalisationGraph::cleanPath(Path path)
{
    delete path;
}

void LocalisationGraph::cleanConfiguration(Configuration c)
{
    // delete c;
}


static void printColorTable(FILE * f,const VtkPoints & points)
{
    fprintf(f,"\n\nPOINT_DATA %d\n",points.size());
    fprintf(f,"SCALARS my_scalars float\nLOOKUP_TABLE custom_table\n");
    for (unsigned int i=0;i<points.size();i++)
    {
        fprintf(f,"%f\n",points[i].c);
    }

    fprintf(f,"\nLOOKUP_TABLE custom_table 15\n");
    fprintf(f,"0.2\t0.2\t0.2\t1.0\n");
    fprintf(f,"0.0\t0.0\t0.5\t1.0\n");
    fprintf(f,"0.0\t0.5\t0.5\t1.0\n");
    fprintf(f,"0.0\t0.5\t0.0\t1.0\n");
    fprintf(f,"0.5\t0.5\t0.0\t1.0\n");
    fprintf(f,"0.5\t0.0\t0.0\t1.0\n");
    fprintf(f,"0.5\t0.0\t0.5\t1.0\n");
    fprintf(f,"0.0\t0.0\t1.0\t1.0\n");
    fprintf(f,"0.0\t1.0\t1.0\t1.0\n");
    fprintf(f,"0.0\t1.0\t0.0\t1.0\n");
    fprintf(f,"1.0\t1.0\t0.0\t1.0\n");
    fprintf(f,"1.0\t0.0\t0.0\t1.0\n");
    fprintf(f,"1.0\t0.0\t0.0\t1.0\n");
    fprintf(f,"1.0\t0.0\t1.0\t1.0\n");
    fprintf(f,"0.8\t0.8\t0.8\t1.0\n");
}
    



void LocalisationGraph::VtkPrint(FILE * mainFile,FILE * wsFile,
        double xScale,double yScale,double zScale)
{
    VtkPoints points;
    VtkTriStrips tristrips;
    VtkPolygons polygons;
    unsigned int i,j;
    TriangleStrip * t;
    Layer * l;
    Node * n;
// graph 
    if (getNbConnexParts() <= 0)
        markConnexPart();

    for (i=0;i<(unsigned int)(graph->size());i++)
    {
        l = ((Layer*)(graph->elementAt(i)));
        for (j=0;j<(unsigned int)(l->size());j++)
        {
            n = l->getNode(j);
            t = n->getTriStrip();
            t->collectVtkPoints(points,tristrips,l->theta, n->getId());
        }
    }

    for (i=0;i < points.size();i++)
    {
        VtkPoint3D & P = points[i];
        P.x *= xScale;
        P.y *= yScale;
        P.z *= zScale;
        //double d = P.c;
        P.c = (P.c+1) / (double)(ConnexParts);
        //printf("Avant : %e -- Apres : %e \n",d,P.c);
    }
            
    
    fprintf(mainFile,"# vtk DataFile Version 1.0\n");
    fprintf(mainFile,"Configuration Space\n");
    fprintf(mainFile,"ASCII\nDATASET POLYDATA\n");
    fprintf(mainFile,"POINTS %d float\n",points.size());
    for (i=0;i<points.size();i++)
    {
        fprintf(mainFile,"%f %f %f\n",(points[i].x),
                (points[i].y),(points[i].z));
    }

    fprintf(mainFile,"\nTRIANGLE_STRIPS %d %d",tristrips.size(),
            tristrips.size()+points.size());
    for (i=0;i<tristrips.size();i++)
    {
        fprintf(mainFile,"\n%d ",tristrips[i].size());
        for (j=0;j<tristrips[i].size();j++)
            fprintf(mainFile,"%d ",tristrips[i][j]);
    }

    printColorTable(mainFile,points);

// WorkSpace
    points.erase(points.begin(),points.end());
    workSpace->collectVtkPoints(points,polygons);
    for (i=0;i < points.size();i++)
    {
        VtkPoint3D & P = points[i];
        P.x *= xScale;
        P.y *= yScale;
    }
            
    
    fprintf(wsFile,"# vtk DataFile Version 1.0\n");
    fprintf(wsFile,"workspace\n");
    fprintf(wsFile,"ASCII\nDATASET POLYDATA\n");
    fprintf(wsFile,"POINTS %d float\n",points.size());
    for (i=0;i<points.size();i++)
    {
        fprintf(wsFile,"%f %f %f\n",(points[i].x),
                (points[i].y),(points[i].z));
    }
    fprintf(wsFile,"\nLINES %d %d\n",polygons.size(),
            points.size() + 2 * polygons.size());
    for (i=0;i<polygons.size();i++)
    {
        fprintf(wsFile,"%d ",polygons[i].size()+1);
        for (j=0;j<polygons[i].size();j++)
            fprintf(wsFile,"%d ",polygons[i][j]);
        fprintf(wsFile,"%d\n",polygons[i][0]);
    }
    printColorTable(wsFile,points);

}