Bueno gente... Creo haber solucionado este gran problema que me venía atormentando hace tiempo. Mi plano no habrá quedado como el "Gugle maps" pero quedo bastante prolijo.
Paso a contarles. Mi software esta desarrollado en VisualFoxpro 9.0 SP2, así que voy a tratar de no poner "código" para no marearlos, como me he mareado yo con "los egoístas de otros lenguajes".
Tengo el plano de un cementerio, que en realidad es un "JPG" tomado con captura de pantalla del "Google Earth". Sobre él necesito poner objetos que seran con quienes el usuario interactúe... (parcelas, placas, floreros, zombies, almas en pena).
Este JPG lo coloco dentro de un Contenedor. Inicialmente la Imagen y el Contenedor tienen las mismas dimensiones. Una proporción (la mitad) menor a la de las dimensiones originales del archivo JPG.
El contenedor está ubicado en una posición determinada del Formulario, y cuando la Imagen aumente o disminuya, éste no lo hará... siempre permanecerá con las mismas dimensiones y la misma posición del comienzo.
Esto provoca que la Imagen tenga dos grupos de valores de posición. Uno con respecto al Contenedor y otro con respecto al Formulario.
Por último, tome para el aumento/disminución de las dimensiones de la imagen, una Escala fija la cual paso a explicarles como la establecí.
Tome las dimensiones de un aumento "manual" que le hice a la imagen, el cual correspondió con lo que yo deseo ver cuando el programita funcione. Entonces tuve dos valores... el original y el "crecido". Tome el "ancho nuevo" y lo dividí en el "ancho original"... y listo el pollo!!... la escala estaba ante mi!!
Bien... vamos a detallar las variables y los objetos que vamos a utilizar.
Objetos:
* Imagen
* Contenedor
Variables:
* Escala: un numero constante que lo calculé como les acabo de contar.
* DirWheel: Dirección de la rueda del mouse, en el caso del VFP este valor puede ser 1 (adelante) o -1 (atrás).
* Width / Height: El ancho / alto de "Imagen"/"Contenedor" al momento de girar la ruedita.
* Left / Top: El extremo izquierdo / superior de "Imagen"/"Contenedor" al momento de girar la ruedita.
* X / Y: los valores que representan la posición del Mouse al momento de girar la ruedita. Estos valores corresponden al "espacio" determinado por el Formulario, sin importar que objeto haya entre el cursor del mouse y el Formulario.
* pWimag / pWcont: Extremo derecho de la imagen / contenedor, calculo hecho a partir del ancho del objeto y la posición del extremo con respecto al Formulario. Si el objeto tiene un ancho de 10 y un "left" de 2, el extremo derecho con respecto al Form estará en 12 (se entiende?).
* pHimag / pHcont: Extremo inferior de la imagen / contenedor. Las mismas consideraciones que para el ancho.
Bien... vamos a desarrollar todo.
Escala=[numero constante] && Establecemos la constante que dirigirá las variaciones en el alto/ancho de la imagen
Si DirWheel > 0
&& Si la dirección de la ruedita es positiva quiere decir que ha girado hacia adelante. La imagen "crecerá"
____Si imagen.width >= 500 .Y. imagen.width<7693
&& Establecemos un rango de crecimiento. Con tan solo una de las dimensiones es suficiente, en este caso use el ancho
________imagen.width=imagen.width*escala
________imagen.height=imagen.height*escala
________imagen.left= X - ((X - imagen.left)*escala)
________imagen.top= Y - ((Y - imagen.top)*escala)
____findelsi
Sino
&& ahora la dirección es contraria, así que el valor será negativo. Entonces la imagen se "achicará"
____Si imagen.width > 500 .Y. imagen.width<=7693
&& Establecemos un rango de disminución. El rango es el mismo que para el crecimiento, pero presten atención a las diferencia de los signos de comparación. Cuando crece, el limite inferior debe estar incluido, cuando decrece, no.
________imagen.width=imagen.width*(1/escala)
________imagen.height=imagen.height*(1/escala)
________magen.left= X - ((X - imagen.left)*(1/escala)
________imagen.top= Y - ((Y - imagen.top)*(1/escala)
____findelsi
findelsi
Bien... hasta aquí toda va de maravillas. El "Zoom in" y el "Zoom out" funcionan como esperábamos. Pero hay un problema. Una irreconciliable pelea entre los pixeles y los decimales. Así que como no hay solución, al menos en este universo, vamos a acomodar la imagen a los sopapos y puñetazos.
Esas diferencias que se generan al querer expresar en pixeles lo que las operaciones de división nos devolvieron con decimales, se van acumulando y llega un momento en que la imagen comienza a desplazarse para rincones que no queremos y a variar sus dimensiones fuera de los rangos que le indicamos. Y pasan toda clase de cosas!!!
Así que fui metiendole "restricciones" a medida que me iban apareciendo. Lamentablemente ese "ZoomIn-ZoomOut" tan bonito que logramos, se nos arruina... pero bueno... la cosa seguirá funcionando dentro de lo que esperabamos... confíen en mi.
Para que cuando la imagen "decresca" los bordes superior (top) e izquierdo (left) no superen el rango y se vea un espacio vacío entre estos y los bordes del contenedor.
Si imagen.top >= 0 && Forzamos el Top y el Left a "0" y que no se atrevan a aparecerce dentro del container!!
____imagen.top = 0
findelsi
Si imagen.left >= 0
____imagen.left = 0
findelsi
Cuando vamos disminuyendo el tamaño se van acumulando decimales y cerca del límite inferior del rango la imagen decrece más allá del mismo, lo que provoca que cuando querramos volver a aumentar el tamaño este límite no nos permita hacerlo y la imagen se quede clavada en esa dimensión y posición. Entonces...
Si imagen.height <= 610 .O. imagen.width <=500 && Forzamos alto, ancho, top y left a los valores iniciales.
____imagen.width = 500
____imagen.height = 610
____imagen.top = 0
____imagen.left = 0
findelsi
Último problemita, hasta el momento... Así como los atrevidos "Top y Left" se nos entrometían, los bordes superior y derecho, también lo hacen. Como, al menos en VFP, no existen variables para estos dos extremos, los tenemos que calcular. Y aca entra a jugar la correspondencia de los puntos de la imagen con los del contenedor y los del formulario. Y se arma la bataola!!
Hay que averiguar en que punto del formulario se ubican estos bordes de la imagen, y para ello utilizaremos el alto y el ancho y las posiciones y dimensiones del contenedor. Vamos?
pWimag=imagen.width + imagen.left + contenedor.left
pWcont=contenedor.width+contenedor.left
Si pWimag < pWcont
____imagen.left = (imagen.left + contenedor.left) + (pWcont - pWimag)
findelsi
pHimag=imagen.height + imagen.top + contenedor.top
pHcont=contenedor.height+contenedor.top
Si pHimag < pHcont
____imagen.top = (imagen.top + contenedor.top) + (pHcont - pHimag)
findelsi
Bien... listo hasta aquí. No me han aparecido nuevos problemitas. Así que la cosa concluye aquí. Quizás en los lenguajes o formas de trabajo que usen cada uno haya otras formas de hacerlo, pero este ha sido mi procedimiento y he llegado a lograr un 95% de lo que quería hacer y eso es muy satisfactorio.
Antes de dejarlos quiero decir algo... en tono "Corporativismo Foxprosiano"... Dicen por ahí, y lo que más duele que sean usuarios de VFP, "Usen el Foxpro para lo que fue creado... estas cosas dejenselas a otros"... Están equivocadísimos!!! El "Zorrito" puede. Ha podido con todo lo que le he tirado... no lo menosprecien.
Listo... gracias por todo, espero que les haya gustado (y lo hayan entendido) este pseudo-tutorial. Los saludo y me voy... tengo que darle como loco a la ruedita del mouse!! Chau... Na' más!
PD: Resta programar el Drag&Drop para poder desplazar el plano hacia los sectores ocultos... y quedaría listo. Repito... gracias por compartir el conocimiento.