Discussion:
[C/C++] Áreas, centros de gravedad, etc.
(demasiado antiguo para responder)
Han Solo
2003-08-11 16:41:41 UTC
Permalink
Hola a todos.

Alguien sabe si existe alguna biblioteca de funciones en C/C++ (en
linux), para calcular áreas, centros de gravedad, inercias... ese tipo
de cosas. Es que me da una pereza horrible ponerme a programarlo...

Gracias por anticipado.

Un Saludo
- --
Han Solo
The Rebel Alliance

Emacs is not on every system

So what? [...] Do you tell your administrative people to stick with
notepad.exe? Do you tell your fat kids they can only have the crummy
games that come with their video games or plain dress that comes with
Barbie?
Gorka Olaizola
2003-08-11 18:38:58 UTC
Permalink
Post by Han Solo
Alguien sabe si existe alguna biblioteca de funciones en C/C++ (en
linux), para calcular áreas, centros de gravedad, inercias... ese tipo
de cosas. Es que me da una pereza horrible ponerme a programarlo...
No sé si es lo que buscar pero esta librería[1] de física la suelen usar en
los simuladores de juegos de coches, así que supongo que tendrá algo para
calcular centros de gravedad e inercias.

[1] http://opende.sourceforge.net/
--
musg0 @ irc http://helvete.escomposlinux.org/
(o_
//\
V_/ "bene vixit qui bene latuit". René Descartes
J.A. Gutierrez
2003-09-03 06:44:50 UTC
Permalink
In es.comp.lenguajes.c Han Solo <***@escomposlinux.org> wrote:

: Alguien sabe si existe alguna biblioteca de funciones en C/C++ (en
: linux), para calcular áreas, centros de gravedad, inercias... ese tipo
: de cosas. Es que me da una pereza horrible ponerme a programarlo...

Para areas y centros de gravedad (suponiendo que hablas de
poligonos planos), lo mas sencillo es descomponer primero
el poligono en triangulos. Luego, es inmediato.
Si el poligono tiene agujeros, necesitaras una fase previa
de eliminacion de los mismos; si te interesa, tambien tengo
codigo para eso.

En el codigo siguiente la unica parte no portable es (creo)
la funcion redraw().

---------------------------------------------------------------------------
/*
* (c) SPDsoft 1995
* Split a polygon.
*/

#include <stdlib.h>
#include <math.h>

#define EZERO

#define xcomp(p,i) (*(p+2*i))
#define ycomp(p,i) (*(p+2*i+1))

#define xpdrw(x) (short)((((x) - xmin)*scale) + MARGIN)
#define ypdrw(y) (short)(wh - MARGIN - ((y)-ymin) * scale )

#ifdef EZERO
# define EPSILLON 0
# define eq_zero(x) ((x) == EPSILLON)
#else
# define EPSILLON 1e-5
# define eq_zero(x) (fabs(x) <= EPSILLON)
#endif

#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))

static float test_rect( int a,int b,int c);
static int getprev(int i );
static int getpost(int i );


float _p1[] = { 0,0,-10,10,-10,-15,8,-20,-10,-5,15,5,10,-7,20,0,5,20 };
float _p[] = { 0,0 ,-8,8,0,5,8,8,0,3,0,-10,5,-20,20,20,15,15,-20,10,18,18,20,20,-30,15,0,-10 };
float _p2[] = { 5,-5,10,-10,5,5,10,10,-5,5,-10,10,-5,-5,-10,-10 };
float _p3[] = { 0,0,0,5,5,10,0,10,0,5,-5,5,-5,0 };


int tri[50][3];
int ntri;


float *p = _p, *endp = (_p+sizeof(_p)/sizeof(float));
char *p_out;

float xmin, xmax,
ymin, ymax;

float lx, ly, scale;
int nvert=sizeof(_p)/sizeof(float)/2;

void init_geom(void)
{
float *f;
int j_prev,
j_post,
i_prev,
i_post,
i,j;

float fj1_prev,
fj2_prev,
fj3_prev,

fj1_post,
fj2_post,
fj3_post,

f1,f2,f3;

int nrest,
n_hits,
n_hits_out,
valid,
found;

/*
* Bounding box
*/

xmin=xmax=*p;
ymin=ymax=*(p+1);

for(f=p; f<endp; f++)
{
if ( *f > xmax ) xmax = *f;
if ( *f < xmin ) xmin = *f;
f++;
if ( *f > ymax ) ymax = *f;
if ( *f < ymin ) ymin = *f;
}

lx = xmax - xmin;
ly = ymax - ymin;

if (NULL==( p_out = calloc((size_t)nvert, sizeof(char))))
exit(1);

ntri = 0;

for( nrest = nvert; nrest > 2 ; )
{
/*
* Skip aligned
*/
found = 0;

for( i=0; i<nvert; i++ )
{
if (! *(p_out+i))
if ( eq_zero(test_rect( getprev(i),i,getpost(i))) )
{
*(p_out+i) = 1;
nrest --;
found = 1;
break;
}
}
if ( i!= nvert)
continue;


for( i=0; i<nvert; i++ )
{

/*
* Try to make tr(i-1,i,i+1)
*
* If tr is convex, discard it and try next
*/
valid = 0;

if(*(p_out+i))
continue;

i_prev = getprev(i);
i_post = getpost(i);

/*
* Discard left handed triangles
*/

if (test_rect( i_prev,i,i_post) < 0.0 )
continue;

/*
* Test against every other vertex
*/

valid = 1;

for( j=0; j<nvert; j++ )
{
if(
(*(p_out+j)) ||
(j==i_post) || (j==i_prev) || (j==i)
)
continue;


f1 = test_rect( i_post,i_prev, j);
f2 = test_rect( i_prev,i, j);
f3 = test_rect( i,i_post, j);

if ( (f1 < 0) || (f2 < 0) || (f3 < 0))
continue; /* it is outside */

if ( (f1 > 0) && (f2 > 0) && (f3 > 0))
{ /* it is inside */
valid = 0;
break;
}

j_prev = getprev(j);
j_post = getpost(j);

fj1_prev = test_rect ( i_post,i_prev, j_prev);
fj2_prev = test_rect ( i_prev,i, j_prev);
fj3_prev = test_rect ( i,i_post, j_prev);

fj1_post = test_rect ( i_post,i_prev, j_post);
fj2_post = test_rect ( i_prev,i, j_post);
fj3_post = test_rect ( i,i_post, j_post);

n_hits = 0;
n_hits_out = 0;

if ( eq_zero(f1) )
{
n_hits ++;
if (( fj1_prev > 0 ) || ( fj1_post > 0 ))
n_hits_out++;
}

if ( eq_zero(f2) )
{
n_hits ++;
if (( fj2_prev > 0 ) || ( fj2_post > 0 ))
n_hits_out++;
}

if ( eq_zero(f3) )
{
n_hits ++;
if (( fj3_prev > 0 ) || ( fj3_post > 0 ))
n_hits_out++;
}

if ( n_hits == n_hits_out )
{
valid = 0;
break;
}

}
/*
* all vertex tested
*/

if ( valid )
{
/*
* Make new triangle
*/
tri[ntri][0] = i_prev;
tri[ntri][1] = i;
tri[ntri][2] = i_post;

ntri ++;
nrest --;
*(p_out+i) = 1;
found = 1;
break;
}
}

if ( ! found )
{
exit(2);
/* PANIC!!!! Input Error */
}
}

return;

}

#define MARGIN 20

void redraw(WindowPtr theWindow)
{
short ww, wh;
float *f;
int i;
PenState PnSt;

GetPenState(&PnSt);
ShowPen();
PenSize(2,2);

ww = theWindow->portRect.right - theWindow->portRect.left ;
wh = theWindow->portRect.bottom - theWindow->portRect.top ;
scale = MIN((float) (ww- 2*MARGIN)/lx, (float)(wh- 2*MARGIN)/ly) ;

MoveTo( xpdrw(*p), ypdrw(*(p+1)) );
for(f=p; f<endp; f+=2)
LineTo( xpdrw(*f), ypdrw(*(f+1)) );
LineTo( xpdrw(*p), ypdrw(*(p+1)) );


PenSize(1,1);

for(i=0; i<ntri; i++)
{
MoveTo( xpdrw(xcomp(p , tri[i][2])), ypdrw(ycomp(p , tri[i][2])) );
LineTo( xpdrw(xcomp(p , tri[i][0])), ypdrw(ycomp(p , tri[i][0])) );
}
SetPenState(&PnSt);

}

static float test_rect(int a,int b,int c)
{
float ddd=xcomp(p,b);

return (
(xcomp(p,b)-xcomp(p,a))*(ycomp(p,c)-ycomp(p,a))+
(ycomp(p,a)-ycomp(p,b))*(xcomp(p,c)-xcomp(p,a))
);

}

static int getprev( int i )
{
int prev=i;

do
{
if (--prev==-1) prev = nvert -1;
}while( *(p_out+prev) );

return(prev);
}

static int getpost( int i )
{
int post=i;

do
{
if (++post==nvert) post = 0;
}while( *(p_out+post) );

return(post);
}
---------------------------------------------------------------------------
--
finger ***@shiva.cps.unizar.es for PGP /
.mailcap tip of the day: / La vida es una carcel
application/ms-tnef; cat '%s' > /dev/null / con las puertas abiertas
text/x-vcard; cat '%s' > /dev/null / (A. Calamaro)
Loading...