Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Problemas Con Un Algoritmo

Iniciado por pbarros, 10 de Mayo de 2006, 08:53:14 PM

« anterior - próximo »

pbarros

 Tengo la siguiente situación:
una serie de puntos (creador mediante un ciclo), y quiero que al acercarme a alguno de ellos se active, ilumine, marque, lo que sea.
En el siguiente dibujo muestro lo que quiero aproximadamente:



bueno, y si me acerco a otro punto:



Los puntos, sólo están dibujados, se supone que están dispersos por toda la ventana, así que no sé si deba guardarlos.... quise hacer algo como (suponiendo que el primer punto está en X:100, Y:100):

si mouse.x>=51 y mouse.x<=149 entonces
 si mouse.y>=51 y mouse.y<=149 entonces
    dibujar_circulo(100,100)
 fin si
sin si
...


pero son muchos los puntos...  ayuda por favor

zupervaca

 ¿Estan a una misma distancia todos como en el dibujo?

ZüNdFoLGe

 Si la situación es como la del dibujo, deberías establecer una DISTANCIA predeterminada al momento de crear los puntos, es decir, CONOCER la distancia. A simple vista, los puntos parecen ser equidistantes. Otro paso es FIJAR UN ENTORNO, es decir, a qué distancia debe estar el  cursor del mouse del punto para que aparezca el círculo. Luego sería algo así:


// detecto si el cursor del mouse está dentro del entorno admitido (puede ser 0)
if (DISTANCIA_Y - ((mouse.y) % DISTANCIA)  <= ENTORNO) && (DISTANCIA_X - ((mouse.x) % DISTANCIA_X) <= ENTORNO)
    // si está entonces compenso la diferencia para que el centro del círculo sea justo el punto
    drawCircle(mouse.x+(DISTANCIA_X - ((mouse.y) % DISTANCIA_X), mouse.y+(DISTANCIA_Y - ((mouse.y) %
                      DISTANCIA_Y));



O sea que solo debes conocer la DISTANCIA entre cada punto y, opcional, un entorno, que puede ser 0 en el caso que solo dibujes el círculo si la flecha está sobre el punto.

P/D- No es necesario almacenar nada  (ole)  

pbarros

Cita de: "ZüNdFoLGe"Si la situación es como la del dibujo, deberías establecer una DISTANCIA predeterminada al momento de crear los puntos, es decir, CONOCER la distancia. A simple vista, los puntos parecen ser equidistantes. Otro paso es FIJAR UN ENTORNO, es decir, a qué distancia debe estar el  cursor del mouse del punto para que aparezca el círculo. Luego sería algo así:


// detecto si el cursor del mouse está dentro del entorno admitido (puede ser 0)
if (DISTANCIA_Y - ((mouse.y) % DISTANCIA)  <= ENTORNO) && (DISTANCIA_X - ((mouse.x) % DISTANCIA_X) <= ENTORNO)
    // si está entonces compenso la diferencia para que el centro del círculo sea justo el punto
    drawCircle(mouse.x+(DISTANCIA_X - ((mouse.y) % DISTANCIA_X), mouse.y+(DISTANCIA_Y - ((mouse.y) %
                      DISTANCIA_Y));



O sea que solo debes conocer la DISTANCIA entre cada punto y, opcional, un entorno, que puede ser 0 en el caso que solo dibujes el círculo si la flecha está sobre el punto.

P/D- No es necesario almacenar nada  (ole)
Si, los puntos están a una distancia fija (ejemplo 20 pixeles) y el entorno al que te refieres, debe ser como la distancia en la que me acerco, no?... si es así, serían unos 5 pixeles....
El símbolo % en C es división, módulo o qué?, ahce mucho que no programo en C y ya se me ha olvidado...

Y gracias por las respuestas...

ZüNdFoLGe

 es el módulo. Los parámetros son, entonces:

DISTANCIA_Y = DISTANCIA_X = 20;
ENTORNO = 5;


pbarros

 Gracias ZüNdFoLGe,
lo hice, corre, pero el único problemilla es que en el if... compara una posición que se encuentra mucho más arriba... osea, como que se le corre el punto hacia arriba y la izquierda, más o menos la misma distancia del entorno... pero cuando dibujo el círculo queda justo en el centro del punto.

------------------------------------------------------------------------------------

(representación del ratón con la posición errónea y dibujando el círculo)

Estoy probando con los valores, pero siguiendo tu ejemplo, es lo más cercano que queda...

Ruben

Cita de: "pbarros"
El símbolo % en C es división, módulo o qué?, ahce mucho que no programo en C y ya se me ha olvidado...

Hi,
es el modulo. Te devuelve el resto, vamos lo que te sobra... (sorry, no me acuerdo como se llamaba...  :rolleyes:  :rolleyes: )
Ejemplo:
int a;
int b;

a = 4 % 2 ;
b = 5 % 2;

a vale 0.
b vale 1;


Por cierto, si tienes muchos puntos y quieres buscar el/los mas cercano/s a otro punto lo mas rapido son las estructuras tipo kd-tree. Aunque no tengo ni idea de si sera demasiado complejo para lo que tu quieres, aun asi ahi queda por si te sirve de algo... (ole)  

ZüNdFoLGe

 
Cita de: "pbarros"lo hice, corre, pero el único problemilla es que en el if... compara una posición que se encuentra mucho más arriba...
El método consiste en buscar coordenadas que sean múltiplos de DISTANCIA, es decir, dados 1000 puntos, esté donde esté, lo único que hago es ver si las coordenadas de la flecha son múltiplos de la distancia, en este caso, significa que estoy sobre un punto (sin saber cual). A la hora de dibujar el círculo, uso las coordenadas de la flecha porque ya se de antemano (se cumple la condicion del if) que está sobre un punto sin importar cual és, al momento de dibujar el círculo el punto será el correcto.

pbarros

 
Cita de: "ZüNdFoLGe"lo único que hago es ver si las coordenadas de la flecha son múltiplos de la distancia, en este caso, significa que estoy sobre un punto (sin saber cual). A la hora de dibujar el círculo, uso las coordenadas de la flecha porque ya se de antemano (se cumple la condicion del if) que está sobre un punto sin importar cual és, al momento de dibujar el círculo el punto será el correcto.
Otra vez, gracias ZüNdFoLGe,
pero mira el dibujo que adjunté... éso es lo que pasa... osea, la condición no se está cumpliendo del todo.... porque si me acerco al punto que deseo, desde abajo... me puedo situar hasta en (el punto está en X: 100, Y: 100 por ejemplo) X=X+1 e Y=Y+1, osea justamente bajo el punto un pixel... y no "detecta" que estoy en el rango...



---------------------------------------------------------------------------------------
Dejo el ejemplo ejecutable para que lo veas Ejemplo

y el código completo es:

Private Sub Command1_Click()
'Botón Limpiar
'Limpio la ventana y vuelvo a dibujar los puntos
 Me.Cls
 Call Pinta
End Sub

Private Sub Form_Load()
'Color de fondo Blanco
 Me.BackColor = vbWhite
'Para usar las primitivas de dibujo
 Me.AutoRedraw = True
 Call Pinta
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
 If (100 - (X Mod 100) <= 50) And (100 - (Y Mod 100) <= 50) Then
     Me.Circle (X + (100 - (X Mod 100)), Y + (100 - (Y Mod 100))), 20, vbRed
 End If
End Sub

Private Sub Pinta()
'Dibuja los puntos en la ventana cada 100 pixeles (X e Y)
Dim I As Integer
Dim J As Integer
 For I = 0 To Me.ScaleWidth Step 100
   For J = 0 To Me.ScaleHeight Step 100
     Me.PSet (I, J), vbBlack
   Next J
 Next I
End Sub

[EX3]

 Yo creo seria mucho mas sencillo averiguar a que distancia estan un punto de otro, mas concretos, la posicion de cursor con el punto y comparar dicho valor con uno establecido, como han dicho arriba. Para ello dx_lib32 te proporiciona la funcion MATH_GetDist() de la clase dx_System que calcula la distancia en pixeles de un punto a otro.

Sobre el operador % de C/C++ que he visto mencionado antes en VB su equivalente es Mod:
Resto = A Mod B
Salu2... ;)
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

ZüNdFoLGe

 
// detecto si el cursor del mouse está dentro del entorno admitido (puede ser 0)
if (DISTANCIA_Y - ((mouse.y) % ENTORNO)  <= 2*ENTORNO) && (DISTANCIA_X - ((mouse.x) % ENTORNO) <= 2*ENTORNO)
   // si está entonces compenso la diferencia para que el centro del círculo sea justo el punto
   drawCircle(mouse.x+(DISTANCIA_X - ((mouse.y) % DISTANCIA_X)), mouse.y+(DISTANCIA_Y - ((mouse.y) %
                     DISTANCIA_Y));


Observa los cambios que he hecho, y aparentemente ahora funciona. Me había olvidado de contemplar el caso "hacia el otro lado" del punto, por ello agregué 2*ENTORNO. Para ver si cae en el entorno del punto uso el entorno mismo para hacer el módulo; recordar que entorno nunca puede ser 0 .

synchrnzr

 Si no te va a suponer un gran problema de rendimiento, yo calcularía la distancia al punto correctamente, en vez de ver si el puntero esta dentro de un recuadro. Suponiendo que las coordenadas del punto son px y py y que las coordenadas del ratón son mx y my calcularía la distancia de la siguiente forma:

mouse_distance = SQRT( ( px - mx ) * ( px - mx ) + ( py - my ) * ( py - my ) )


Y luego, si mouse_distance es menor de la distancia a la que quieres que se dibuje el círculo, entonces...

IF mouse_distance < distance THEN DibujarCículo ELSE Nada


Puedes optimizar eliminando la raiz cuadrada y comparando los cuadrados de las distancias:

mouse_distance = ( px - mx ) * ( px - mx ) + ( py - my ) * ( py - my )
IF mouse_distance < ( distance * distance ) THEN DibujarCículo ELSE Nada


sync

Vicente

 Si tienes muchos puntos puedes también dividir el espacio en sectores que agrupan puntos, y primero calculas en que espacio estás y después en los puntos del espacio (y como mucho con puntos de espacios adyacentes). Así te ahorras comparar contra muchos puntos.

Un saludo!

Vicente

sés

 No he leído todas las respuestas, pero si los puntos están a la misma distancia unos de otros... eh... es un simple mapa de TILES de toda la vida en el que cada punto sería el centro de un tile.

int tilex = ratonx / ANCHO_TILE_X;
int tiley = ratony / ALTO_TILE_Y;


Luego sólo habría que calcular la distancia al centro de ese tile para ver si se sibuja el círculo o no.
Soy indeciso... ¿o no?

pbarros

 Hola a todos,
gracias por todas las respuestas... especialmente a ZüNdFoLGe, que es lo más parecido a la solución que quiero.

A propósito Eduardo, el último código:
Citar// detecto si el cursor del mouse está dentro del entorno admitido (puede ser 0)
if (DISTANCIA_Y - ((mouse.y) % ENTORNO)  <= 2*ENTORNO) && (DISTANCIA_X - ((mouse.x) % ENTORNO) <= 2*ENTORNO)
   // si está entonces compenso la diferencia para que el centro del círculo sea justo el punto
   drawCircle(mouse.x+(DISTANCIA_X - ((mouse.y) % DISTANCIA_X)), mouse.y+(DISTANCIA_Y - ((mouse.y) %
                     DISTANCIA_Y));
no funcionó... aún cambiando los (mouse.?) % ENTORNO por (mouse.?) % DISTANCIA_? como anteriormente lo habías enviado. Sin modificación simplemente no lo hace, lo modifico y hace, lo mismo que te explicaba, sólo que expande el rango mucho más hacia arriba y a la izquierda, osea, si me sitúo por debajo del punto, no lo detecta.

Yo anoche hice una modificación basándome en los resultados del cálculo del módulo que me diste, pero, tiene unas pequeñas fallas...
 If (Distancia - (X Mod Distancia) <= Entorno) Or (Distancia - (X Mod Distancia) >= Distancia - Entorno) _
 And (Distancia - (Y Mod Distancia) <= Entorno) Or (Distancia - (Y Mod Distancia) >= Distancia - Entorno) Then
   Me.Circle (IIf(Distancia - (X Mod Distancia) <= Entorno, X + (Distancia - (X Mod Distancia)), X + (Distancia - (X Mod Distancia)) - Distancia), IIf(Distancia - (Y Mod Distancia) <= Entorno, Y + (Distancia - (Y Mod Distancia)), Y + (Distancia - (Y Mod Distancia)) - Distancia)), Entorno, vbRed
 End If


Es mucho más enredado, pero hace el 90% de lo que quiero, si tienes un cálculo más simple... te lo agradecería  ;)

synchrnzr, él código que me propones, me sirve, pero tendría q hacer lo que no quería, que es preguntar por cada punto en la ventana, y justamente es lo que no deseaba hacer... de todas formas gracias :D .






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.