elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Introducción a Git (Primera Parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Problema con el par mas cercano.
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Problema con el par mas cercano.  (Leído 2,151 veces)
majojimu

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Problema con el par mas cercano.
« en: 9 Julio 2013, 08:55 am »

Hola.
Tengo un cuadrado y distintos puntos en un plano. De cada punto sabemos su ejex y ejey.  Pretendo calcular que punto es más cercano a cada vértice del cuadrado.

Cada punto se refiere a un peaton y tiene la siguiente estructura
Código
  1. struct Vpeaton
  2. {
  3.       int ad_peaton;     //numero del punto
  4.       double adg_x;      //eje x del punto
  5.       double adg_y;      //eje y del punto
  6. };
  7. typedef std::vector<Vpeaton> V_peaton;

Mientras que el cuadrado viene definido por los vertices (xsup,ysup), (xsup, yinf), (xinf,ysup) y (xinf,ysup).

Este es el código que he escrito para averiguar el punto más cercano a cada esquina del cuadrado. Pero no me funciona y no se en que falla.

Código
  1. V_peaton Areas;
  2. //buscar peston cercano a cada esquina.
  3.              distminXsYs = sqrt((xsup-Areas[0].adg_x)*(xsup-Areas[0].adg_x)+(ysup-Areas[0].adg_y)*(ysup-Areas[0].adg_y));
  4.              distminXiYs = sqrt((xinf-Areas[0].adg_x)*(xinf-Areas[0].adg_x)+(ysup-Areas[0].adg_y)*(ysup-Areas[0].adg_y));
  5.              distminXsYi = sqrt((xsup-Areas[0].adg_x)*(xsup-Areas[0].adg_x)+(yinf-Areas[0].adg_y)*(yinf-Areas[0].adg_y));
  6.              distminXiYi = sqrt((xinf-Areas[0].adg_x)*(xinf-Areas[0].adg_x)+(yinf-Areas[0].adg_y)*(yinf-Areas[0].adg_y));
  7.  
  8.              for(int i=1; i<Areas.size(); i++)  
  9.              {                  
  10.                    dist1 = sqrt((xsup-Areas[i].adg_x)*(xsup-Areas[i].adg_x)+(ysup-Areas[i].adg_y)*(ysup-Areas[i].adg_y));
  11.                    dist2 = sqrt((xinf-Areas[i].adg_x)*(xinf-Areas[i].adg_x)+(ysup-Areas[i].adg_y)*(ysup-Areas[i].adg_y));
  12.                    dist3 = sqrt((xsup-Areas[i].adg_x)*(xsup-Areas[i].adg_x)+(yinf-Areas[i].adg_y)*(yinf-Areas[i].adg_y));
  13.                    dist4 = sqrt((xinf-Areas[i].adg_x)*(xinf-Areas[i].adg_x)+(yinf-Areas[i].adg_y)*(yinf-Areas[i].adg_y));
  14.  
  15.                    if(dist1<distminXsYs)
  16.                    {
  17.                               distminXsYs=dist1;
  18.                               peaton_1=Areas[i].ad_peaton;
  19.                    }
  20.                    if (dist2<distminXiYs)
  21.                    {
  22.                               distminXiYs=dist2;
  23.                               peaton_2=Areas[i].ad_peaton;
  24.                    }                              
  25.                    if(dist3<distminXsYi);
  26.                    {
  27.                               distminXsYi=dist3;
  28.                               peaton_3=Areas[i].ad_peaton;
  29.                    }
  30.                    if(dist4<distminXiYi);
  31.                    {
  32.                               distminXiYi=dist4;
  33.                               peaton_4=Areas[i].ad_peaton;
  34.                    }
  35.            }


« Última modificación: 9 Julio 2013, 08:59 am por majojimu » En línea

engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Re: Problema con el par mas cercano.
« Respuesta #1 en: 9 Julio 2013, 09:08 am »

que tal si dices por que te da malo... es decir que te da y que esperabas? que datos pasaste y que te respondió?



En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
majojimu

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Re: Problema con el par mas cercano.
« Respuesta #2 en: 9 Julio 2013, 09:51 am »

que tal si dices por que te da malo... es decir que te da y que esperabas? que datos pasaste y que te respondió?



Tengo la siguiente lista de puntos.

Nº punto   Eje_x      Eje_y
0   -6.53      -0.52
1   3.93      -1.55
2   -4.92      4.84
3   -1.54      -2.35
4   -6.07      0.24
5   -4.04      -3.85
6   -2.29      3.31
7   -0.75      -4.69
8   -4.24      1.14
9   -0.48      -1.4
10   -1.69      2.06
11   -4.4      3.65
12   -1.67      5.68
13   -0.45      -0.8
14   -2.38      2.4
15   -2.06      -0.32
16   0.18      -2.88
17   -5.8      1.43
18   -2.58      -1.31
19   -1.17      -0.86
20   0.13      2.74
21   4.31      5.86
22   -1.59      -5.96
23   -0.93      -5.6
24   -6.21      2.17
25   1.84      5.79
26   -6.25      5.83
27   -4      -2.95
28   4.98      0.91
29   -0.68      6.54
30   -0.01      2.14
31   -3.01      1.62
32   0.1      -4.41
33   -1.22      3.68
34   0.08      0.96
35   -4.98      2.95
36   -6.3      -2.9
37   -5.98      -4.7
38   -4.03      5.74
39   -4.99      -2.45
40   -2.89      -6.16
41   -0.08      -2.07
42   5.25      5.31
43   -0.56      -3.51
44   -1.47      -3.72
45   -4.24      -6.4
46   -2.32      -3.52
47   3.66      5.87
48   6.36      3.58
49   -4.08      0.44
50   0.02      5.99
51   -0.66      5.7
52   3.47      1.96
53   -4.97      5.93
54   -5.57      -1.98
55   -6.26      -1.12
56   -0.61      -0.14
57   -6.34      -5.66
58   -6.74      -2.42
59   -2.91      -5.31
60   -0.6      1.5
61   -3.12      -3.53
62   -4.37      4.45
63   -5.65      2.63
64   -6.52      -4.16
65   -2.65      0.39
66   5.51      2.54
67   -2.64      6.22
68   -4.65      -4.25
69   -4.93      -3.18
70   -5.14      -5.46
71   3.77      3.11
72   -3.03      4.9
73   0.2      -5.27
74   -2.09      1.36
75   -4.17      -5.37
76   -2.32      -5.43
77   0.23      -0.29
78   -1.3      0.87
79   -3.74      -1.22
80   6.67      5.37
81   0.22      5.06
82   -5.37      0.92
83   3.73      -2.81
84   2.58      -0.61
85   2.58      -4.66
86   -3.29      3.58
87   -5.72      4.16
88   -0.95      -6.62
89   5.72      -3.63


Y los vertices del cuadrado son xsup=-6.7071067, ysup= 0.7071067,xinf=-5.2928933, yinf  =-0.7071067.

se obtiene como resultado
peaton_1=4;
peaton_2=82;
peaton_3=89;
peaton_4=89;

En línea

majojimu

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Re: Problema con el par mas cercano.
« Respuesta #3 en: 9 Julio 2013, 10:28 am »

que tal si dices por que te da malo... es decir que te da y que esperabas? que datos pasaste y que te respondió?


Tengo la siguiente lista de puntos.

Nº punto   Eje_x      Eje_y
0   -6.53      -0.52
1   3.93      -1.55
2   -4.92      4.84
3   -1.54      -2.35
4   -6.07      0.24
5   -4.04      -3.85
6   -2.29      3.31
7   -0.75      -4.69
8   -4.24      1.14
9   -0.48      -1.4
10   -1.69      2.06
11   -4.4      3.65
12   -1.67      5.68
13   -0.45      -0.8
14   -2.38      2.4
15   -2.06      -0.32
16   0.18      -2.88
17   -5.8      1.43
18   -2.58      -1.31
19   -1.17      -0.86
20   0.13      2.74
21   4.31      5.86
22   -1.59      -5.96
23   -0.93      -5.6
24   -6.21      2.17
25   1.84      5.79
26   -6.25      5.83
27   -4      -2.95
28   4.98      0.91
29   -0.68      6.54
30   -0.01      2.14
31   -3.01      1.62
32   0.1      -4.41
33   -1.22      3.68
34   0.08      0.96
35   -4.98      2.95
36   -6.3      -2.9
37   -5.98      -4.7
38   -4.03      5.74
39   -4.99      -2.45
40   -2.89      -6.16
41   -0.08      -2.07
42   5.25      5.31
43   -0.56      -3.51
44   -1.47      -3.72
45   -4.24      -6.4
46   -2.32      -3.52
47   3.66      5.87
48   6.36      3.58
49   -4.08      0.44
50   0.02      5.99
51   -0.66      5.7
52   3.47      1.96
53   -4.97      5.93
54   -5.57      -1.98
55   -6.26      -1.12
56   -0.61      -0.14
57   -6.34      -5.66
58   -6.74      -2.42
59   -2.91      -5.31
60   -0.6      1.5
61   -3.12      -3.53
62   -4.37      4.45
63   -5.65      2.63
64   -6.52      -4.16
65   -2.65      0.39
66   5.51      2.54
67   -2.64      6.22
68   -4.65      -4.25
69   -4.93      -3.18
70   -5.14      -5.46
71   3.77      3.11
72   -3.03      4.9
73   0.2      -5.27
74   -2.09      1.36
75   -4.17      -5.37
76   -2.32      -5.43
77   0.23      -0.29
78   -1.3      0.87
79   -3.74      -1.22
80   6.67      5.37
81   0.22      5.06
82   -5.37      0.92
83   3.73      -2.81
84   2.58      -0.61
85   2.58      -4.66
86   -3.29      3.58
87   -5.72      4.16
88   -0.95      -6.62
89   5.72      -3.63


Y los vertices del cuadrado son xsup=-6.7071067, ysup= 0.7071067,xinf=-5.2928933, yinf  =-0.7071067.

se obtiene como resultado
peaton_1=4;
peaton_2=82;
peaton_3=89;
peaton_4=89;



Disculpa he olvidado decir que lo que se espera que salga es:
peaton_1=4;
peaton_2=82;
peaton_3=0;
peaton_4=55;
En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Problema con el par mas cercano.
« Respuesta #4 en: 9 Julio 2013, 10:51 am »

Primera optimización: Si estás manejando coordenadas, lo suyo sería tener una estructura para manejarlos como tal.

Código
  1. class Punto
  2. {
  3.  public:
  4.    double x;
  5.    double y;
  6.  
  7.    Punto( double px, double py )
  8.    : x( px ), y( py )
  9.    {  }
  10. };
  11.  
  12. struct Vpeaton
  13. {
  14.    int ad_peaton;     //numero del punto
  15.    Punto punto;       // punto  
  16. };
  17. typedef std::vector<Vpeaton> V_peaton;

Segunda optimización: Si quieres calcular distancias... saca una función que la calcule en vez de repetir 8 veces el mismo cálculo. Reduces puntos de fallo y mejoras el mantenimiento y la legibilidad del código.

Código
  1.  V_peaton Areas;
  2.  
  3.  //buscar peston cercano a cada esquina.
  4.  distminXsYs = distancia( punto_ supizq, Areas[0] );
  5.  distminXiYs = distancia( punto_infizq, Areas[0] );
  6.  distminXsYi = distancia( punto_supder, Areas[0] );
  7.  distminXiYi = distancia( punto_infder, Areas[0] );
  8.  
  9.  for(int i=1; i<Areas.size(); i++)  
  10.  {                  
  11.    dist1 = distancia( punto_supizq, Areas[i] );
  12.    dist2 = distancia( punto_infizq, Areas[i] );
  13.    dist3 = distancia( punto_supder, Areas[i] );
  14.    dist4 = distancia( punto_infder, Areas[i] );
  15.  
  16.    if (dist1<distminXsYs)
  17.    {
  18.      distminXsYs=dist1;
  19.      peaton_1=Areas[i].ad_peaton;
  20.    }
  21.  
  22.    if (dist2<distminXiYs)
  23.    {
  24.      distminXiYs=dist2;
  25.      peaton_2=Areas[i].ad_peaton;
  26.    }                              
  27.  
  28.    if(dist3<distminXsYi);
  29.    {
  30.      distminXsYi=dist3;
  31.      peaton_3=Areas[i].ad_peaton;
  32.    }
  33.  
  34.    if(dist4<distminXiYi);
  35.    {
  36.      distminXiYi=dist4;
  37.      peaton_4=Areas[i].ad_peaton;
  38.    }
  39.  }

Tercera optimización: si asignas un valor inicial a las distancias lo suficientemente alto como para que cualquier punto posea una distancia inferior te puedes ahorrar las 4 primeras distancias y aglutinar todo en el for.

Código
  1.  V_peaton Areas;
  2.  
  3.  double distminXsYs = 1e9; // por ejemplo
  4.  double distminXiYs = 1e9;
  5.  double distminXsYi = 1e9;
  6.  double distminXiYi = 1e9;
  7.  
  8.  for(int i=0; i<Areas.size(); i++)  
  9.  {                  
  10.    dist1 = distancia( punto_supizq, Areas[i] );
  11.    dist2 = distancia( punto_infizq, Areas[i] );
  12.    dist3 = distancia( punto_supder, Areas[i] );
  13.    dist4 = distancia( punto_infder, Areas[i] );
  14.  
  15.    if (dist1<distminXsYs)
  16.    {
  17.      distminXsYs=dist1;
  18.      peaton_1=Areas[i].ad_peaton;
  19.    }
  20.  
  21.    if (dist2<distminXiYs)
  22.    {
  23.      distminXiYs=dist2;
  24.      peaton_2=Areas[i].ad_peaton;
  25.    }                              
  26.  
  27.    if(dist3<distminXsYi);
  28.    {
  29.      distminXsYi=dist3;
  30.      peaton_3=Areas[i].ad_peaton;
  31.    }
  32.  
  33.    if(dist4<distminXiYi);
  34.    {
  35.      distminXiYi=dist4;
  36.      peaton_4=Areas[i].ad_peaton;
  37.    }
  38.  }

Con esto además corriges uno de tus problemas, y era que no asociabas valores a los peatones si la distancia mínima se encuentra en el punto 0.

Cuarta optimización: Podrías usar un vector de puntos para definir el rectángulo, con eso podrías evitar tener que comprobar la distancia con cada esquina de forma explícita.

Código
  1.  class DatoDistancias
  2.  {
  3.    public:
  4.      double distancia;
  5.      Punto punto;
  6.  
  7.      DatoDistancias( const Punto& pt )
  8.        : distancia( 1e9 ), punto( pt )
  9.      { }
  10.  };
  11.  
  12.  V_peaton Areas;
  13.  V_peaton peatones; // En vez de peaton_1, peaton_2, peaton_3, peaton_4; Hay que inicializarlo
  14.  
  15.  std::vector< DatoDistancias > rectangulo;
  16.  
  17.  // presupongo que los límites del cuadrado son conocidos. Si no es así esto se sustituiría por la inicialización correspondiente.
  18.  rectangulo.push_back( Punto( -6.7071067, 0.7071067 ) );
  19.  rectangulo.push_back( Punto( -6.7071067, -0.7071067 ) );
  20.  rectangulo.push_back( Punto( 6.7071067, 0.7071067 ) );
  21.  rectangulo.push_back( Punto( 6.7071067, -0.7071067 ) );
  22.  
  23.  for( int i=0; i<Areas.size(); i++)  
  24.  {
  25.    for ( int j=0; j<rectangulo.size( ); ++j )
  26.    {
  27.      double dist = distancia( rectangulo[j].punto, Areas[i] );
  28.      if ( dist < rectangulo[j].distancia )
  29.      {
  30.        peatones[j] = Areas[i].ad_peaton;
  31.        rectangulo[j].distancia = dist;
  32.      }
  33.    }
  34.  }

Creo que el código final tiene bastante mejor pinta, no crees?

Y ya te digo yo que es muuucho más fácil corregir errores de esta forma.

La implementación de la función distancia no es que se me haya olvidado ponerla, con lo que tienes no te debería costar mucho implementarla.
En línea

majojimu

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Re: Problema con el par mas cercano.
« Respuesta #5 en: 9 Julio 2013, 11:22 am »

Primera optimización: Si estás manejando coordenadas, lo suyo sería tener una estructura para manejarlos como tal.

Código
  1. class Punto
  2. {
  3.  public:
  4.    double x;
  5.    double y;
  6.  
  7.    Punto( double px, double py )
  8.    : x( px ), y( py )
  9.    {  }
  10. };
  11.  
  12. struct Vpeaton
  13. {
  14.    int ad_peaton;     //numero del punto
  15.    Punto punto;       // punto  
  16. };
  17. typedef std::vector<Vpeaton> V_peaton;

Segunda optimización: Si quieres calcular distancias... saca una función que la calcule en vez de repetir 8 veces el mismo cálculo. Reduces puntos de fallo y mejoras el mantenimiento y la legibilidad del código.

Código
  1.  V_peaton Areas;
  2.  
  3.  //buscar peston cercano a cada esquina.
  4.  distminXsYs = distancia( punto_ supizq, Areas[0] );
  5.  distminXiYs = distancia( punto_infizq, Areas[0] );
  6.  distminXsYi = distancia( punto_supder, Areas[0] );
  7.  distminXiYi = distancia( punto_infder, Areas[0] );
  8.  
  9.  for(int i=1; i<Areas.size(); i++)  
  10.  {                  
  11.    dist1 = distancia( punto_supizq, Areas[i] );
  12.    dist2 = distancia( punto_infizq, Areas[i] );
  13.    dist3 = distancia( punto_supder, Areas[i] );
  14.    dist4 = distancia( punto_infder, Areas[i] );
  15.  
  16.    if (dist1<distminXsYs)
  17.    {
  18.      distminXsYs=dist1;
  19.      peaton_1=Areas[i].ad_peaton;
  20.    }
  21.  
  22.    if (dist2<distminXiYs)
  23.    {
  24.      distminXiYs=dist2;
  25.      peaton_2=Areas[i].ad_peaton;
  26.    }                              
  27.  
  28.    if(dist3<distminXsYi);
  29.    {
  30.      distminXsYi=dist3;
  31.      peaton_3=Areas[i].ad_peaton;
  32.    }
  33.  
  34.    if(dist4<distminXiYi);
  35.    {
  36.      distminXiYi=dist4;
  37.      peaton_4=Areas[i].ad_peaton;
  38.    }
  39.  }

Tercera optimización: si asignas un valor inicial a las distancias lo suficientemente alto como para que cualquier punto posea una distancia inferior te puedes ahorrar las 4 primeras distancias y aglutinar todo en el for.

Código
  1.  V_peaton Areas;
  2.  
  3.  double distminXsYs = 1e9; // por ejemplo
  4.  double distminXiYs = 1e9;
  5.  double distminXsYi = 1e9;
  6.  double distminXiYi = 1e9;
  7.  
  8.  for(int i=0; i<Areas.size(); i++)  
  9.  {                  
  10.    dist1 = distancia( punto_supizq, Areas[i] );
  11.    dist2 = distancia( punto_infizq, Areas[i] );
  12.    dist3 = distancia( punto_supder, Areas[i] );
  13.    dist4 = distancia( punto_infder, Areas[i] );
  14.  
  15.    if (dist1<distminXsYs)
  16.    {
  17.      distminXsYs=dist1;
  18.      peaton_1=Areas[i].ad_peaton;
  19.    }
  20.  
  21.    if (dist2<distminXiYs)
  22.    {
  23.      distminXiYs=dist2;
  24.      peaton_2=Areas[i].ad_peaton;
  25.    }                              
  26.  
  27.    if(dist3<distminXsYi);
  28.    {
  29.      distminXsYi=dist3;
  30.      peaton_3=Areas[i].ad_peaton;
  31.    }
  32.  
  33.    if(dist4<distminXiYi);
  34.    {
  35.      distminXiYi=dist4;
  36.      peaton_4=Areas[i].ad_peaton;
  37.    }
  38.  }

Con esto además corriges uno de tus problemas, y era que no asociabas valores a los peatones si la distancia mínima se encuentra en el punto 0.

Cuarta optimización: Podrías usar un vector de puntos para definir el rectángulo, con eso podrías evitar tener que comprobar la distancia con cada esquina de forma explícita.

Código
  1.  class DatoDistancias
  2.  {
  3.    public:
  4.      double distancia;
  5.      Punto punto;
  6.  
  7.      DatoDistancias( const Punto& pt )
  8.        : distancia( 1e9 ), punto( pt )
  9.      { }
  10.  };
  11.  
  12.  V_peaton Areas;
  13.  V_peaton peatones; // En vez de peaton_1, peaton_2, peaton_3, peaton_4; Hay que inicializarlo
  14.  
  15.  std::vector< DatoDistancias > rectangulo;
  16.  
  17.  // presupongo que los límites del cuadrado son conocidos. Si no es así esto se sustituiría por la inicialización correspondiente.
  18.  rectangulo.push_back( Punto( -6.7071067, 0.7071067 ) );
  19.  rectangulo.push_back( Punto( -6.7071067, -0.7071067 ) );
  20.  rectangulo.push_back( Punto( 6.7071067, 0.7071067 ) );
  21.  rectangulo.push_back( Punto( 6.7071067, -0.7071067 ) );
  22.  
  23.  for( int i=0; i<Areas.size(); i++)  
  24.  {
  25.    for ( int j=0; j<rectangulo.size( ); ++j )
  26.    {
  27.      double dist = distancia( rectangulo[j].punto, Areas[i] );
  28.      if ( dist < rectangulo[j].distancia )
  29.      {
  30.        peatones[j] = Areas[i].ad_peaton;
  31.        rectangulo[j].distancia = dist;
  32.      }
  33.    }
  34.  }

Creo que el código final tiene bastante mejor pinta, no crees?

Y ya te digo yo que es muuucho más fácil corregir errores de esta forma.

La implementación de la función distancia no es que se me haya olvidado ponerla, con lo que tienes no te debería costar mucho implementarla.

Muchas gracias, la verdad si que queda más claro el código.
Aunque con mi código ya solucione el error (un ; detrás del 3º y 4º if), Probaré el código que me has dicho, que veo que se optimiza mucho los recursos.
Gracias
En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Problema con el par mas cercano.
« Respuesta #6 en: 9 Julio 2013, 11:29 am »

Ten en cuenta que el código no he podido probarlo y que intenta ser una guía.

Así, por ejemplo, si analizas el código ves que la inicialización de rectangulo es un poco rara:

Código
  1. class DatoDistancias
  2.  {
  3.    public:
  4.      double distancia;
  5.      Punto punto;
  6.  
  7.      DatoDistancias( const Punto& pt )
  8.        : distancia( 1e9 ), punto( pt )
  9.      { }
  10.  };
  11.  
  12.  // ...
  13.  
  14.  std::vector< DatoDistancias > rectangulo;
  15.  
  16.  rectangulo.push_back( Punto( -6.7071067, 0.7071067 ) );

Básicamente es un vector de elementos de tipo DatoDistancias pero yo le paso un punto. Quizás sería más conveniente escribir

Código
  1. rectangulo.push_back( DatoDistancias( Punto( -6.7071067, 0.7071067 ) ) );

Pero debería funcionar porque el constructor de DatoDistancias no se ha definido como "explicit", aún así lo dicho, donde estoy ahora mismo no puedo probar códigos y lo he hecho de cabeza.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines