Triangulation

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
frjulien112
Posts: 1
Joined: Thu Apr 24, 2008 10:00 am
Location: Paris, France

Triangulation

Post by frjulien112 »

Hello.

I've been using Irrlicht for quite a long time, and after using contribution from many, i'd like to contribuate too.

I'm doing a 3D visualition tool for geographic purpose.

Here is some code too draw from 2d coordinates of a region, a mesh representing this region

There is a class triangulate, and few code to use this class in the main program.

I might be ugly code, but i'm not a programmer ...

Triangulate.cpp

Code: Select all



#include "triangulate.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>



data::data* Triangulate::dt;
scene::SMeshBuffer* Triangulate::mb;

static const float EPSILON=5;
int Triangulate::debut=0;
int Triangulate::fin=0;

long int Triangulate::Area()
{

  int n = fin-debut+1;

  float A=0;

  for(int p=fin,q=debut; q<fin+1; p=q++)
  {

   //std::cout<<"A="<<A<<"+"<<dt->map[p]->x*dt->map[q]->y - dt->map[q]->x*dt->map[p]->y<<std::endl;
    A+= (dt->map[p]->x/1000)*(dt->map[q]->y/1000) - (dt->map[q]->x/1000)*(dt->map[p]->y/1000) ;
  }
  return A/2;
}




   /*
     InsideTriangle decides if a point P is Inside of the triangle
     defined by A, B, C.
   */
bool Triangulate::InsideTriangle(long int Ax, long int Ay,
                      long int Bx, long int By,
                      long int Cx, long int Cy,
                      long int Px, long int Py)

{
  long long int ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
 long long int cCROSSap, bCROSScp, aCROSSbp;

  ax = Cx - Bx;  ay = Cy - By;
  bx = Ax - Cx;  by = Ay - Cy;
  cx = Bx - Ax;  cy = By - Ay;
  apx= Px - Ax;  apy= Py - Ay;
  bpx= Px - Bx;  bpy= Py - By;
  cpx= Px - Cx;  cpy= Py - Cy;

  aCROSSbp = ax*bpy - ay*bpx;
  cCROSSap = cx*apy - cy*apx;
  bCROSScp = bx*cpy - by*cpx;

  return ((aCROSSbp > 0) && (bCROSScp > 0) && (cCROSSap > 0));
};

bool Triangulate::Snip(int u,int v,int w,int n,int *V)
{
  int p;
  long long int Ax, Ay, Bx, By, Cx, Cy, Px, Py;

  Ax = dt->map[V[u]]->x;
  Ay = dt->map[V[u]]->y;

  Bx = dt->map[V[v]]->x;
  By = dt->map[V[v]]->y;

  Cx = dt->map[V[w]]->x;
  Cy = dt->map[V[w]]->y;

  if ((Ax==Bx)&&(Ay==By)) return true;
  if ((Ax==Cx)&&(Ay==Cy)) return true;
  if ((Cx==Bx)&&(Cy==By)) return true;


  //std::cout<<"0>"<<(float)(Bx-Ax)/100*(Cy-Ay)/100 - (By-Ay)/100*(Cx-Ax)/100<<std::endl; ;
  if ( 0 > (float)(Bx-Ax)/100*(Cy-Ay)/100 - (By-Ay)/100*(Cx-Ax)/100 ) return false;

  for (p=0;p<n;p++)
  {
    if( (p == u) || (p == v) || (p == w) ) continue;
    Px = dt->map[V[p]]->x;
    Py = dt->map[V[p]]->y;
    if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) {
        //std::cout<<"uvwp"<<u<<","<<v<<","<<w<<","<<p<<std::endl;
        return false;
    }
  }
  //std::cout<<"ok:"<<u<<","<<v<<","<<w<<std::endl; ;
  return true;
}

bool Triangulate::Process(int deb, int fi)
{
  /* allocate and initialize list of Vertices in polygon */

            debut=deb;
            fin=fi;

  int n = fin-debut+1;
  // std::cout<<"n="<<n<<std::endl;
  if ( n < 3 ) return false;

  int *V = new int[n];

  /* we want a counter-clockwise polygon in V */
  int v;

   //std::cout<<"aire="<<Area()<<std::endl;
  if ( 0<Area() )
    for (v=0; v<n; v++) V[v] = v+debut;
  else
    for(v=0; v<n; v++) V[v] = fin-v;

   // Decomplex(V,n);

  int nv = n;


  /*  remove nv-2 Vertices, creating 1 triangle every time */
  int count = 5*nv;   /* error detection */

  for(int m=0, v=nv-1; nv>2; )
  {
    /* if we loop, it is probably a non-simple polygon */
    if (0 >= (count--))
    {
      std::cout<<"Triangulate: ERROR - probable bad polygon!";
      return false;
    }

    /* three consecutive vertices in current polygon, <u,v,w> */
    int u = v  ; if (nv <= u) u = 0;     /* previous */
    v = u+1; if (nv <= v) v = 0;     /* new v    */
    int w = v+1; if (nv <= w) w = 0;     /* next     */
    //std::cout<<"uvw:"<<u<<","<<v<<","<<w<<","<<n<<"="<<Area(V[w],V[v])<<"<>"<<":"<<std::endl;

    if ( Snip(u,v,w,nv,V) )
    {
      int a,b,c,s,t;

      /* true names of the vertices */
      a = V[u]; b = V[v]; c = V[w];

      /* output Triangle */
      mb->Indices.push_back(a-debut);
     mb->Indices.push_back(c-debut);
      mb->Indices.push_back(b-debut);

      m++;

      /* remove v from remaining polygon */
      for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--;

      /* resest error detection counter */
      count = 5*nv;
      //std::cout<<"uvw:"<<u<<","<<v<<","<<w<<","<<n<<"="<<"<>"<<":"<<std::endl;

    }
  }



  delete V;

  return true;
}


Triangulate::Triangulate(data::data* d, scene::SMeshBuffer* m){
            dt=d;
            mb=m;
            debut=0;
            fin=0;
        };

Triangulate::~Triangulate(){};

/************************************************************************/
/*** END OF CODE SECTION TRIANGULATE.CPP BEGINNING OF TEST.CPP A SMALL **/
/*** TEST APPLICATION TO DEMONSTRATE THE USAGE OF THE TRIANGULATOR     **/
/************************************************************************/


triangulate.h

Code: Select all

// COTD Entry submitted by John W. Ratcliff [jratcliff@verant.com]

// ** THIS IS A CODE SNIPPET WHICH WILL EFFICIEINTLY TRIANGULATE ANY
// ** POLYGON/CONTOUR (without holes) AS A STATIC CLASS.  THIS SNIPPET
// ** IS COMPRISED OF 3 FILES, TRIANGULATE.H, THE HEADER FILE FOR THE
// ** TRIANGULATE BASE CLASS, TRIANGULATE.CPP, THE IMPLEMENTATION OF
// ** THE TRIANGULATE BASE CLASS, AND TEST.CPP, A SMALL TEST PROGRAM
// ** DEMONSTRATING THE USAGE OF THE TRIANGULATOR.  THE TRIANGULATE
// ** BASE CLASS ALSO PROVIDES TWO USEFUL HELPER METHODS, ONE WHICH
// ** COMPUTES THE AREA OF A POLYGON, AND ANOTHER WHICH DOES AN EFFICENT
// ** POINT IN A TRIANGLE TEST.
// ** SUBMITTED BY JOHN W. RATCLIFF (jratcliff@verant.com) July 22, 2000

/**********************************************************************/
/************ HEADER FILE FOR TRIANGULATE.H ***************************/
/**********************************************************************/


#ifndef TRIANGULATE_H

#define TRIANGULATE_H

/*****************************************************************/
/** Static class to triangulate any contour/polygon efficiently **/
/** You should replace Vector2d with whatever your own Vector   **/
/** class might be.  Does not support polygons with holes.      **/
/** Uses STL vectors to represent a dynamic array of vertices.  **/
/** This code snippet was submitted to FlipCode.com by          **/
/** John W. Ratcliff (jratcliff@verant.com) on July 22, 2000    **/
/** I did not write the original code/algorithm for this        **/
/** this triangulator, in fact, I can't even remember where I   **/
/** found it in the first place.  However, I did rework it into **/
/** the following black-box static class so you can make easy   **/
/** use of it in your own code.  Simply replace Vector2d with   **/
/** whatever your own Vector implementation might be.           **/
/*****************************************************************/

#include <irrlicht.h>
#include "data.h"


using namespace irr;

class Triangulate
{
public:

        Triangulate(data::data* d, scene::SMeshBuffer* m);

        virtual ~Triangulate();

  // triangulate a contour/polygon, places results in STL vector
  // as series of triangles.
  static bool Process(int deb, int fi);

  // compute area of a contour/polygon
  static long int Area();

  // decide if point Px/Py is inside triangle defined by
  // (Ax,Ay) (Bx,By) (Cx,Cy)
  static bool InsideTriangle(long int Ax, long int Ay,
                      long int Bx, long int By,
                      long int Cx, long int Cy,
                      long int Px, long int Py);


private:

  static void Decomplex(int* V,int n);
  static data::data* dt;
  static  scene::SMeshBuffer* mb;
  static int debut;
  static int  fin;

  static bool Snip(int u,int v,int w,int n,int *V);

};


#endif
And in main :

Code: Select all

void affichage::dessinecarte()
{
       if (dt->getnbpointmap()<3) return;
        scene::SMesh* msh = new scene::SMesh();
        core::aabbox3d<f32> Box;
        std::cout<<"mb:"<<msh->getMeshBufferCount()<<std::endl;
        scene::SMeshBuffer* mb = new scene::SMeshBuffer();
        std::cout<<"mb:"<<msh->getMeshBufferCount()<<std::endl;
        std::cout<<"index:"<<mb->getIndexCount ()<<std::endl;
        std::cout<<"vertex:"<<mb->getVertexCount ()<<std::endl;
        video::S3DVertex tv;
        int debut=0;
        Triangulate* t=new Triangulate(dt,mb);
        std::cout<<dt->getminy()<<"<"<<dt->getmaxy()<<","<<dt->getminx()<<"<"<<dt->getmaxx()<<" nbpt="<<dt->getnbpointmap()<<std::endl;

        //driver->setTransform(video::ETS_WORLD, core::matrix4());

        for(int i=0;i<dt->getnbpointmap();i++) {

       //     if (i==80000) driver->draw3DLine (core::vector3df(-dt->map[i-1]->x,
       //     dt->map[i-1]->y,0),core::vector3df(-dt->map[i]->x,
       //     dt->map[i]->y,0),video::SColor(255, 255, 255, 255));
      //  smgr->addCubeSceneNode( 5 ,NULL,-1,core::vector3df(-dt->map[i]->x,dt->map[i]->y,100));

            tv=video::S3DVertex(-dt->map[i]->x,
            dt->map[i]->y,0,0,0,1, video::SColor(100,255,0,0), 0, 0);
            mb->Vertices.push_back(tv);
            if (i==dt->getnbpointmap()-1) {
                t->Process(debut,dt->getnbpointmap()-1);
                msh->recalculateBoundingBox();
                msh->addMeshBuffer(mb);
                mb->drop();
                continue;

                }
            if (strcmp (dt->map[i]->dct,dt->map[i+1]->dct) != 0) {
                t->Process(debut,i);
                debut=i+1;
                msh->recalculateBoundingBox();
                msh->addMeshBuffer(mb);
                mb->drop();
                mb = new scene::SMeshBuffer();
                t=new Triangulate(dt,mb);
                std::cout<<"boulcecarte"<<i<<","<<dt->map[i]->dct<<","<<dt->map[i+1]->dct<<","<<std::endl;

            }


          }


    scene::SAnimatedMesh   *anmmesh = new scene::SAnimatedMesh;
    std::cout<<"mb:"<<msh->getMeshBufferCount()<<std::endl;

    anmmesh->addMesh(msh);
    mcarte=smgr->addAnimatedMeshSceneNode(anmmesh);

    std::cout<<"nb material="<<mcarte->getMaterialCount()<<std::endl;
    mcarte->getMaterial(0).EmissiveColor.set(255, 200, 200, 0);
    mcarte->getMaterial(0).DiffuseColor.set(255, 255, 255, 0);
    if (mcarte->getMaterialCount()>1) {
    mcarte->getMaterial(1).EmissiveColor.set(255, 0, 200, 0);
    mcarte->getMaterial(1).DiffuseColor.set(255, 0, 255, 0);
    }
    if (mcarte->getMaterialCount()>2) {
    mcarte->getMaterial(2).DiffuseColor.set(255, 0, 0, 255);
    mcarte->getMaterial(2).EmissiveColor.set(255, 0, 0, 200);
    }

    if (mcarte->getMaterialCount()>3) {
    mcarte->getMaterial(3).EmissiveColor.set(255, 0, 200, 200);
    mcarte->getMaterial(3).DiffuseColor.set(255, 0, 255,200);
    }

    if (mcarte->getMaterialCount()>4) {
        int nbdep=4;
    while (mcarte->getMaterialCount()>nbdep){
        mcarte->getMaterial(nbdep).EmissiveColor.set(255, stg->hasard(0,2565), stg->hasard(0,255), stg->hasard(0,255));
        mcarte->getMaterial(nbdep).DiffuseColor.set(255, stg->hasard(0,255), stg->hasard(0,255),stg->hasard(0,255));
        nbdep++;
    }
    }
    mcarte->setMaterialFlag(video::EMF_LIGHTING, true);
    mcarte->setAutomaticCulling(irr::scene::EAC_OFF);


        std::cout<<"mb:"<<msh->getMeshBufferCount()<<std::endl;
        std::cout<<"index:"<<mb->getIndexCount ()<<std::endl;
        std::cout<<"vertex:"<<mb->getVertexCount ()<<std::endl;
}
Post Reply