Título: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: Harold23 en 3 Julio 2017, 18:42 pm Muy buenas tardes;
Mi idea es poder hacer zoom con uso de GDI+ en un dibujo que estoy haciendo de prueba, cuyo centro de enfoque sea la posición del mouse, el cual aplica el zoom por medio de un ScaleTransform en el evento MouseWheel del Picture. Lo que pasa actualmente es lo siguiente: 1. Ubicado en un punto del PictureBox con el cursor, hago uso del Scrool, con el fin de acercar o alejar el dibujo con respecto al punto de posición del mouse. (https://social.msdn.microsoft.com/Forums/getfile/1092864) 2. Luego de que se activa el evento MouseWheel, si se aleja o acerca el dibujo, pero lo que hace es alejarse del punto de foco(que corresponde a la posición del mouse). (https://social.msdn.microsoft.com/Forums/getfile/1092865) La idea es, como clos programas CAD por ejemplo, es que se acerque o aleje el dibujo respecto a la posición del mouse, es decir, que la posición del mouse sea el centro de foco de la ampliación o reducción de lo dibujado. ¿Cómo puedo solucionar esto?. El código que tengo actualmente es el siguiente: Código
Agradeciera mucho me pudieran guiar en este caso, porque la verdad ya no se como lograrlo. Muchas gracias. MOD: Imagenes adaptadas a lo permitido. Etiquetas GeSHi. Título: Re: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: ivancea96 en 3 Julio 2017, 23:31 pm Tienes un punto en una imagen (el cursor, con respecto a la imagen), con su X y su Y.
Si escalas esa imagen, ¿sabrías decir dónde está ese mismo punto ahora? Ya tenemos el nuevo punto. Ahora hay que colocar ese nuevo punto de la imagen para que coincida con la posición del cursor (con respecto a la pantalla). ¿Podrías hacerlo? Y si no se me queda nada, listo. ¿Puedes responder a esas preguntas? Si sí, entonces hazlo paso a paso, y verás que sale solo. Si no, di cuál y por qué, para que te podamos ayudar. En estos casos, ver el proceso visualmente es lo mejor. Y hacerse las preguntas correctas. ¿Qué es exactamente lo que queremos? En este caso, es escalar, y mover la imagen de forma de que coincida con el cursor, nada más. Oh, y cuando tengas una duda así, es preferible que te abstengas de poner tanto código. Una pregunta bien hecha y concisa es más fácil de responder que poner un programa (cosa que puede desmotivar a la hora de responder :D) Título: Re: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: Harold23 en 3 Julio 2017, 23:49 pm Hola, muy buenas tardes;
Tienes razón en eso, solo traté de ser lo más explícito posible. El inconveniente es que no es una imagen(es un objeto vectorial que en el proyecro dibujaré); sé que la solución está con el Graphics.TraslateTransform y ScaleTransform, combinándolas correctamente, lo cual he intentado de varias formas, pero no he logrado. Seré lo más conciso: 1. La idea es que al hacer zoom con el MouseWheel del Picture, el gráfico dibujado se escale de tamaño teniendo como punto de origen la Posición Actual del Mouse. La idea es como este GIF. (https://i.stack.imgur.com/Xfzgb.gif) La idea es emular lo mismo que hace Autocad, cuando se quiero hacer Zoom. (https://photos-4.dropbox.com/t/2/AADvk_Ajl9ZhWDwR1WH46gtCH8quNuy4NuIWcAguw-hfNw/12/194395947/jpeg/32x32/1/_/1/2/2017-07-03_16-57-00.gif/EOL9tZMBGI60ASAHKAc/RlxNPKopZVG0Vrn5_GRe4GMfn-dJCs0kNOkcoFFxTS8%2COjjiFS_755zk3TtcROFxqm0o_ETIglE_46z5-Ynf6yM?size=2048x1536&size_mode=3) ¿Es entendible lo que quiero decir?. Agradezco pudieras ayudarme con una explicación más concisa, por ejemplo con un simple dibujo de un Rectángulo, y cuando se quiera hacer zoom con el Scroll del mouse(MouseWheel) el dibujo se acerque o se aleje, teniendo en cuenta el punto donde está el puntero del mouse. Agradezco pueda ayudarme en esto compañero, pues compartir el conocimiento es lo mejor que podemos heredar. Gracias por todo. Título: Re: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: ivancea96 en 4 Julio 2017, 00:01 am El tema es dividir el proceso en pasos.
En primer lugar: es una imagen vectorial, bien, pero: ¿La puedes escalar? ¿La puedes mover? Me refiero, a si tienes el algoritmo para ello o si puedes hacerlo. En caso afirmativo, eso ya no es un problema. Entiendo lo que quieres hacer, y eso es lo que expliqué en el primer mensaje. Entrando a detalles... Probablemente lo que te interese es, teniendo el origen de la transformación en la esquina superior izquierda de la imagen (en adelante, (0,0), el origen), aplicar una escala primero, para hacer grande la imagen, y luego la translación que comenté antes. Puedes empzar haciendo que el zoom siempre se haga en el centro de la imagen. Si logras esto, lo otro es casi igual. (https://i.gyazo.com/2abb5bee34ccdb11c83dbbbcec3d887c.png) La idea sería esa. Edito: Es evidente que la imagen no la hice bien "del todo", sinó al escalarlo, también se saldría por arriba de la pantalla. Pero, you know, paint D: Título: Re: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: Harold23 en 4 Julio 2017, 00:07 am Compañero, creame que llevo más de 2 semanas y no lo he logrado, le rogaría el favor que con un simple ejemplo de un rectángulo, pudiera ayudarme, que ya de ahí yo tomo la idea. Yo soy un igeniero civil, que me dedico a crear pequeños programas de utilidad, y estoy en un punto que ya no me sobran las ideas, pues lo que usted hace ver simple, ya para mí se ha vuelto un dolor de cabeza.
Añado un video ejemplar hecho en Autocad, con lo que deseo lograr: https://www.dropbox.com/preview/autocad.mp4 (https://www.dropbox.com/preview/autocad.mp4) Le pido por favor, con un simple ejemplo pequeño, me ilustre y yo de ahí en adelnate me voy. Dios me lo bendiga. Título: Re: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: ivancea96 en 4 Julio 2017, 01:13 am Un ejemplo, en javascript:
Pega el código en el cuadro de texto y haz click en "Execute" en http://ivancea.xyz/canvasScript.html (http://ivancea.xyz/canvasScript.html) El mismo código lo tienes en los "templates" a nombre de "Loading images". Es lo que tú has dicho, zoom centrado en el ratón. Además, tiene para desplazar con click. No es 1 imagen, sinó que son líneas e imágenes dibujadas al momento. En ese ejemplo, las transformaciones las ejecuto antes de dibujar, con lo que afectan a todo lo que dibujaré después. Aquí primero aplico la translación, y después la escala. Está todo un poco comentado, pero bueno, lo importante son las ecuaciones. Código
Probablemente no sea igual a lo que buscas para C#, pero la lógica es la misma. Y bueno, como ves, apenas son 2 líneas para X y 2 para Y. No es muy complicado, pero el tema es entenderlo. Título: Re: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: Harold23 en 4 Julio 2017, 04:05 am Hola compañero. De antemano muchas gracias por el código, pero la verdad nunca he trabajado con javascript, y por más que he tratado de buscar convertidores de código, no lo he encontrado, entiendo la idea más sin embargo con código no puedo lograrlo traspasar.
¿Es mucho pedirle, abusando de su amabilidad, pasarlo en sintaxis C# o VB.Net?. Preferiblemente VB.Net. Mientras, trataré de seguir convertir ese código. Dios me lo bendiga. Título: Re: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: Serapis en 4 Julio 2017, 05:58 am Ya te lo ha explicado bien en el primer mensaje...
si eres capaz de escalar una imagen y eres capaz de desplazarla (pegarla) en otra posición, consigues lo que quieres. Un sencillo ejemplo (yo en pseudocódigo, así cualquier que lea lo puede trasladar al lenguaje que precise...) Código: // Da igual si es una imagen o una captura de la pantalla, ventana, control, etc... Funcion ZoomEnXY( entero X, entero Y, fraccion Zoom, grafico Imagen) fraccion dX, fraccion dY grafico ImgZoom // 0º Es realmente necesario? si zoom=1.0 luego Devolver //nada que cambiar. // 1º primero obtienes una imagen escalada al zoom indicado. ImgZoom = ZoomImg(Zoom, Imagen) // 2º Ahora toca cordenar la imagen en el mismo punto que se pulsó. // 2.1 X e Y deben ser cordenadas relativas en la imagen (si ya lo son, se puede omitir). X = (X - Imagen.Left) Y = (Y - Imagen.Top) //2.2 Escalamos las cordenadas relativas (x,y). // Esto es, dónde está el pixel en la imagen escalada, donde se pinchó en la original? dX = (Zoom * X) dY = (Zoom * Y) // Esto quiere decir que una vez la imagen se coloque en el mismo punto, dX y dY //sería la cordenada relativa de la imagen coincidente con x,y relativa de la imagen original. // 2.3 ahora solo queda traducir la cordenada relativa de la imagen escalada a la cordenada absoluta. // O lo que es lo mismo, obtener el origen de la imagen, poscionado como 'eje' en dX,dY. X = ((Imagen.left + X) - dX) // la absoluta (previa) - la relativa actual, no da el origen de la imagen escalada. Y = ((Imagen.Top + Y) - dY) // Es una regla de tres. X= ... es lo mismo que decir ImgZoom.Left = ... // 3º Finalmente pegar la imagen en la nueva posicion. GraficoDibujar(X, Y, ImgZoom) Fin Funcion Un código más limpio podría relativizar el asunto de las cordenadas derivándolo a otra función... Código: Funcion ZoomEnXY( entero X, entero Y, fraccion Zoom, grafico Imagen) grafico ImgZoom // 0º Es realmente necesario? si zoom=1.0 luego Devolver //nada que cambiar. // 1º primero obtienes una imagen escalada al zoom indicado. ImgZoom = ZoomImg(Zoom, Imagen) // 2º Ahora toca cordenar la imagen en el mismo punto que se pulsó. X = TrasladarOrigen(X , Imagen.Left, Zoom) Y = TrasladarOrigen(Y , Imagen.Top, Zoom) // 3º Finalmente pegar la imagen en la nueva posicion. GraficoDibujar(X, Y, ImgZoom) Fin Funcion La función que calcula la nueva posición en un solo paso Pero mejor entenderlo bien más arriba, paso a paso, no usarlo sin entenderlo. Con copiar y pegar no se aprende... Código: entero = Funcion TrasladarOrigen(entero Distancia, entero Posicion, fraccion Zoom) Devolver = (Distancia - ((distancia - Posicion) * Zoom)) Fin Funcion Título: Re: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: Harold23 en 4 Julio 2017, 17:09 pm Muy buenos días compañero;
Es que una imagen tiene sus propiedades de location, cuestion que no tiene un Graphics, creame que yo le entiendo el procedimiento, de lo cual le estoy enteramente agradecido, pero eso no lo he podido trasladar a código con un Graphics.Todos los ejemplos que he visto por la internet todo lo hacen trabajando con BitMap, que es más sencillo, pero con un PictureBox, donde lo qu hago es obtener su e.Graphics, no he podido lograrlo. Por fa, ayudenme con un ejemplo de este tipo, se los ruego, hoy por mi mañana por ti. Dios me lo bendiga. Título: Re: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: ivancea96 en 4 Julio 2017, 19:14 pm Esque es lo mismo. La "location" es exactamente lo mismo que dibujarla transladada. Es lo mismo. Com ote digo, ve por pasos. Primero, transládalo. Todo. Sea bitmap, o vectorial. Transládalo. Hecho eso, nuevamente, es prácticamente lo mismo.
Título: Re: GDI+. Hacer zoom respecto a la posición del Mouse en evento MouseWheel de un Pic Publicado por: Harold23 en 4 Julio 2017, 19:19 pm Hola compañeto, pues déjame decirte que lo logré, ahora ando un poquito ponchado es con el tema del Pan.
Mira el código que organicé para tal fin, del zoom respecto al puntero del mouse: Código: Imports System.Drawing Public Class frm_camera ''' <summary> ''' Verifica si un botón del Mouse se ha presionado dentro de un control. ''' </summary> Dim mousePress As Boolean = False ''' <summary> ''' Variable que guarda posición del Mouse en el evento Down de un control. Esto ''' ocurre cuando se presiona un botón del Mouse en un control. ''' </summary> Dim mouseDown_Location As PointF Dim TraslationX_Graphics_old As Single = 0F Dim TraslationY_Graphics_old As Single = 0F ''' <summary> ''' Variable para guardar el valor que debe trasladarse el Objeto Graphics en el eje X, durante el Zoom ''' para que siempre el foco del zoom sea de acuerdo a la posición del punntero del Mouse. ''' </summary> Dim TraslationX_Graphics As Single = 0F ''' <summary> ''' Variable para guardar el valor que debe trasladarse el Objeto Graphics en el eje Y, durante el Zoom ''' para que siempre el foco del zoom sea de acuerdo a la posición del punntero del Mouse. ''' </summary> Dim TraslationY_Graphics As Single = 0F ''' <summary> ''' Escala de zoom que debe aplicarse en ScaleTransform del Graphics, el cual se aciva con el evento MouseWheel. ''' </summary> Dim zoom As Single = 1.0F ''' <summary> ''' Escala del zoom inmediatamente anterior del que ahora tiene la variable zoom. Esta variable siempre se calcula ''' en el evento MouseWheel. ''' </summary> Dim zoom_old As Single = 1.0F ''' <summary> ''' Incremento del zoom que se realiza en el evento MouseWheel. ''' </summary> Const zoom_increment As Single = 0.1F ''' <summary> ''' Mínimo zoom que se puede aplicar a los dibujos. ''' </summary> Const zoom_min As Single = 0.1F ''' <summary> ''' Máximo zoom que se puede aplicar a los dibujos. ''' </summary> Const zoom_max As Single = 5.0F Private Sub transformar(canvas As Graphics) canvas.Clear(Color.Wheat) canvas.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half canvas.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear canvas.ScaleTransform(zoom, zoom) canvas.TranslateTransform(TraslationX_Graphics, TraslationY_Graphics) Dim pen As New Pen(Color.Red) pen.Width = 1 / zoom canvas.DrawRectangle(pen, 100, 100, 100, 50) End Sub ''' <summary> ''' Evento que se desencadena cuando se presiona un botón del Mouse en el Control. ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown 'Se verifica que ha presionado el botón izquierdo del Mouse. If e.Button = MouseButtons.Left Then ' 'Se verifica que no se tiene g 'If Not mousePress = True Then 'mousePress = True ' 'Obtiene las coordenadas del puntero del Mouse cuando se presionó el Mouse. mouseDown_Location = e.Location TraslationX_Graphics_old = TraslationX_Graphics TraslationY_Graphics_old = TraslationY_Graphics 'End If PictureBox1.Invalidate() End If End Sub ''' <summary> ''' Evento que se produce cunado el puntero del mouse se mueve por el control. ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove 'Se verifica que ha presionado el botón izquierdo del Mouse. If e.Button = MouseButtons.Left Then ' 'Posición actual del puntero del mouse. Dim mousePosNow As PointF = e.Location 'Variable para saber cuanto debe desplazarse el objeto gráfico de acuerdo a la 'posición guardada en el evento MouseDown y la actual en este evento. Dim deltaX, deltaY As Single 'Se haya los valores de desplazamiento. deltaX = mousePosNow.X - mouseDown_Location.X deltaY = mousePosNow.Y - mouseDown_Location.Y ' 'Se obtiene DE NUEVO el desplazamiento que debe realizarse en el Objeto Graphics, teniendo en cuenta 'el valor pasado de dichos traslados obtenidos en el el evento MouseDown+ el nuevo delta de desplazamiento 'teniendo en cuenta de dividir dicho valor con el valor actual del zoom. TraslationX_Graphics = (TraslationX_Graphics_old + (deltaX / zoom)) TraslationX_Graphics = (TraslationY_Graphics_old + (deltaY / zoom)) ' 'Obligo a redibujar el control. PictureBox1.Invalidate() End If End Sub Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp ' 'Este evento ocurre cuando el puntero del Mouse se encuentra sobre el control 'y soltó un botón del Mouse. ' 'Se indica que ya no se encuentra presionado el botón del Mouse. mousePress = False End Sub ''' <summary> ''' Evento que se produce cuando el Scroll del mouse se hace rodar. ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> Private Sub PictureBox1_MouseWheel(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseWheel ' 'Actualizo el valor del zoom actual, antes de que se calcule el nuevo en este evento. zoom_old = zoom 'Verifico que el paso de la muesca del mouse se hace hacia arriba.(>zoom). If e.Delta > 0 Then ' 'Se incrementa el zoom, de acuerdo a la variable constante de la clase. Se 'tiene en cuenta que no se sobrepase del mayor valor del zoom. zoom = Math.Min(zoom + zoom_increment, zoom_max) Else ' 'Para el caso de disminución del Mouse, establezco un mínimo valor para no tener 'problemas de OverFlow. El mínimo valor del zoom zoom = Math.Max(zoom - zoom_increment, zoom_min) End If ' 'Se obtiene la posición actual del Mouse. Dim mousePosNow As Point = e.Location 'Variables para saber el valor de los deltas entre la posición actual del mouse 'y la ubicación de la parte superior izquierda del PictureBox. Dim deltaX, deltaY As Single deltaX = mousePosNow.X - PictureBox1.Location.X deltaY = mousePosNow.Y - PictureBox1.Location.Y 'Variable que guardan el valor teniendo en cuenta el zoom inmediatamente 'anterior de los desplazamientos que sufrió el Graphics. Dim oldGraphicsX As Single Dim oldGraphicsY As Single oldGraphicsX = ((deltaX / zoom_old)) oldGraphicsY = ((deltaY / zoom_old)) 'Variable para guardar los nuevos desplazamientos que debe sufrir el Graphics, 'para que el centro del foco del Zoom sea la ubicación actual del Mouse. Dim newGraphicsX As Single Dim newGraphicsY As Single newGraphicsX = ((deltaX / zoom)) newGraphicsY = ((deltaY / zoom)) ' 'Los nuevos valores de Traslado del objeto Graphics se obtiene. TraslationX_Graphics = newGraphicsX - oldGraphicsX + TraslationX_Graphics TraslationY_Graphics = newGraphicsY - oldGraphicsY + TraslationY_Graphics 'Se obliga a redibujar el control. PictureBox1.Invalidate() End Sub Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint 'Envío el objeto Graphics, para que dibuje teniendo en cuenta las transformaciones. transformar(e.Graphics) End Sub ¿Es la forma correcta?. De ser así, te agradecería pudieras ayudarme con hacer el Pan o mover por medio del Mouse, teniendo presionado el Button.Left. Muchas gracias. |