Diseño de aplicación para la generación de tours virtuales Pág. 1 ANEXOS ANEXO A. CREACIÓN DE FOTOGRAFÍAS ESFÉRICAS ANEXO B. CÓDIGO VISUAL BASIC DE LAS PRINCIPALES VENTANAS DE LA APLICACIÓN Pág. 2 ANEXO Anexos A. ESFÉRICAS CREACIÓN DE FOTOGRAFÍAS Diseño de aplicación para la generación de tours virtuales Pág. 3 SUMARIO ANEXOS ________________________________________________________ 1 SUMARIO _______________________________________________________ 3 SUMARIO ______________________________________________________ 28 B.1 OBJETO ___________________________________________________ 29 B.2 VENTANA PANTALLA_TOUR_ESFERICO.VB_____________________ 30 B.3 PANTALLA FOTO_ESFERICA.VB_______________________________ 69 B.4 PANTALLA PUNTOS_CALIENTES_ESTATICOS ___________________ 92 B.5 PANTALLA PARAMETROS.VB _________________________________ 97 B.6 PANTALLA OPCIONES_PUNTOS_CALIENTES_ESTATICOS _______ 103 Pág. 4 A.1. Anexos OBJETO Con el objetivo de hacer Fotografías Esféricas, el primer paso a realizar es la toma de fotografías, por tanto, la elección del motivo y del encuadre que se quieren representar y resaltar. Se debe prestar especial atención al resultado de la Fotografía Esférica, debido a que el usuario puede observar cualquier punto de la fotografía con el detenimiento que le parezca conveniente. Por ello se debe entender bien qué pasos se deben seguir, los aspectos más delicados en cada uno de los pasos y la necesidad de un material adecuado. Diseño de aplicación para la generación de tours virtuales Pág. 5 A.2. Material A.1.1 La Cámara Es recomendable utilizar una cámara digital réflex. Por un lado, se aconseja cámara digital por el hecho que luego las fotografías son más sencillas de tratarlas y modificar los aspectos que lo requieran (la exposición, la apertura del diafragma de la cámara, el valor ISO...). Y por el otro, cámara réflex, ya que debe tener controles manuales para obtener fotografías uniformes, es decir, los tonos y la luminosidad deben ser lo más parecidos posible en todas las fotografías que posteriormente formen la fotografía esférica y si no se pueden cambiar sus valores, la cámara asignará a cada fotografía los valores que considera los mejores y probablemente cada foto tenga sus propios ajustes, haciendo prácticamente imposible su posterior unión. Además dependiendo del tamaño de sensor, hará que se puedan utilizar objetivos más o menos angulares. Cuanto más grande sea el sensor, objetivos menos angulares o con mayor longitud serán necesarios, ya que éste podrá abarcar mayor campo de visión, y por tanto se podrá controlar mejor la profundidad de campo y producir menos ruido con valores extremos con poca luz . Los controles manuales que se utilizarán son el ISO, la apertura del obturador, el tiempo de exposición, el balance de blancos y el enfoque. Conviene asegurarse si hay contrastes remarcables y hacer un promedio de las mediciones tanto del enfoque como de los parámetros de diafragma y velocidad. Además se recomienda disparar en formato Raw (formato no comprimido muy usado en el mundo fotográfico), algo que también se puede elegir en las cámaras réflex. Al disparar en formato Raw, permite en el posterior procesado de las fotografías modificar los niveles de luminosidad si no se ha conseguido la que se quería a la hora de tomar las fotografías, sin perder información dentro de la fotografía debido a que se trata a un formato no comprimido. Fig. A.1 Imagen de un antiguo negativo [www.xataka.com] Pág. 6 Anexos La cámara se recomienda orientarla verticalmente, es decir, con la empuñadura en la parte superior o inferior, pero en la parte lateral; así, de éste modo el ángulo de visión que se cubre verticalmente es mayor que si se orientara la cámara horizontalmente, debido a que el sensor de la cámara tiene forma rectangular imitando a los antiguos negativos como se puede apreciar en la figura A.1. A.1.2 Filtros Existen muchos tipos de filtros que relazan un efecto u otro, por ello es muy importante saber exactamente como modifican la imagen y poder actuar en consecuencia. Por ejemplo, en el caso de los filtros polarizadores, lo que hacen es reducir la luz que proviene de los reflejos producidos normalmente por superficies metálicas, agua o cristal. Por tanto, según se oriente la cámara esa reducción de luz puede ser diferente ya que la iluminación en la toma actual es diferente además de que el uso de estos filtros puede provocar manchas negras en la imagen, con lo que puede complicar la posterior unión de las fotografías. Se aconseja el uso de filtros que no modifiquen la imagen dependiendo de la orientación de la cámara, es decir, filtros que siempre realicen el mismo efecto con independencia de la iluminación actual. A.1.3 Iluminación artificial No es aconsejable el uso del flash que lleva incorporada la cámara, ya que de ésta forma no se crea una iluminación uniforme en el ambiente. Por tanto, se utilizará siempre que se pueda iluminación natural recurriendo a largas exposiciones y valores altos de ISO si fuera necesario o luces fijas en el escenario para conseguir esa iluminación constante en todas las fotografías. Existen situaciones en que existe mucho contraste de iluminación, altas luces y sombras, que con cualquiera de los dos casos contemplados anteriormente no se consigue esa uniformidad que se persigue. En estos casos, se suele utilizar la técnica HDR (Alto Rango Dinámico). La técnica HDR consiste en realizar diferentes disparos con el mismo encuadre y con las mismas configuraciones, tan solo modificando el valor de exposición EV y así conseguir la exposición correcta para cada zona de la fotografía, es decir, que se vea todo claro y Diseño de aplicación para la generación de tours virtuales Pág. 7 nítido. Se harán tantas fotografías con diferentes valores de exposición como se quiera o se precise según la situación en que se esté trabajando. Por tanto, si existe mucho contraste de iluminación habrá que hacer más cantidad de fotografías y con un rango de exposición mayor que si no existiera tanto contraste. Luego, se deben combinar todas las fotografías con diferentes exposiciones tomadas de la misma escena con un programa especializado, como por ejemplo el Photomatrix, y así obtener una única fotografía en donde todas las zonas de ésta están perfectamente iluminadas. Al no consistir en una simple suma de imágenes, mediante éste tipo de programas se consigue crear una imagen final como el usuario desea pudiendo modificar ciertos parámetros como la saturación, la luminosidad, microcontraste, etc. (ver figura B.2) y así poder conseguir el toque final que el usuario quiera. En el caso de la realización de Fotografías Esféricas con la técnica HDR, el procedimiento es sutilmente diferente. Antes de tomar ninguna fotografía, se debe utilizar el mismo rango de exposición para todo el proceso de tomas de fotos para la Fotografía Esférica final. Primeramente, se deben unir todas las fotografías tomadas con el mismo nivel de exposición, realizando tantas fotografías esféricas como fotos de diferentes exposiciones hayamos definido al principio. Una vez hecho esto, con todas las imágenes esféricas planas de diferentes exposiciones, se procederá igual como si se tuvieran diferentes exposiciones de un único encuadre. Por tanto, se introducirán éstas en el programa específico para la técnica HDR, en este caso Photomatrix, y finalmente se obtendrá una única fotografía esférica en el que cada zona de ésta está debidamente expuesta. Pág. 8 Anexos Fig. A.2 Captura de pantalla de la ventana principal del programa Photomatrix A.1.4 El trípode Es un elemento esencial para hacer las fotografías esféricas. Sirve como estabilizador y nivelador, sobre el cual se harán todos los giros necesarios para cubrir la esfera entera que se quiere fotografiar. Es recomendable un trípode ligero para facilitar su transporte y que sea lo más alto posible para facilitar el de fotografiado de todas las zonas dispuestas a retratar. Una opción para la estabilidad del mismo, es que haya una barra central vertical en la que se pueda colgar peso para evitar su cimbreo. A.1.5 Nivelador Es importante que la cámara esté bien nivelada respecto a la horizontal y que todas las fotografías que se vayan a tomar no están desviadas unas de otras. Para ello es recomendable utilizar un nivel de burbujas de 3 ejes como la de la figura A.3 que se pueda poner en la zapata del flash de la cámara como el que se indica en la siguiente imagen. Diseño de aplicación para la generación de tours virtuales Pág. 9 Fig. A.3 Fotografía donde se puede observar la situación del nivelador en la cámara [tec.nologia.com]] Es importante mencionar que muchas veces se nivela la base del trípode, ya que suelen llevar una burbuja como el de la imagen de la figura A.4, pero éste es un error muy importante. En la base del trípode no se pone la cámara sino que se ajusta un cabezal esférico, como se explicará más adelante, por tanto, que la base esté nivelada mientras que la cámara está en otro lugar en contacto con otra superficie no sirve de nada para nivelar las fotografías que se van a tomar. Fig. A.4 Fotografía en donde se puede apreciar la burbuja niveladora de la base del trípode [canonistas.com] Por tanto, se debe nivelar el objeto que va a tomar las fotos, en este caso, la cámara de hacer fotos. Pág. 10 A.1.6 Anexos Cabezal esférico o rótula Es el elemento que permite ajustar la cámara para realizar el giro respecto el punto nodal y evitar el efecto del paralelaje. Además, resulta muy útil para el posterior solapamiento de las fotografías ya que suelen llevar escritos los grados angulares. La figura A.5 consiste en un cabezal esférico de la empresa americana, Nodal Ninja. Como se puede observar en la imagen, éste tipo de cabezales, tienen 3 grados de libertad: el parámetro A, el B y como se mueve el brazo del parámetro B con respecto al brazo del A. Por tanto, resulta sencillo poder ajustar la cámara como se desee y orientar posteriormente ésta como se crea conveniente. Los parámetros A y B resultan especialmente útiles para ajustar la cámara en el punto nodal, ya que como se puede observar en la siguiente fotografía se pueden modificar cuando el usuario quiera y por tanto, es adaptable a cualquier cámara y cualquier objetivo. Fig. A.5 Cabezal esférico Nodal Ninja [http://www.nodalninja.com/] Diseño de aplicación para la generación de tours virtuales Pág. 11 El efecto del paralelaje es la desviación angular de la posición aparente de un objeto[1] que se hace más evidente cuanto más cerca se encuentra el motivo mientras que a partir de varios metros el efecto se hace insignificante, en otras palabras, es un efecto óptico que consiste en la diferencia de lo captado por la cámara y lo que se ve por el visor de la misma, como se puede apreciar en la figura A.6. Ésto ocurre cuando se utiliza un visor que no está montado en el mismo eje que el objetivo. Por tanto, en interiores es donde es más importante cuidar que éste efecto no se produzca. Este efecto puede ser vertical, horizontal o ambos a la vez. Fig. A.6. Esquema del efecto de paralelaje [http://estudiodefotografiafotografoprofesional.es/] El punto nodal es en realidad una pareja de puntos situados en el eje óptico de un objetivo compuesto que sirven de referencia para mediciones básicas, como la longitud focal. La luz llega al objetivo con un ángulo específico y suele salir de él con un ángulo distinto. Pero hay dos puntos en el eje óptico, que el rayo de luz entrará por uno de ellos y saldrá por el otro con el mismo ángulo, éstos son los puntos nodales Explicado en otro términos. Cuando se coloca la cámara en el trípode por la rosca de la base, al girar el trípode la perspectiva cambia, en casos extremos ese cambio de perspectiva impediría que las imágenes se pudieran unir correctamente. Pero existe un punto a lo largo del objetivo en el cual no cambia la perspectiva cuando rotamos respecto a éste, como se puede observar en la figura A.7. Pág. 12 Anexos Fig. A.7 Esquema de la rotación de la cámara respecto al punto nodal [http://www.panoramicas-canarias.es/] Diseño de aplicación para la generación de tours virtuales Pág. 13 Fig. A.8 Esquema del efecto al situar en diferentes lugares de la cámara el eje de giro de la cámara en el sensor de la misma [Gráfico basado en Big Ben's Panorama Tutorials] Como se puede observar en la figura A.8, dependiendo del punto que se elija para la rotación tendrá un efecto diferente al sensor de la cámara. 1. Se situa la cámara de modo que dos objetos verticales (por ejemplo, dos árboles) estén más o menos alineados o próximos. Uno muy cerca al punto de toma y otro lejano. La imagen que se produce se representa por las barras verticales inferiores. 2. Si el centro óptico del objetivo (en rojo) y el eje de giro de la cámara (en verde), al girar la cámara las distancias en la imagen entre esos objetos deben permanecer invariables. Si se juntan o se separan hay que adelantar o retrasar la cámara en un rail de enfoque hasta que coincidan ambos centros. 3. Al estar el centro óptico (en rojo) retrasado respecto al eje de giro del sistema (en verde), al rotar hacia la izquierda los dos objetos tienden a juntarse. Pág. 14 Anexos 4. En el caso contrario, con el eje de giro retrasado respecto al centro óptico, esos objeetos tienden a separarse. Cuando ambos objetos están muy distantes del punto de toma, este efecto es prácticamente inapreciable. A.1.7 Objetivo fotográfico Se puede utilizar cualquier objetivo, pero dependiendo de cual se use se deberán realizar más o menos instantáneas. Cuanto mayor sea el angular del objetivo, es decir, tenga más campo de visión, serán necesarias menos fotografías. El objetivo ideal es el Ojo de Pez, que es el mayor angular de toda la gama y teóricamente abarca 180º verticalmente y 180º horizontalmente, con lo que tan solo serían necesarias 3 fotografías. Aunque por otro lado, éste objetivo introduce mucha distorsión y limita la resolución en la zona periférica de la imagen. Todo esto no quiere decir que con un objetivo de menor angular no se pueda hacer, sino que requerirá mayor número de fotografías y con su consiguiente aumento del número de uniones de las mismas para la fotografía esférica final. Se debe tener en cuenta si el objetivo a usar producirá distorsión de la imagen y por tanto, posteriormente las fotos tomadas se deben tratar para rectificarlas. En el caso de un objetivo gran angular, es decir, que abarque mucho campo de visión, habrá una distorsión de líneas haciéndolas curvas que será más grande cuanto más se acerque al fotógrafo al motivo debido a que éste objetivo exagera la perspectiva de los objetos, éste es el efecto de la perspectiva cónica o barril. Diseño de aplicación para la generación de tours virtuales Pág. 15 Fig. A.9 Imagen en donde se puede observar la distorsión que un objetivo gran angular produce Como se puede observar en la figura A.9, en los extremos de la imagen se acentúa la distorsión barril y aún se hace más claro cuanto más cerca se tenga el objeto capturado. Pág. 16 Anexos Fig. A.10 Fotografía en donde se puede apreciar la distorsión producida por el uso de un objetivo ojo de pez [www.canonistas.com] Se puede observar, que utilizando un objetivo ojo de pez, la distorsión es aún mayor debido a que se intenta concentrar toda la información que este objetivo puede abarcar dentro del tamaño del sensor de la cámara. Existen algunos objetivos ojos de pez, que si el sensor de la cámara es grande y/o la distancia focal del objetivo es muy pequeña, pueden aparecer esquinas negras o incluso poder apreciar la forma circular del objetivo como se puede apreciar en la figura A.10. A.3. Toma de las fotografías Antes de empezar a hacer las fotografías, es importante definir muy bien lo que se quiere fotografiar para eliminar cualquier objeto no deseado en la toma, empezando por la sombra del propio fotógrafo. Además, se debe tener en cuenta los posibles cambios de iluminación durante la sesión fotográfica y los movimientos rápidos de las nubes o personas. Por lo que después de hacer un análisis de la situación en que se encuentra a la hora de hacer la fotografía, se escogen los parámetros adecuados para ése escenario. Una vez elegidos, se bloquean los parámetros manuales de la cámara como la Diseño de aplicación para la generación de tours virtuales Pág. 17 exposición, la velocidad, balance de blancos, ISO y enfoque, para asegurar que todas las fotografías estén tomadas bajos los mimos parámetros. En el caso de la apertura, se debe asegurar que tenga suficiente profundidad de campo para que salgan enfocados los diferentes planos de la imagen. Además, se recomienda tapar el visor, parte de la cámara por donde el fotógrafo mira a la hora de hacer las fotografías, evitando así la entrada de luz. Es conveniente, también, antes de empezar a tomar las fotografías, nivelar y equilibrar bien la cámara con el nivelador que se ha explicado anteriormente. Las diferentes fotografías que se toman deben tener un área de superposición de entre un 20% y un 40%, ya que así facilitará el proceso de unión entre fotografías porque cada foto estará referenciada con las fotografías de los lados como se puede observar en el esquema de la figura A.11 y A.12. Fig. A.11 Esquema del proceso de la toma de fotografías [javierselva.desnivel.com] Pág. 18 Anexos Fig. A.12 Visualización del área de superposición en la toma de las fotografías [javierselva.desnivel.com] El ángulo de visión de la lente que se utiliza y el área de superposición entre fotografías determina el número de fotografías que se tienen que realizar para conseguir una fotografía esférica. Se coloca el trípode en un lugar liso y plano para poder hacer girar la cámara y hacer todas las fotografías respecto el punto de nodal sin peligro de que pueda moverse, como se ha explicado en el punto A.1.6. La técnica para la realización de fotografías depende de la imaginación de cada persona y de la lente que se utilice. Si se utiliza una lente de ojo de pez, se deberán considerar unos aspectos diferentes a la hora de pensar cómo se organiza la toma de fotografías que si se utiliza una lente menos angular. En este caso se procede a describir el procedimiento más convencional, que consiste en colocar la cámara lo más perpendicular al suelo, lo más nivelada posible y realizar las fotografías cubriendo los 360º. En función del ángulo de visión de la cámara se necesitará hacer un mínimo de fotografías mayor o menor, normalmente entre 8 y 16 imágenes son suficientes para abarcar todo el espacio de la esfera; luego hay que considerar si se debe hacer otra vuelta entera de fotografías inclinando la cámara hacia arriba o hacia abajo para que abarque finalmente la esfera Diseño de aplicación para la generación de tours virtuales Pág. 19 completa. A.4. Creación de la fotografía esférica plana Una vez realizadas las fotografías es necesario unirlas para obtener la fotografía esférica final, lo que en el argot se llama "stitchar". Para ello existen multitud de programas que facilitan el trabajo, corrigiendo las deformaciones de las lentes, la nivelación de las fotografías, defectos como el "vignetting" (oscurecimiento de las esquinas de la fotografía) e incluso los tonos de las fotografías si no están unificadas ("blending"). Algunos ejemplos de este tipo de programas son Hugin, Autopoano Giga, PtGui, etc. Fig. A.13 Esquemas de algunos casos en los que se puede enfrentar los programas de unión de las fotografías. Como se puede observar en los esquemas anteriores (figura A13), cada caso requiere unas rectificaciones por parte del programa diferente. En el caso de que las imágenes no estén alineadas, se deberá cortar la imagen final para que quede una imagen rectangular con los bordes rectos y no con escalones. Hay programas que son compatibles tanto con plataforma Mac como PC. Normalmente lo que diferencia un programa de otro, es tanto el formato final de éstos como películas QuickTime interactivas, documentos vrml, formato de imagen, etc. como la calidad en la unión de las fotografías. La calidad en la unión de las fotografías se puede evaluar según rectifique las deformaciones creadas por la lente, la sensibilidad de detectar la diferencia de nivel de las fotografías, cómo realice el "blending", etc. Además, resulta muy útil tener la posibilidad de poder añadir o eliminar puntos de control, ya que si el programa no ha realizado lo que el usuario deseaba, éste siempre puede ayudar al programa. Pág. 20 Anexos Fig. A.14 Diferentes formatos de imagen de salida de los programas de unión de fotografías. Como se puede observar en la figura A.14, existen diferentes formatos de exportación de imagen de los programas de "stitching" de las fotografías. En el caso que concierne este proyecto, tan solo se contemplarán las caras de cubo o la disposición esférica. Se elegirá una u otra, dependiendo de la disposición de imagen que se necesite en el siguiente paso, es decir, la edición fotográfica y la propia edición de la Fotografía Esférica. Normalmente se suele hacer un retoque manual final que suele ser ajuste de curvas, ajuste de niveles, retoque de algunas zonas en las que el "pegado" ha tenido algún desplazamiento y finalmente, eliminación de los elementos que intervienen a la hora de tomar las fotografías como el trípode, el fotógrafo, el flash, etc. Para ésta edición existen infinidad de programas de edición fotográfica como el Adobe Photoshop, Gimp, etc. Siguiendo el ejemplo de la imagen anterior, se muestra el resultado final (figura A.15) de la unión de las fotografías en el caso de una fotografía panorámica y no esférica, pero en donde se puede observar el resultado de esa unión, que en ambos casos se procede de la misma manera. Diseño de aplicación para la generación de tours virtuales Pág. 21 Fig. A.15 Imagen final después de la unión de diferentes fotografías [javierselva.desnivel.com] B.3.1 Modelo matemático en la unión de fotografías Se ha hecho una investigación de qué procesos y cálculos matemáticos hacen los programas de unión de fotografías y así tener una idea más extensa del proceso global en la realización de un tour virtual. Se procede a explicar una manera de realizar una unión de fotografías automatizada basada en las propiedades invariantes de las imágenes, debido a sus ventajas respecto a otros métodos, como son las siguientes: • El uso de características invariantes permite una unión de las fotografías fiable independientemente de la variación de rotación, el zoom y la iluminación de las mismas. • No es necesario que el usuario agregue las imágenes al programa de unión en un orden determinado, ya que el programa reconoce automáticamente las relaciones entre las mismas • Se crean resultados de alta calidad utilizando blendings multi-banda para renderizar las panorámicas, ya sean cilíndricas como esféricas. Para la buena explicación del proceso anteriormente mencionado, se procederá a explicar los siguientes puntos: proceso de elección de las propiedades invariantes, metodología en el proceso de unión y finalmente, ajuste y verificación de la unión. Elección de las propiedades invariantes El primer paso a realizar es extraer y emparejar las propiedades SIFT (Scale Invariant Feature Transform) entre todas las imágenes que formarán finalmente una única. Pág. 22 Anexos SIFT es un método para extraer características distintivas de las imágenes en escala de grises, es decir que puede ser utilizado para reconocer la misma característica entre diferentes vistas de una misma escena. Estas características son invariantes a la escala de la imagen y a la rotación, parcialmente es invariante a la deformación. El algoritmo analiza una imagen a través de la escala de espacio utilizando el método piramidal con sucesivos filtros Gaussianos. Éste encuentra máximos y mínimos de contraste a través de tres máscaras en tres niveles adyacentes de Gaussianos (DOG), los cuales son potenciales puntos clave. Asumiendo que la cámara rota respecto al centro óptico, el grupo de transformaciones de las imágenes pueden sufrir un grupo especial de homografías, es decir, un grupo de correspondencias. Se parametriza cada cámara con un vector de rotación ?=[ ? 1 , ? 2 , ? 3 ] y una longitud focal f. Ésto da homografías emparejadas u~i =H ij u~j donde: H ij = K i R i R Tj K -j 1 y u~i , u~j son las posiciones homogéneas de las imágenes ( u~i =si [ u i ,1 ] , donde u i es la posición en dos dimensiones de la imagen). El modelo de la cámara de 4 parámetros es definida por: [ fi K i= 0 0 0 fi 0 0 0 1 ] y (utilizando la representación exponencial para la rotación) Ri =e [? i ]x [ 0 - ? i3 ? i2 , [ ? i ] x = ? i3 0 - ? i1 - ? i2 ? i1 0 ] Idealmente se utilizarían el grupo de propiedades invariantes con éste grupo de transformaciones. Una vez, las propiedades han sido extraídas de todas las n imágenes (tiempo lineal), éstas deben ser unidas. Al poder haber diferentes imágenes que se superpongan, cada propiedad es unida a sus k vecinos más cercanos (normalmente se utiliza k=4). Proceso de unión de las imágenes Del proceso de búsqueda de las propiedades invariantes, es decir, ésas que ayudan a la Diseño de aplicación para la generación de tours virtuales Pág. 23 unión; se han identificado fotografías que tienen gran cantidad de puntos coincidentes entre ellas. Se considera un número constante de m imágenes, que tienen el máximo número de propiedades coincidentes con la imagen actual, como imágenes potenciales a la unión (se utilizará m=6). Primero, se utiliza RANSAC para seleccionar un grupo de “inliers” (puntos dentro del umbral considerado) que son compatibles con la homografía entre las imágenes. En un segundo paso, se aplicará un modelo probabilístico para verificar el modelo. RANSAC (Random Sample Consensus) es un procedimiento de ajuste robusto que utiliza el mínimo de muestras aleatorias de correspondencias para estimar los parámetros de la transformación de la imagen y encuentra una solución que tiene el mejor consenso con los datos. En el caso de panoramas, se seleccionan grupos de r=4 correspondientes propiedades y realiza el homograma H entre ellas utilizando una transformación directa y linear. Se repite el mismo proceso con n=500 ensayos y se selecciona la solución con máximo número de “inliers”. La probabilidad de que la propiedad de la unión entre un par de imágenes coincida (la probabilidad “inlier”) es pi , la probabilidad de encontrar una transformación correcta después de n ensayos es r n p ( H es correcta )=1- (1- ( pi ) ) Después de haber hecho muchos ensayos, la probabilidad de encontrar una homografía correcta es muy alta. Por cada par de potenciales uniones de imágenes, se tienen un grupo de propiedades de unión que son consistentemente geométricas (“inliers”) y un grupo de propiedades que están dentro del área de solapamiento pero no consistentes (“outliers”). La idea del modelo de verificación es comparar las probabilidades que éste grupo inliers/outliers sea generado por una unión correcta de las imágenes o por una unión errónea. Para una imagen dada, se indica el número total de parámetros o propiedades en el área de solapamiento nf y el número de “inliers” ni . El hecho de que una imagen sea unida correcta o incorrectamente se representa mediante una variable binaria m? { 0,1 } . El ( i) hecho de que la propiedad de unión f ? {0,1} sea inlier/outlier es independiente a Bernoulli, así pues el número total de “inliers” es Binomial p( f p( f ( 1:n f ) |m=1 )= B( ni ; n f , p 1 ) ( 1: nf ) |m=0 )= B( n i ; n f , p 0 ) Pág. 24 Anexos Donde p1 es la probabilidad de que un “inlier” de una propiedad dé una unión correcta, y p0 es la probabilidad de que un “inlier” dé una unión incorrecta. El grupo de variables de unión de propiedades n i=? nf i= 1 f (i ) B( x ; n , p )= { f (i ) ,i =1,2 , ... , n f } se denota f ( 1: n f ) . El número de “inliers” y B(.) es una distribución Binomial. n! p x ( 1- p )nx !( n- x )! x Se suelen utilizar los valores de p1=0.6 y p0=0.1. Ahora, se procede a evaluar la probabilidad de que una imagen haya sido unida correctamente utilizando la regla de Bayes. p ( m=1|f ( 1: n f ) )= p( f (1 : n f ) |m=1 ) p( m=1) p( f (1: n f ) ) 1 = 1+ p( f p( f (1 : n f ) |m= 0) p ( m=0 ) (1 : n f ) Se asume que una imagen ha sido unida si p ( m=1 )| f |m=1) p ( m=1) (1 : n f ) )> p min B(ni ;n f ,p 1) p(m=1) 1 ¿ ¿ B(ni ;n f ,p 0) p( m=0) reject accept 1 -1 pmin B.3.2 Corrección de la distorsión de la lente en la unión de las fotografías Como se ha explicado anteriormente, para realizar fotografías Esféricas se utilizan o bien objetivos muy angulares o bien objetivos ojos de pez. Ambos tipos de objetivos no siguen la geometría de la tangente plana, sino que incorporan distorsiones para alcanzar grandes campos de visión. Un objetivo del estilo antes mencionado sigue una función trigonométrica que cambia con rapidez que con dificultades puede aproximarse a un polinomio de tercer grado. Para un objetivo ojo de pez o bien muy angular, los parámetros de corrección de la lente corrigen la desviación entre las lentes reales y la geometría idílica de ése tipo de objetivo. Existen un total de 6 parámetros que tienen que ver en la corrección de la distorsión de la lente: o Campo de visión (FoV: Field of View): no es exactamente un error, pero es un parámetro que determina la distorsión de perspectiva de la imagen Diseño de aplicación para la generación de tours virtuales o Pág. 25 Los parámetros reales de corrección de la lente a, b y c que son utilizados para solucionar la distorsión radial (distorsión de barril y de pincushion) y la distorsión de ondulación o Los parámetros de desplazamiento de la lente d y e que corrigen el eje óptico si éste no está en el centro de la imagen Campo de visión (FoV) La longitud focal es una propiedad física de cada objetivo. Junto con el tamaño efectivo del sensor y la distancia de enfoque, se aproximan al campo visual de la imagen (existen otros factores que influyen en el mismo). Hay que tener presente que recortar una imagen puede cambiar el campo de visión de la misma, por tanto, si se quiere hacerlo con una imágenes, se debe hacer con el resto de las imágenes que quieren ser unidas a la misma medida. El campo de visión unido a la proyección de la lente (rectilíneo, esférico o cilíndrico) determina la distorsión de perspectiva. La distorsión de perspectiva es menor cuanto menor sea el valor de FoV. Parámetros a, b & c de la distorsión de lente Para ópticas perfectas rectilíneas, lo único que se debería saber es el campo de visión. Resultados perfectos se pueden conseguir con una proyección de los píxeles de a l imagen en un plano tangente. Desgraciadamente, los objetivos reales se desvían de ésta perfecta proyección. Las desviaciones alejan los puntos fijos de la escena de donde éstos deberían estar. Por suerte, éste movimiento suele aparecer radialmente, coincidiendo o alejado de un centro común; además, la cantidad de desviación es prácticamente la misma con un radio determinado respecto a ese centro. Por tanto, un modelo que corrija esa desviación da unos resultados bastante aceptables. Los parámetros a, b y c de la distorsión de la lente corresponde aun polinomio de tercer grado describiendo la distorsión radial de la lente: En donde rdest y rsrc son los radios normalizados referentes a un pixel de una imagen. El punto central de éste radio es donde el eje óptico cruza la imagen, normalmente en la imagen del centro. Normalizados en éste caso significa que el círculo más grande que encaja completamente en la imagen tiene radio 1.0, es decir, radio = 1 es la mitad del lado más pequeño de la imagen. Con un objetivo perfecto, los parámetros tendrían los Pág. 26 Anexos siguientes valores: a=b=c=0.0 y d=1.0, y por tanto daría r src=r dest . Normalmente, los valores de a,b y c son inferiores a 1.0, y en la mayoría de los casos inferior a 0.01. Valores demasiado grande, significa que se ha escogido un tipo de objetivo erróneo, por ejemplo, un objetivo ojo de pez en vez de linear o viceversa. Estos valores son en valor absoluto, ya que pueden ser tanto positivos como negativos. El cuarto parámetro (d) controla el resultado del tamaño de la imagen y tiene el siguiente valor: d =1- ( a + b+ c ) La aproximación polinominal nunca es exacta, pero puede dar una aproximación muy buena al comportamiento real de los objetivos. Parámetros de desplazamiento de la lente d y e Algunas veces el objetivo y el sensor de la imagen no estarán centrados uno respecto al otro. En este caso el eje óptico no se encontrará en el centro de la imagen. Si se utiliza el algoritmo de corrección de lente anteriormente explicado en las imágenes en donde no tiene el eje óptico centrado, la corrección de lente y de perspectiva se aplicará en un punto central erróneo. Los parámetros de desplazamiento de la lente d (desplazamiento horizontal) y e (desplazamiento vertical) compensa dicho problema. Éstos contienen valores en pixeles que determinan como de lejos está el centro de la corrección radial desplazada fuera del centro geométrico de la imagen. a,b,c y FoV son las propiedades físicas de la combinación objetivo-cámara. Si siempre se dispara con la misma configuración de enfoque, se pueden reusar los mismos parámetros de forma segura. En el caso contrario, aunque el valor de FoV cambiará notablemente, normalmente se suelen reutilizar los valores de a,b y c. Hay diferentes maneras de determinas los valores de a,b,c y FoV que calibran la combinación de objetivo-cámara: Diseño de aplicación para la generación de tours virtuales Pág. 27 ANEXO F. CÓDIGO VISUAL BASIC DE LAS PRINCIPALES VENTANAS DE LA APLICACIÓN Pág. 28 Anexos SUMARIO SUMARIO _____________________________________________________ 28 B.1 OBJETO ___________________________________________________ 29 B.2 VENTANA PANTALLA_TOUR_ESFERICO.VB ____________________ 30 B.3 PANTALLA FOTO_ESFERICA.VB ______________________________ 69 B.4 PANTALLA PUNTOS_CALIENTES_ESTATICOS __________________ 92 B.5 PANTALLA PARAMETROS.VB ________________________________ 97 B.6 PANTALLA OPCIONES_PUNTOS_CALIENTES_ESTATICOS ______ 103 Diseño de aplicación para la generación de tours virtuales Pág. 29 B.1 OBJETO Transcripción del código fuente (en Visual NET 2010) de las principales ventanas del programa. En este apartado se quiere mostrar de qué manera se han programado las principales características que definen al programa Esférica: manejo de fotos esféricas, creación de tours, puntos calientes, inserción de ficheros multimedia,etc… Pág. 30 Anexos B.2 Ventana Pantalla_Tour_Esferico.Vb Imports System.IO Imports System.Runtime.Serialization.Formatters.Binary Public Class frmPantalla_tour_esferico Private ficheroGuardar As String Private texto As String Private nombreFicheroXML As String = "" Private carpetaFicheroXML As String = "" Private Property dlgSave As SaveFileDialog Private Property dlgOpen As OpenFileDialog Private Property dlgCarpeta As FolderBrowserDialog Private Property dlgFile As OpenFileDialog 'Al presionar Nuevo Proyecto, se abrirá un cuadro de diálogo para buscar el archivo Private Sub NuevoProyectoToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiNuevo_Proyecto.Click 'Se vacia el objeto tourActual = Nothing imListPanoramicas.Images.Clear() ltViewPanoramicas.Clear() 'Se crea un nuevo objeto para poder volver a empezar Diseño de aplicación para la generación de tours virtuales tourActual = New TourEsferico() txtNombre_proyecto.Text = tourActual.tituloProyecto numTamaño_Alto.Value = tourActual.altoImagen numTamaño_ancho.Value = tourActual.anchoImagen btnAñadir_FE.Enabled = False btnConfiguracion_FE.Enabled = False btnEliminar_FE.Enabled = False msiBarra_inferior_opciones.Enabled = False msiConfiguración_visualización_html.Enabled = False msiAjustar_Imagen_Ventana.Enabled = False msiCerrar_Proyecto.Enabled = False msiPC_estaticos.Enabled = False msiCopiar.Enabled = False msiCortar.Enabled = False msiCrear_Tour.Enabled = False msiGuardar_Proyecto.Enabled = False msiGuardar_Proyecto_Como.Enabled = False msiModos_Ver_Imagen.Enabled = False msiPegar.Enabled = False msiRatón_teclado.Enabled = False msiVista_Previa_Tour.Enabled = False tsbtnBarra_inferior_opciones.Enabled = False tsbtnConfiguracion_Ventana_html.Enabled = False Pág. 31 Pág. 32 Anexos tsbtnCrear_tour.Enabled = False tsbtnGuardar_proyecto.Enabled = False tsbtnPC_estaticos.Enabled = False tsbtnRaton_teclado.Enabled = False txtArchivo_imagen.Text = "" numCalidad.Value = 0 numInercia.Value = 0 numNumero_puntos_calientes.Value = 0 End Sub 'Con Cargar Imagenes, se abrirá la ventana pertintente Private Sub CargarImágenesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiCargar_Imagenes.Click Call cargarImagenes() End Sub 'Al presionar en Salir, se cerrará el programa Private Sub SalirToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiSalir.Click End End Sub 'Al presionar en el botón de Acerca de, se abrirá una ventana con la información del programa Private Sub msiAcerca_de_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiAcerca_de.Click MessageBox.Show("Editor de tours esféricos realizado en Visual Basic. Autor: Laura Rampérez. Fecha: 16/10/2010", "Acerca de...", MessageBoxButtons.OK) End Sub Diseño de aplicación para la generación de tours virtuales Pág. 33 'Al presionar en Guardar Proyecto, se abrirá la ventana pertintente Private Sub msiGuardar_Proyecto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiGuardar_Proyecto.Click If tourActual.nombreFichero = "" Then dlgSave = New SaveFileDialog dlgSave.Filter = "Proyecto Tour Esférico (*.pte)|*.pte" dlgSave.Title = "Guarda Proyecto" If dlgSave.ShowDialog() = DialogResult.OK Then ficheroGuardar = dlgSave.FileName Dim objArchivo As New System.IO.FileInfo(ficheroGuardar) Dim strNombre As String = objArchivo.Name tourActual.tituloProyecto = Mid(strNombre, 1, strNombre.Length - 4) tourActual.nombreFichero = dlgSave.FileName ficheroGuardar = dlgSave.FileName Call guardarProyecto(ficheroGuardar) End If Else ficheroGuardar = tourActual.nombreFichero Call guardarProyecto(ficheroGuardar) End If End Sub Pág. 34 Anexos 'Al presionar en Guardar Proyecto como, se abrirá la ventana pertinente Private Sub msiGuardar_Proyecto_Como_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiGuardar_Proyecto_Como.Click dlgSave = New SaveFileDialog dlgSave.Filter = "Proyecto Tour Esférico (*.pte)|*.pte" dlgSave.Title = "Guarda Proyecto" If dlgSave.ShowDialog() = DialogResult.OK Then ficheroGuardar = dlgSave.FileName Dim objArchivo As New System.IO.FileInfo(ficheroGuardar) Dim strNombre As String = objArchivo.Name tourActual.tituloProyecto = Mid(strNombre, 1, strNombre.Length - 4) tourActual.nombreFichero = dlgSave.FileName ficheroGuardar = dlgSave.FileName Call guardarProyecto(ficheroGuardar) End If End Sub Private Sub CrearTourToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiCrear_Tour.Click Call CrearTour() End Sub Private Sub tsbtnAbrir_proyecto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbtnAbrir_proyecto.Click Call msiAbrir_Proyecto_Click(sender, e) End Sub Private Sub pboxFoto_Esferica_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Diseño de aplicación para la generación de tours virtuales Pág. 35 frmPantalla_Foto_Esferica.ShowDialog() frmPantalla_Foto_Esferica.Dispose() Call ltViewPanoramicas_Click(sender, e) 'Refresco los datos cambiado End Sub Private Sub msiBarra_inferior_opciones_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiBarra_inferior_opciones.Click frmBarra_herramientas.ShowDialog() End Sub Private Sub System.Object, msiConfiguración_visualización_html_Click(ByVal ByVal e As System.EventArgs) sender As Handles msiConfiguración_visualización_html.Click frmConfiguración_visualización_html.ShowDialog() End Sub Private Sub msiRatón_teclado_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiRatón_teclado.Click frmRatón_teclado.ShowDialog() End Sub Private Sub msiVista_Previa_Tour_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiVista_Previa_Tour.Click 'ABRIR HTML Dim Path As String = nombreFicheroXML Shell("Rundll32.exe shell32.dll,OpenAs_RunDLL " & Path) End Sub 'Es la función para guardar el Proyecto Private Function guardarProyecto(ByVal ficheroProyecto As String) As Integer Dim myFileStream As Stream = File.Create(ficheroGuardar) Dim serializer As New BinaryFormatter() Pág. 36 Anexos serializer.Serialize(myFileStream, tourActual) myFileStream.Close() Return 0 End Function Private Function cargarDatosProyecto(ByVal ficheroProyecto As String) As Integer Dim myFileStream As Stream = File.OpenRead(ficheroProyecto) Dim deserializer As New BinaryFormatter() tourActual = CType(deserializer.Deserialize(myFileStream), TourEsferico) myFileStream.Close() Return 0 End Function 'Es la función para crear el Tour(código de PtViewer) Private Function CrearTour() As Integer If tourActual.tituloProyecto <> "" Then dlgCarpeta = New FolderBrowserDialog dlgCarpeta.Description = "Elegir la carpeta dónde se guarda el tour" If dlgCarpeta.ShowDialog() = DialogResult.OK Then nombreFicheroXML = dlgCarpeta.SelectedPath & "\" & tourActual.tituloProyecto & ".html" carpetaFicheroXML = dlgCarpeta.SelectedPath System.IO.Directory.CreateDirectory(dlgCarpeta.SelectedPath "\Imagenes\") 'COPIAR EL ARCHIVO .JAR & Diseño de aplicación para la generación de tours virtuales Pág. 37 Try FileCopy("ptviewer.jar", carpetaFicheroXML & "\ptviewer.jar") Catch cp As System.IO.IOException MsgBox("Falta el fichero ptviwer.jar en el directorio de ejecucion. Por favor copielo usted mismo") End Try Dim sw As New System.IO.StreamWriter(nombreFicheroXML) sw.WriteLine("<html>") sw.WriteLine("<title>" & tourActual.tituloProyecto & "</title>") sw.WriteLine("<head></head>") sw.WriteLine("<body>") sw.WriteLine(" <applet code=""ptviewer.class"" archive=""ptviewer.jar"" width=""" & tourActual.anchoImagen & "%"" height= """ & tourActual.altoImagen & "%""> ") 'Ponemos variables de touresferico If tourActual.xBar <> 0 Then sw.WriteLine(" <param name=bar_x value="" " & tourActual.xBar & """>") End If If tourActual.yBar <> 0 Then sw.WriteLine(" <param name=bar_y value="" " & tourActual.yBar & """>") End If If tourActual.widthBar <> 0 Then sw.WriteLine(" tourActual.widthBar & """>") End If <param name=bar_width value="" " & Pág. 38 Anexos If tourActual.heightBar <> 0 Then sw.WriteLine(" <param name=bar_height value="" " & tourActual.heightBar & """>") End If 'COLOR DE LA BARRA If tourActual.colorBar <> Mid(Hex(Color.DarkGray.ToArgb), 3) Then sw.WriteLine(" <param name=barcolor value=""c " & " & tourActual.colorBar & " "">") End If If tourActual.visibleBar = True Then sw.WriteLine("<param name=showToolbar value=""true"">") End If If tourActual.xDescrBar <> 0 Then sw.WriteLine("<param name=toolbarDescr_x value="" tourActual.xDescrBar & " "">") End If If tourActual.colorDescrBar <> Mid(Hex(Color.Black.ToArgb), 3) Then sw.WriteLine(" <param name=toolbarDescr_color value="" " & tourActual.colorDescrBar & " "">") End If If tourActual.imageBar <> "" Then sw.WriteLine(" <param name=toolbarImage value="" " tourActual.imageBarsin & " "">") End If If tourActual.loadBar = True Then sw.WriteLine(" <param name=imgLoadFeedback value=""true"">") & Diseño de aplicación para la generación de tours virtuales Pág. 39 End If If tourActual.boldTextBar = True Then sw.WriteLine(" <param name=toolbarBoldText value=""true"">") End If If tourActual.xView <> 0 Then sw.WriteLine(" <param name=View_x value=""" & tourActual.xView & """>") End If If tourActual.yView <> 0 Then sw.WriteLine(" <param name=View_y value=""" & tourActual.yView & """>") End If 'COLOR fondo If tourActual.colorView <> Mid(Hex(Color.White.ToArgb), 3) Then sw.WriteLine(" <param name=bgcolor value=""c" & tourActual.colorView & """>") End If 'LOGO If tourActual.cursor = 1 Then sw.WriteLine(" <param name=cursor value=""MOVE"">") Else : sw.WriteLine(" <param name=cursor value=""CROSSHAIR"">") End If If tourActual.mouseSensibility <> 1 Then sw.WriteLine(" tourActual.mouseSensibility & """>") <param name=mouseSensibility value=""" & Pág. 40 Anexos End If If tourActual.mousePanTime <> 20 Then sw.WriteLine(" <param name=mousePanTime value="" " & tourActual.mousePanTime & """>") End If 'MENSAJE ESTADO If tourActual.authoringMode = True Then sw.WriteLine(" <param name=authoringMode value=""true"">") End If 'Puntos calientes estáticos If Not (tourActual.shs(0) Is Nothing) Then For k As Integer = 0 To tourActual.shs.Count - 1 If tourActual.shs(k).estatico = True Then If tourActual.shs(k).popupHS = False And tourActual.shs(k).siempreVisible = False Then sw.Write(" <param name=shotspot" & k & " value="" x" & tourActual.shs(k).xnumber tourActual.shs(k).anumber & & " y" & tourActual.shs(k).ynumber & " a" & " b" & tourActual.shs(k).bnumber & " u'" & tourActual.shs(k).enlaceHS & "' ") ElseIf tourActual.shs(k).popupHS = True And tourActual.shs(k).siempreVisible = False Then sw.Write(" <param name=shotspot" & k & " value="" x" & tourActual.shs(k).xnumber tourActual.shs(k).anumber & " & " y" & tourActual.shs(k).ynumber & " a" & b" tourActual.shs(k).enlaceHS & "' ") & tourActual.shs(k).bnumber & " p u'" & Diseño de aplicación para la generación de tours virtuales ElseIf Pág. 41 tourActual.shs(k).popupHS = False And tourActual.shs(k).siempreVisible = True Then sw.Write(" <param name=shotspot" & k & " value="" x" & tourActual.shs(k).xnumber tourActual.shs(k).anumber & " & " y" & tourActual.shs(k).ynumber & " a" & b" & tourActual.shs(k).bnumber & " q u'" & tourActual.shs(k).enlaceHS & "' ") ElseIf tourActual.shs(k).popupHS = True And tourActual.shs(k).siempreVisible = True Then sw.Write(" <param name=shotspot" & k & " value="" x" & tourActual.shs(k).xnumber tourActual.shs(k).anumber & & " y" & tourActual.shs(k).ynumber & " a" & " b" & tourActual.shs(k).bnumber & " p q u'" & tourActual.shs(k).enlaceHS & "' ") End If If tourActual.shs(k).accionHS.numComando <> -1 Then Select Case tourActual.shs(k).accionHS.numComando Case 0 FileCopy(tourActual.shs(k).accionHS.parametros(0), carpetaFicheroXML "\Imagenes\Imagen_Punto_Caliente_Estatico" & k & ".jpg") sw.WriteLine(" i'\Imagenes\Imagen_Punto_Caliente_Estatico" & k & ".jpg' "">") Case 1 sw.WriteLine(" i'ptviewer:ZoomIn()' "">") Case 2 sw.WriteLine(" i'ptviewer:ZoomOut()' "">") Case 3 sw.WriteLine(" i'ptviewer:panLeft()' "">") Case 4 & Pág. 42 Anexos sw.WriteLine(" i'ptviewer:panRight()' "">") Case 5 sw.WriteLine(" i'ptviewer:panUp()' "">") Case 6 sw.WriteLine(" i'ptviewer:panDown()' "">") Case 7 sw.WriteLine(" tourActual.shs(k).accionHS.parametros(0) & tourActual.shs(k).accionHS.parametros(1) i'ptviewer:gotoView(" ", & " "," & & & tourActual.shs(k).accionHS.parametros(2) & ")' "">") Case 8 sw.WriteLine(" i'ptviewer:showHS()' "">") Case 9 sw.WriteLine(" i'ptviewer:hideHS()' "">") Case 10 sw.WriteLine(" i'ptviewer:toggleHS()' "">") Case 11 sw.WriteLine(" i'ptviewer:startAutoPan(" & tourActual.shs(k).accionHS.parametros(0) & "," & tourActual.shs(k).accionHS.parametros(1) & "," & tourActual.shs(k).accionHS.parametros(2) & ")' "">") Case 12 sw.WriteLine(" i'ptviewer:stopAutoPan()' "">") Case 13 sw.WriteLine(" i'ptviewer:newPanoFromList(" & tourActual.shs(k).accionHS.parametros(0) & "," & tourActual.shs(k).accionHS.parametros(1) & "," & tourActual.shs(k).accionHS.parametros(2) & "," & Diseño de aplicación para la generación de tours virtuales Pág. 43 tourActual.shs(k).accionHS.parametros(3) & ")' "">") Case 14 sw.WriteLine(" i'ptviewer:moveFromTo(" & tourActual.shs(k).accionHS.parametros(0) & "," & tourActual.shs(k).accionHS.parametros(1) & "," & tourActual.shs(k).accionHS.parametros(2) & "," & tourActual.shs(k).accionHS.parametros(3) & "," & tourActual.shs(k).accionHS.parametros(4) & "," & tourActual.shs(k).accionHS.parametros(5) & "," & tourActual.shs(k).accionHS.parametros(6) & "," & i'ptviewer:moveTo(" & tourActual.shs(k).accionHS.parametros(7) & ")' "">") Case 15 sw.WriteLine(" tourActual.shs(k).accionHS.parametros(0) & "," & tourActual.shs(k).accionHS.parametros(1) & "," & tourActual.shs(k).accionHS.parametros(2) & "," & tourActual.shs(k).accionHS.parametros(3) & "," & i'ptviewer:playSound(" & tourActual.shs(k).accionHS.parametros(4) & ")' "">") Case 16 sw.WriteLine(" tourActual.shs(k).accionHS.parametros(0) & ")' "">") Case 17 sw.WriteLine(" i'ptviewer:DrawSHSImage(" & tourActual.shs(k).accionHS.parametros(0) & ")' "">") Case 18 sw.WriteLine(" i'ptviewer:HideSHSImage(" & tourActual.shs(k).accionHS.parametros(0) & ")' "">") Case 19 sw.WriteLine(" i'ptviewer:ToggleSHSImage(" & tourActual.shs(k).accionHS.parametros(0) & ")' "">") Case 20 sw.WriteLine(" i'ptviewer:ShowCompass()' Pág. 44 Anexos "">") Case 21 sw.WriteLine(" i'ptviewer:HideCompass()' "">") Case 22 sw.WriteLine(" i'ptviewer:waitWhilePanning()' "">") Case 23 sw.WriteLine(" i'ptviewer:loadROI(" & i'ptviewer:loadROI(" & "," & i'ptviewer:setQuality(" & tourActual.shs(k).accionHS.parametros(0) & ")' "">") Case 24 sw.WriteLine(" tourActual.shs(k).accionHS.parametros(0) & tourActual.shs(k).accionHS.parametros(1) & ")' "">") Case 25 sw.WriteLine(" tourActual.shs(k).accionHS.parametros(0) & ")' "">") Case 26 sw.WriteLine(" i'ptviewer:shsEnableVisibleOnly()' "">") Case 27 sw.WriteLine(" "">") End Select Else sw.WriteLine(" "">") End If i'ptviewer:DrawSHSPopup()' Diseño de aplicación para la generación de tours virtuales Pág. 45 End If Next k End If For i As Integer = 0 To tourActual.fotosEsfericas.Count - 1 sw.Write(" <param name=pano" & i & " value=""{file=Imagenes\" & tourActual.fotosEsfericas(i).nombreFile & "}") 'Copiar la foto esférica en el directorio que se está creando de imágenes Try FileCopy(tourActual.fotosEsfericas(i).pFile, carpetaFicheroXML & "\Imagenes\" & tourActual.fotosEsfericas(i).nombreFile) Catch ex As System.IO.IOException MsgBox(Err.Description) Return Err.Number Exit Function End Try If tourActual.fotosEsfericas(i).loadAllRoi = True Then sw.Write(" {LoadAllRoi=true} ") End If 'ROIS, copiando las imágenes If tourActual.fotosEsfericas(i).panSinLimite = False Then sw.Write(" {panMax=" & tourActual.fotosEsfericas(i).panMax & "}") sw.Write(" {panMin=" & tourActual.fotosEsfericas(i).panMin & "}") End If If tourActual.fotosEsfericas(i).tiltMin <> 0 Then Pág. 46 Anexos sw.Write(" {tiltMin=" & tourActual.fotosEsfericas(i).tiltMin & "}") End If If tourActual.fotosEsfericas(i).tiltMax <> 0 Then sw.Write(" {tiltMax=" & tourActual.fotosEsfericas(i).tiltMax & "}") End If If tourActual.fotosEsfericas(i).fovMax <> 0 Then sw.Write(" {fovMax=" & tourActual.fotosEsfericas(i).fovMax & "}") End If If tourActual.fotosEsfericas(i).fovMin <> 0 Then sw.Write(" {fovMin=" & tourActual.fotosEsfericas(i).fovMin & "}") End If If tourActual.fotosEsfericas(i).panInicio <> 0 Then sw.WriteLine(" {pan=" & tourActual.fotosEsfericas(i).panInicio & "}") End If If tourActual.fotosEsfericas(i).tiltInicio <> 0 Then sw.Write(" {tilt=" & tourActual.fotosEsfericas(i).tiltInicio & "}") End If If tourActual.fotosEsfericas(i).fovInicio <> 0 Then sw.Write(" {fov=" & tourActual.fotosEsfericas(i).fovInicio & "}") End If Diseño de aplicación para la generación de tours virtuales Pág. 47 'Inits If tourActual.fotosEsfericas(i).inits.numComando > -1 Then sw.Write(" {inits=") Select Case tourActual.fotosEsfericas(i).inits.numComando Case 0 sw.Write("ptviewer:ZoomIn()") Case 1 sw.Write("ptviewer:ZoomOut()") Case 2 sw.Write("ptviewer:panLeft()") Case 3 sw.Write("ptviewer:panRight()") Case 4 sw.Write("ptviewer:panUp()") Case 5 sw.Write("ptviewer:panDown()") Case 6 sw.Write("ptviewer:gotoView(" tourActual.fotosEsfericas(i).inits.parametros(0) tourActual.fotosEsfericas(i).inits.parametros(1) & & tourActual.fotosEsfericas(i).inits.parametros(2) & ")") Case 7 sw.Write("ptviewer:showHS()") Case 8 sw.Write("ptviewer:hideHS()") Case 9 & ", " "," & & Pág. 48 Anexos sw.Write("ptviewer:toggleHS()") Case 10 sw.Write("ptviewer:startAutoPan(" & tourActual.fotosEsfericas(i).inits.parametros(0) & "," & tourActual.fotosEsfericas(i).inits.parametros(1) & "," & tourActual.fotosEsfericas(i).inits.parametros(2) & ")") Case 11 sw.Write("ptviewer:stopAutoPan()") Case 12 sw.Write("ptviewer:newPanoFromList(" & tourActual.fotosEsfericas(i).inits.parametros(0) & "," & tourActual.fotosEsfericas(i).inits.parametros(1) & "," & tourActual.fotosEsfericas(i).inits.parametros(2) & "," & tourActual.fotosEsfericas(i).inits.parametros(3) & ")") Case 13 sw.Write("ptviewer:moveFromTo(" & tourActual.fotosEsfericas(i).inits.parametros(0) & "," & tourActual.fotosEsfericas(i).inits.parametros(1) & "," & tourActual.fotosEsfericas(i).inits.parametros(2) & "," & tourActual.fotosEsfericas(i).inits.parametros(3) & "," & tourActual.fotosEsfericas(i).inits.parametros(4) & "," & tourActual.fotosEsfericas(i).inits.parametros(5) & "," & tourActual.fotosEsfericas(i).inits.parametros(6) & "," & tourActual.fotosEsfericas(i).inits.parametros(7) & ")") Case 14 sw.Write("ptviewer:moveTo(" & tourActual.fotosEsfericas(i).inits.parametros(0) & "," & tourActual.fotosEsfericas(i).inits.parametros(1) & "," & tourActual.fotosEsfericas(i).inits.parametros(2) & "," & tourActual.fotosEsfericas(i).inits.parametros(3) & "," & tourActual.fotosEsfericas(i).inits.parametros(4) & ")") Case 15 sw.Write("ptviewer:playSound(" tourActual.fotosEsfericas(i).inits.parametros(0) & ")") & Diseño de aplicación para la generación de tours virtuales Pág. 49 Case 16 sw.Write("ptviewer:DrawSHSImage(" & tourActual.fotosEsfericas(i).inits.parametros(0) & ")") Case 17 sw.Write("ptviewer:HideSHSImage(" & tourActual.fotosEsfericas(i).inits.parametros(0) & ")") Case 18 sw.Write("ptviewer:ToggleSHSImage(" & tourActual.fotosEsfericas(i).inits.parametros(0) & ")") Case 19 sw.Write("ptviewer:ShowCompass()") Case 20 sw.Write("ptviewer:HideCompass()") Case 21 sw.Write("ptviewer:waitWhilePanning()") Case 22 sw.Write("ptviewer:loadROI(" & tourActual.fotosEsfericas(i).inits.parametros(0) & ")") Case 23 sw.Write("ptviewer:loadROI(" tourActual.fotosEsfericas(i).inits.parametros(0) & & "," & tourActual.fotosEsfericas(i).inits.parametros(1) & ")") Case 24 sw.Write("ptviewer:setQuality(" tourActual.fotosEsfericas(i).inits.parametros(0) & ")") Case 25 sw.Write("ptviewer:hsEnableVisibleOnly()") Case 26 & Pág. 50 Anexos sw.Write("ptviewer:hsShowDescrInStatusBar()") Case 27 sw.Write("ptviewer:popup_panning()") Case 28 sw.Write(tourActual.fotosEsfericas(i).inits.parametros(0)) End Select sw.Write("}") End If If tourActual.fotosEsfericas(i).waitImagen <> "" Then FileCopy(tourActual.fotosEsfericas(i).waitImagen, carpetaFicheroXML & "\Imagenes\Waitimagen.jpg ") sw.Write(" {wait=\Imagenes\Waitimagen.jpg}") End If If tourActual.fotosEsfericas(i).waittime <> 0 Then sw.Write(" {waittime=" & tourActual.fotosEsfericas(i).waittime & "}") End If If tourActual.fotosEsfericas(i).quality <> 3 Then sw.Write(" {quality=" & tourActual.fotosEsfericas(i).quality & "}") End If If tourActual.fotosEsfericas(i).mass <> 0 Then sw.Write(" "}") End If {mass=" & tourActual.fotosEsfericas(i).mass & Diseño de aplicación para la generación de tours virtuales Pág. 51 If tourActual.fotosEsfericas(i).antialias = True Then sw.Write(" {antialias=" & tourActual.fotosEsfericas(i).antialias & "}") End If If tourActual.fotosEsfericas(i).horizonPosition <> 50 Then sw.Write(" {horizonPosition=" & tourActual.fotosEsfericas(i).horizonPosition & "}") End If 'Puntos calientes If tourActual.fotosEsfericas(i).hs(0).nombreHS <> "" Then For j As Integer = 0 To tourActual.fotosEsfericas(i).hs.Count - 1 If tourActual.fotosEsfericas(i).hs(j).estatico = False Then If False And tourActual.fotosEsfericas(i).hs(j).popupHS tourActual.fotosEsfericas(i).hs(j).siempreVisible = False = And tourActual.fotosEsfericas(i).hs(j).colorHS = "FF0000" Then sw.Write(" {hotspot" & j & "= x" & tourActual.fotosEsfericas(i).hs(j).xnumber & " y" & tourActual.fotosEsfericas(i).hs(j).ynumber & " n'" & tourActual.fotosEsfericas(i).hs(j).nombreHS & "' u'" & tourActual.fotosEsfericas(i).hs(j).enlaceHS & "'}") ElseIf tourActual.fotosEsfericas(i).hs(j).popupHS = True And tourActual.fotosEsfericas(i).hs(j).siempreVisible = False And tourActual.fotosEsfericas(i).hs(j).colorHS = "FF0000" Then sw.Write(" {hotspot" tourActual.fotosEsfericas(i).hs(j).xnumber tourActual.fotosEsfericas(i).hs(j).ynumber & & tourActual.fotosEsfericas(i).hs(j).nombreHS & " & j & " "= y" p n'" "' u'" x" & & & & tourActual.fotosEsfericas(i).hs(j).enlaceHS & "'}") ElseIf tourActual.fotosEsfericas(i).hs(j).popupHS = False And tourActual.fotosEsfericas(i).hs(j).siempreVisible = True And Pág. 52 Anexos tourActual.fotosEsfericas(i).hs(j).colorHS = "FF0000" Then sw.Write(" {hotspot" tourActual.fotosEsfericas(i).hs(j).xnumber & tourActual.fotosEsfericas(i).hs(j).ynumber & & " tourActual.fotosEsfericas(i).hs(j).nombreHS j & " & "= x" y" q & n'" "' & & u'" & tourActual.fotosEsfericas(i).hs(j).enlaceHS & "'}") ElseIf tourActual.fotosEsfericas(i).hs(j).popupHS = False And tourActual.fotosEsfericas(i).hs(j).siempreVisible = False And tourActual.fotosEsfericas(i).hs(j).colorHS <> "FF0000" Then sw.Write(" {hotspot" & j & "= x" & tourActual.fotosEsfericas(i).hs(j).xnumber & " y" & tourActual.fotosEsfericas(i).hs(j).ynumber & " c" & tourActual.fotosEsfericas(i).hs(j).colorHS & " n'" & tourActual.fotosEsfericas(i).hs(j).nombreHS & "' u'" & tourActual.fotosEsfericas(i).hs(j).enlaceHS & "'}") ElseIf tourActual.fotosEsfericas(i).hs(j).popupHS = True And tourActual.fotosEsfericas(i).hs(j).siempreVisible = True And tourActual.fotosEsfericas(i).hs(j).colorHS = "FF0000" Then sw.Write(" {hotspot" tourActual.fotosEsfericas(i).hs(j).xnumber tourActual.fotosEsfericas(i).hs(j).ynumber & & j & " " tourActual.fotosEsfericas(i).hs(j).nombreHS & x" y" p & "= q & n'" "' & & u'" & tourActual.fotosEsfericas(i).hs(j).enlaceHS & "'}") ElseIf tourActual.fotosEsfericas(i).hs(j).popupHS = False And tourActual.fotosEsfericas(i).hs(j).siempreVisible = True And tourActual.fotosEsfericas(i).hs(j).colorHS <> "FF0000" Then sw.Write(" {hotspot" tourActual.fotosEsfericas(i).hs(j).xnumber tourActual.fotosEsfericas(i).hs(j).ynumber & & & j & " " "= x" y" q & & c" & tourActual.fotosEsfericas(i).hs(j).colorHS & " n'" & tourActual.fotosEsfericas(i).hs(j).nombreHS & "' u'" & tourActual.fotosEsfericas(i).hs(j).enlaceHS & "'}") ElseIf tourActual.fotosEsfericas(i).hs(j).popupHS = True And tourActual.fotosEsfericas(i).hs(j).siempreVisible = False And tourActual.fotosEsfericas(i).hs(j).colorHS <> "FF0000" Then sw.Write(" {hotspot" & j & "= x" & Diseño de aplicación para la generación de tours virtuales Pág. 53 tourActual.fotosEsfericas(i).hs(j).xnumber & tourActual.fotosEsfericas(i).hs(j).ynumber " & y" " p & c" & tourActual.fotosEsfericas(i).hs(j).colorHS & " n'" & tourActual.fotosEsfericas(i).hs(j).nombreHS & "' u'" & tourActual.fotosEsfericas(i).hs(j).enlaceHS & "'}") ElseIf tourActual.fotosEsfericas(i).hs(j).popupHS = True And tourActual.fotosEsfericas(i).hs(j).siempreVisible = True And tourActual.fotosEsfericas(i).hs(j).colorHS <> "FF0000" Then sw.Write(" {hotspot" tourActual.fotosEsfericas(i).hs(j).xnumber & tourActual.fotosEsfericas(i).hs(j).ynumber & & j & " " "= x" y" p q & & c" & tourActual.fotosEsfericas(i).hs(j).colorHS & " n'" & tourActual.fotosEsfericas(i).hs(j).nombreHS & "' u'" & tourActual.fotosEsfericas(i).hs(j).enlaceHS & "'}") End If If tourActual.fotosEsfericas(i).hs(j).accionHS.numComando <> -1 Then Select Case tourActual.fotosEsfericas(i).hs(j).accionHS.numComando Case 0 FileCopy(tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0), carpetaFicheroXML & "\Imagenes\Imagen_Punto_Caliente" & j & ".jpg") sw.Write(" i'\Imagenes\Imagen_Punto_Caliente" & j & ".jpg' "">") Case 1 sw.Write(" i'" tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & "' "">") Case 2 sw.Write(" i'ptviewer:ZoomIn()' ") Case 3 sw.Write(" i'ptviewer:ZoomOu()' ") & Pág. 54 Anexos Case 4 sw.Write(" i'ptviewer:panLeft()' ") Case 5 sw.Write(" i'ptviewer:panRight()' ") Case 6 sw.Write(" i'ptviewer:panUp()' ") Case 7 sw.Write(" i'ptviewer:panDown()' ") Case 8 sw.Write(" tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(1) i'ptviewer:gotoView(" & ", & " "," & & & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(2) & ")' ") Case 9 sw.Write(" i'ptviewer:showHS()' ") Case 10 sw.Write(" i'ptviewer:hideHS()' ") Case 11 sw.Write(" i'ptviewer:toggleHS()' ") Case 12 sw.Write(" i'ptviewer:startAutoPan(" & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(1) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(2) & ")' ") Case 13 sw.Write(" i'ptviewer:stopAutoPan()' ") Case 14 Diseño de aplicación para la generación de tours virtuales Pág. 55 sw.Write(" i'ptviewer:newPanoFromList(" & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(1) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(2) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(3) & ")' ") Case 15 sw.Write(" i'ptviewer:moveFromTo(" & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(1) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(2) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(3) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(4) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(5) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(6) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(7) & ")' ") Case 16 sw.Write(" i'ptviewer:moveTo(" & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(1) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(2) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(3) & "," & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(4) & ")' ") Case 17 sw.Write(" i'ptviewer:playSound(" & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & ")' ") Case 18 sw.Write(" i'ptviewer:DrawSHSImage(" & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & ")' ") Case 19 sw.Write(" i'ptviewer:HideSHSImage(" & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & ")' ") Case 20 sw.Write(" i'ptviewer:ToggleSHSImage(" & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & ")' ") Pág. 56 Anexos Case 21 sw.Write(" i'ptviewer:ShowCompass()' ") Case 22 sw.Write(" i'ptviewer:HideCompass()' ") Case 23 sw.Write(" i'ptviewer:waitWhilePanning()' ") Case 24 sw.Write(" i'ptviewer:loadROI(" & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & ")' ") Case 25 sw.Write(" i'ptviewer:loadROI(" tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & "," & & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(1) & ")' ") Case 26 sw.Write(" i'ptviewer:setQuality(" & tourActual.fotosEsfericas(i).hs(j).accionHS.parametros(0) & ")' ") Case 27 sw.Write(" i'ptviewer:hsEnableVisibleOnly()' ") Case 28 sw.Write(" i'ptviewer:hsShowDescrInStatusBar()' ") Case 29 sw.Write(" ") End Select End If i'ptviewer:popup_panning()' Diseño de aplicación para la generación de tours virtuales Pág. 57 End If Next j End If sw.WriteLine(" "">") Next i sw.WriteLine("<param name=file value=""ptviewer:0"">") sw.WriteLine("</applet>") sw.WriteLine("</body>") sw.WriteLine("</html>") sw.Close() End If 'Poner que se active Vista Previa Tour msiVista_Previa_Tour.Enabled = True Else MsgBox("Se debe poner un nombre de Tour Esférico", MsgBoxStyle.Exclamation, "Advertencia") End If Return 0 End Function Private Sub tsbtnCrear_tour_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbtnCrear_tour.Click Call CrearTour() End Sub Private Sub tsbtnBarra_inferior_opciones_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbtnBarra_inferior_opciones.Click frmBarra_herramientas.ShowDialog() Pág. 58 Anexos End Sub Private Sub System.Object, tsbtnConfiguracion_Ventana_html_Click(ByVal ByVal e As System.EventArgs) sender As Handles tsbtnConfiguracion_Ventana_html.Click frmConfiguración_visualización_html.ShowDialog() End Sub Private Sub tsbtnRaton_teclado_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbtnRaton_teclado.Click frmRatón_teclado.ShowDialog() End Sub Private Sub msiAbrir_Proyecto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiAbrir_Proyecto.Click dlgOpen = New OpenFileDialog dlgOpen.Filter = "Proyecto Tour Esférico (*.pte)|*.pte" dlgOpen.Title = "Abrir Proyecto" If dlgOpen.ShowDialog() = DialogResult.OK Then cargarDatosProyecto(dlgOpen.FileName) 'Cargo los datos del proyecto ltViewPanoramicas.Clear() imListPanoramicas.Images.Clear() For i As Integer = 0 To tourActual.fotosEsfericas.Count - 1 imListPanoramicas.Images.Add(Image.FromFile(tourActual.fotosEsfericas(i).pFile)) ltViewPanoramicas.Items.Add(tourActual.fotosEsfericas(i).nombreFile, i) Next i If tourActual.fotosEsfericas.Count > 0 Then Diseño de aplicación para la generación de tours virtuales ltViewPanoramicas.Refresh() btnAñadir_FE.Enabled = True btnConfiguracion_FE.Enabled = True btnEliminar_FE.Enabled = True msiBarra_inferior_opciones.Enabled = True msiConfiguración_visualización_html.Enabled = True msiAjustar_Imagen_Ventana.Enabled = True msiCerrar_Proyecto.Enabled = True msiPC_estaticos.Enabled = True msiCopiar.Enabled = True msiCortar.Enabled = True msiCrear_Tour.Enabled = True msiGuardar_Proyecto.Enabled = True msiGuardar_Proyecto_Como.Enabled = True msiModos_Ver_Imagen.Enabled = True msiPegar.Enabled = True msiRatón_teclado.Enabled = True tsbtnBarra_inferior_opciones.Enabled = True tsbtnConfiguracion_Ventana_html.Enabled = True tsbtnCrear_tour.Enabled = True tsbtnGuardar_proyecto.Enabled = True tsbtnPC_estaticos.Enabled = True tsbtnRaton_teclado.Enabled = True msiCargar_Sonidos.Enabled = True Pág. 59 Pág. 60 Anexos numeroFE = 0 'Coloco por defecto todo el control en la primera imagen txtArchivo_imagen.Text = tourActual.fotosEsfericas(numeroFE).nombreFile numTamaño_ancho.Value = tourActual.anchoImagen numTamaño_Alto.Value = tourActual.altoImagen numCalidad.Value = tourActual.fotosEsfericas(numeroFE).quality numInercia.Value = tourActual.fotosEsfericas(numeroFE).mass numNumero_puntos_calientes.Value = tourActual.fotosEsfericas(numeroFE).hs.Count End If txtNombre_proyecto.Text = tourActual.tituloProyecto End If End Sub Private Sub tsbtnNuevo_proyecto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbtnNuevo_proyecto.Click Call NuevoProyectoToolStripMenuItem_Click(sender, e) End Sub Private Sub pboxFoto_Esferica_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) txtNombre_proyecto.Text = tourActual.tituloProyecto txtArchivo_imagen.Text = tourActual.fotosEsfericas(numeroFE).nombreFile numCalidad.Value = tourActual.fotosEsfericas(numeroFE).quality numInercia.Value = tourActual.fotosEsfericas(numeroFE).mass numNumero_puntos_calientes.Value tourActual.fotosEsfericas(numeroFE).hs.Count End Sub = Diseño de aplicación para la generación de tours virtuales Pág. 61 Private Sub msiCerrar_Proyecto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiCerrar_Proyecto.Click tourActual = Nothing End Sub Private Sub tsbtnCargar_Imagenes_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbtnCargar_Imagenes.Click Call cargarImagenes() End Sub Private Sub PuntosCalientesEstáticosToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiPC_estaticos.Click frmPuntos_Calientes_estáticos.ShowDialog() End Sub Private Function Insert(ByVal p1 As String) As String Throw New NotImplementedException End Function Private Sub tsbtnGuardar_proyecto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbtnGuardar_proyecto.Click Call msiGuardar_Proyecto_Click(sender, e) End Sub Private Sub ltViewPanoramicas_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles ltViewPanoramicas.Click numeroFE = ltViewPanoramicas.FocusedItem.ImageIndex txtArchivo_imagen.Text = tourActual.fotosEsfericas(numeroFE).nombreFile numCalidad.Value = tourActual.fotosEsfericas(numeroFE).quality numInercia.Value = tourActual.fotosEsfericas(numeroFE).mass numNumero_puntos_calientes.Value tourActual.fotosEsfericas(numeroFE).hs.Count = Pág. 62 Anexos End Sub Private Sub ltViewPanoramicas_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles ltViewPanoramicas.DoubleClick frmPantalla_Foto_Esferica.ShowDialog() frmPantalla_Foto_Esferica.Dispose() Call ltViewPanoramicas_Click(sender, e) 'Refresco los datos cambiado End Sub Private Sub cargarImagenes() Dim numeroImagenes As Integer 'En el caso que sea la primera vez que se cargan imágenes dlgFile = New OpenFileDialog dlgFile.Multiselect = True dlgFile.Filter = "Imágenes JPG (*.jpg)|*.jpg|Mapas de bits (*.gif)|*.gif" dlgFile.Title = "Abre una imagen JPG o GIF" If dlgFile.ShowDialog() = DialogResult.OK Then Dim iTemporal As Integer If tourActual.fotosEsfericas.Count = tourActual.fotosEsfericas(0).pFile = "" Then iTemporal = 0 numeroImagenes = dlgFile.FileNames.Count ReDim tourActual.fotosEsfericas(numeroImagenes - 1) Else iTemporal = tourActual.fotosEsfericas.Count numeroImagenes = iTemporal + dlgFile.FileNames.Count 1 And Diseño de aplicación para la generación de tours virtuales Pág. 63 ReDim Preserve tourActual.fotosEsfericas(numeroImagenes - 1) End If For i As Integer = 0 To dlgFile.FileNames.Count - 1 tourActual.fotosEsfericas(i + iTemporal) = New FotoEsferica() tourActual.fotosEsfericas(i + iTemporal).pFile = dlgFile.FileNames(i) tourActual.fotosEsfericas(i + iTemporal).nombreFile dlgFile.SafeFileNames(i) Next i ltViewPanoramicas.Clear() imListPanoramicas.Images.Clear() For i As Integer = 0 To tourActual.fotosEsfericas.Count - 1 imListPanoramicas.Images.Add(Image.FromFile(tourActual.fotosEsfericas(i).pFile)) ltViewPanoramicas.Items.Add(tourActual.fotosEsfericas(i).nombreFile, i) Next i ltViewPanoramicas.Refresh() btnAñadir_FE.Enabled = True btnConfiguracion_FE.Enabled = True btnEliminar_FE.Enabled = True msiBarra_inferior_opciones.Enabled = True msiConfiguración_visualización_html.Enabled = True msiAjustar_Imagen_Ventana.Enabled = True msiCerrar_Proyecto.Enabled = True = Pág. 64 Anexos msiPC_estaticos.Enabled = True msiCopiar.Enabled = True msiCortar.Enabled = True msiCrear_Tour.Enabled = True msiGuardar_Proyecto.Enabled = True msiGuardar_Proyecto_Como.Enabled = True msiModos_Ver_Imagen.Enabled = True msiPegar.Enabled = True msiRatón_teclado.Enabled = True tsbtnBarra_inferior_opciones.Enabled = True tsbtnConfiguracion_Ventana_html.Enabled = True tsbtnCrear_tour.Enabled = True tsbtnGuardar_proyecto.Enabled = True tsbtnPC_estaticos.Enabled = True tsbtnRaton_teclado.Enabled = True msiCargar_Sonidos.Enabled = True End If End Sub Private Sub ImágenesEnTamañoGrandeToolStripMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msipTamaño_grande.Click ltViewPanoramicas.View = View.LargeIcon End Sub Private Sub ImágenesEnTamañoPequeñoToolStripMenuItem_Click(ByVal sender System.Object, ByVal e As System.EventArgs) Handles msipTamaño_Pequeño.Click ltViewPanoramicas.View = View.SmallIcon As Diseño de aplicación para la generación de tours virtuales Pág. 65 End Sub Private Sub msipLista_Click(ByVal sender As System.Object, ByVal e As e As System.EventArgs) Handles msipLista.Click ltViewPanoramicas.View = View.List End Sub Private Sub msipTítulos_Click(ByVal sender As System.Object, ByVal System.EventArgs) Handles msipTítulos.Click ltViewPanoramicas.View = View.Tile End Sub Private Sub DetallesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DetallesToolStripMenuItem.Click ' Dim subelemento As ListViewItem ltViewPanoramicas.View = View.Details End Sub Private Sub btnEliminar_FE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEliminar_FE.Click ' Si hay un Item seleccionado ... If ltViewPanoramicas.SelectedItems.Count() > 0 Then 'Pregunta si lo quiere eliminar If MsgBox("¿Seguro que desea eliminar la imagen " & tourActual.fotosEsfericas(numeroFE).nombreFile & "?", CType(vbQuestion + vbYesNo, MsgBoxStyle)) = vbYes Then 'Elimina el elemento seleccionado ( SelectedItem.Index ) ltViewPanoramicas.Items.RemoveAt(numeroFE) End If Else Pág. 66 Anexos MsgBox("¡No tiene ninguna imagen esferica selecionada!", MsgBoxStyle.Exclamation, "Advertencia") End If End Sub Private Sub btnAñadir_FE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAñadir_FE.Click Call cargarImagenes() End Sub Private Sub btnConfiguracion_FE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConfiguracion_FE.Click If ltViewPanoramicas.SelectedItems.Count() > 0 Then frmPantalla_Foto_Esferica.ShowDialog() frmPantalla_Foto_Esferica.Dispose() Call ltViewPanoramicas_Click(sender, e) 'Refresco los datos cambiado Else MsgBox("¡No tiene ninguna imagen esferica selecionada!", MsgBoxStyle.Exclamation, "Advertencia") End If End Sub Private Sub CargarSonidosToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles msiCargar_Sonidos.Click frmSonidos.ShowDialog() End Sub Private Sub msiAjustar_Imagen_Ventana_Click(ByVal sender As ByVal e As System.EventArgs) Handles msiAjustar_Imagen_Ventana.Click If ltViewPanoramicas.SelectedItems.Count() > 0 Then frmAmpliacion_imagen.ShowDialog() System.Object, Diseño de aplicación para la generación de tours virtuales Pág. 67 Else MsgBox("¡No tiene ninguna imagen esferica selecionada!", MsgBoxStyle.Exclamation, "Advertencia") End If End Sub Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtNombre_proyecto.TextChanged tourActual.tituloProyecto = txtNombre_proyecto.Text End Sub Private Sub tsbtnPC_estaticos_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbtnPC_estaticos.Click frmPuntos_Calientes_estáticos.ShowDialog() Call ltViewPanoramicas_Click(sender, e) 'Refresco los datos cambiado End Sub Private Sub numTamaño_ancho_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numTamaño_ancho.ValueChanged tourActual.anchoImagen = CInt(numTamaño_ancho.Value) End Sub Private Sub numTamaño_Alto_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numTamaño_Alto.ValueChanged tourActual.altoImagen = CInt(numTamaño_Alto.Value) End Sub Private Sub mnuStPanoramicas_ItemClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles mnuStPanoramicas.ItemClicked End Sub Private System.Object, Sub ltViewPanoramicas_SelectedIndexChanged(ByVal ByVal e As System.EventArgs) sender As Handles Pág. 68 ltViewPanoramicas.SelectedIndexChanged End Sub End Class Anexos Diseño de aplicación para la generación de tours virtuales Pág. 69 B.3 Pantalla Foto_Esferica.vb Public Class frmPantalla_Foto_Esferica Dim nombreImagen As String Dim enInicio As Boolean = False Public panoTmp As New FotoEsferica Private Property dlgFile As OpenFileDialog Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As sender As System.Object, ByVal e As As System.Object, ByVal e As System.EventArgs) Handles btnAceptar.Click Call GuardarDatosPano() panoTmp = Nothing Me.Close() End Sub Private Sub btnAplicar_Click(ByVal System.EventArgs) Handles btnAplicar.Click Call GuardarDatosPano() End Sub Private Sub btnCancelar_Click(ByVal sender System.EventArgs) Handles btnCancelar.Click panoTmp = Nothing Me.Close() End Sub Private Sub Pantalla_Foto_Esferica_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load If panoTmp Is Nothing Then panoTmp = New FotoEsferica Pág. 70 Anexos txtArchivo_foto_esferica.Text = tourActual.fotosEsfericas(numeroFE).pFile panoTmp.pFile = tourActual.fotosEsfericas(numeroFE).pFile panoTmp.nombreFile = tourActual.fotosEsfericas(numeroFE).nombreFile numCalidad.Value = CInt(tourActual.fotosEsfericas(numeroFE).quality) panoTmp.quality = tourActual.fotosEsfericas(numeroFE).quality numPosición_horizonte.Value = CInt(tourActual.fotosEsfericas(numeroFE).horizonPosition) panoTmp.horizonPosition = tourActual.fotosEsfericas(numeroFE).horizonPosition txtImagen_mientras_se_carga.Text = tourActual.fotosEsfericas(numeroFE).waitImagen panoTmp.waitImagen = tourActual.fotosEsfericas(numeroFE).waitImagen numTiempo_espera.Value = CInt(tourActual.fotosEsfericas(numeroFE).waittime) panoTmp.waittime = tourActual.fotosEsfericas(numeroFE).waittime numAngulo_hor_inicio.Value = tourActual.fotosEsfericas(numeroFE).panInicio panoTmp.panInicio = tourActual.fotosEsfericas(numeroFE).panInicio numAngulo_ver_inicio.Value = tourActual.fotosEsfericas(numeroFE).tiltInicio panoTmp.tiltInicio = tourActual.fotosEsfericas(numeroFE).tiltInicio numFOV_inicio.Value = tourActual.fotosEsfericas(numeroFE).fovInicio panoTmp.fovInicio = tourActual.fotosEsfericas(numeroFE).fovInicio 'INICIO cbxSin_limites.Checked = tourActual.fotosEsfericas(numeroFE).panSinLimite If cbxSin_limites.Checked = True Then numMax_Pan.Enabled = False numMin_Pan.Enabled = False hsPanMax.Enabled = False Diseño de aplicación para la generación de tours virtuales Pág. 71 hsPanMin.Enabled = False Else numMax_Pan.Enabled = True numMin_Pan.Enabled = True hsPanMax.Enabled = True hsPanMin.Enabled = True numMax_Pan.Value = tourActual.fotosEsfericas(numeroFE).panMax numMin_Pan.Value = tourActual.fotosEsfericas(numeroFE).panMin End If If tourActual.fotosEsfericas(numeroFE).inits.numComando > -1 Then enInicio = True cboxInits.SelectedIndex = tourActual.fotosEsfericas(numeroFE).inits.numComando End If numMax_Tilt.Value = tourActual.fotosEsfericas(numeroFE).tiltMax numMin_Tilt.Value = tourActual.fotosEsfericas(numeroFE).tiltMin numMax_fov.Value = tourActual.fotosEsfericas(numeroFE).fovMax numMin_fov.Value = tourActual.fotosEsfericas(numeroFE).fovMin numInercia.Value = tourActual.fotosEsfericas(numeroFE).mass cboxAntialias.Checked = tourActual.fotosEsfericas(numeroFE).antialias dgrdPuntos_Calientes.Rows.Clear() 'limpio el grid If tourActual.fotosEsfericas(numeroFE).hs(0).nombreHS <> "" Then dgrdPuntos_Calientes.Rows.Add(tourActual.fotosEsfericas(numeroFE).hs.Count) 'Añado el numero de filas que necesitare For i As Integer = 0 To tourActual.fotosEsfericas(numeroFE).hs.Count - Pág. 72 Anexos 1 Dim textoTmp As String = "" dgrdPuntos_Calientes.Rows(i).Cells(0).Value = tourActual.fotosEsfericas(numeroFE).hs(i).nombreHS dgrdPuntos_Calientes.Rows(i).Cells(1).Value = tourActual.fotosEsfericas(numeroFE).hs(i).xnumber dgrdPuntos_Calientes.Rows(i).Cells(2).Value = tourActual.fotosEsfericas(numeroFE).hs(i).ynumber dgrdPuntos_Calientes.Rows(i).Cells(3).Value = tourActual.fotosEsfericas(numeroFE).hs(i).enlaceHS dgrdPuntos_Calientes.Rows(i).Cells(6).Value = tourActual.fotosEsfericas(numeroFE).hs(i).mascaraHS dgrdPuntos_Calientes.Rows(i).Cells(7).Value = tourActual.fotosEsfericas(numeroFE).hs(i).colorHS dgrdPuntos_Calientes.Rows(i).Cells(8).Value = tourActual.fotosEsfericas(numeroFE).hs(i).popupHS dgrdPuntos_Calientes.Rows(i).Cells(9).Value = tourActual.fotosEsfericas(numeroFE).hs(i).siempreVisible dgrdPuntos_Calientes.Rows(i).Cells(10).Value = tourActual.fotosEsfericas(numeroFE).hs(i).accionHS.numComando For j As Integer = 0 To tourActual.fotosEsfericas(numeroFE).hs(i).accionHS.parametros.Length - 1 If j <> 0 Then textoTmp = textoTmp & "," End If textoTmp tourActual.fotosEsfericas(numeroFE).hs(i).accionHS.parametros(j) Next j = Diseño de aplicación para la generación de tours virtuales Pág. 73 dgrdPuntos_Calientes.Rows(i).Cells(11).Value = textoTmp Next i End If End Sub Private Sub btnImagen_HD_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnImagen_HD.Click frmImagenes_HD.ShowDialog() End Sub Private Sub scrAngulo_hor_inicio_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles scrAngulo_hor_inicio.Scroll numAngulo_hor_inicio.Value = scrAngulo_hor_inicio.Value End Sub Private Sub scrAngulo_ver_inicio_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles scrAngulo_ver_inicio.Scroll numAngulo_ver_inicio.Value = scrAngulo_ver_inicio.Value End Sub Private Sub scrFov_inicio_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles scrFov_inicio.Scroll numFOV_inicio.Value = scrFov_inicio.Value End Sub Private Sub hsPanMax_Scroll(ByVal sender As System.Object, ByVal e As ByVal e As System.Windows.Forms.ScrollEventArgs) Handles hsPanMax.Scroll numMax_Pan.Value = hsPanMax.Value Call VisualizarImagenPan() End Sub Private Sub hsPanMin_Scroll(ByVal sender As System.Object, System.Windows.Forms.ScrollEventArgs) Handles hsPanMin.Scroll Pág. 74 Anexos numMin_Pan.Value = hsPanMin.Value Call VisualizarImagenPan() End Sub Private Sub hsTiltMax_Scroll(ByVal sender As System.Object, ByVal e As ByVal e As ByVal e As ByVal e As System.Windows.Forms.ScrollEventArgs) Handles hsTiltMax.Scroll numMax_Tilt.Value = hsTiltMax.Value Call VisualizarImagentilt() End Sub Private Sub hsTiltMin_Scroll(ByVal sender As System.Object, System.Windows.Forms.ScrollEventArgs) Handles hsTiltMin.Scroll numMin_Tilt.Value = hsTiltMin.Value Call VisualizarImagentilt() End Sub Private Sub hsFovMax_Scroll(ByVal sender As System.Object, System.Windows.Forms.ScrollEventArgs) Handles hsFovMax.Scroll numMax_fov.Value = hsFovMax.Value Call VisualizarImagenFov() End Sub Private Sub hsFovMin_Scroll(ByVal sender As System.Object, System.Windows.Forms.ScrollEventArgs) Handles hsFovMin.Scroll numMin_fov.Value = hsFovMin.Value Call VisualizarImagenFov() End Sub 'Cuando hayamos seleccionado Sin Limites Private Sub cbxSin_limites_CausesValidationChanged(ByVal sender As ByVal e As System.EventArgs) Handles cbxSin_limites.CausesValidationChanged Object, Diseño de aplicación para la generación de tours virtuales Pág. 75 Call VisualizarImagenPan() End Sub Private Sub cbxSin_limites_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cbxSin_limites.Click panoTmp.panSinLimite = CBool(cbxSin_limites.CheckState) If cbxSin_limites.Checked = True Then numMax_Pan.Enabled = False numMin_Pan.Enabled = False hsPanMax.Enabled = False hsPanMin.Enabled = False numMax_Pan.Value = 0 numMin_Pan.Value = 0 Else numMax_Pan.Enabled = True numMin_Pan.Enabled = True hsPanMax.Enabled = True hsPanMin.Enabled = True End If End Sub Private Sub dgrdPuntos_Calientes_CellClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) dgrdPuntos_Calientes.CellClick If dgrdPuntos_Calientes.CurrentCellAddress.X = 4 Then frmOpciones_puntos_calientes.ShowDialog() frmOpciones_puntos_calientes.Dispose() End If Handles Pág. 76 Anexos If dgrdPuntos_Calientes.CurrentCellAddress.X = 5 Then If (MsgBox("¿Estás seguro que deseas eliminar el punto caliente " & dgrdPuntos_Calientes.CurrentCellAddress.Y & "?", vbYesNo) = vbYes) Then dgrdPuntos_Calientes.Rows.Remove(dgrdPuntos_Calientes.CurrentRow) End If End If End Sub Private Sub numMax_Pan_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numMax_Pan.ValueChanged hsPanMax.Value = CInt(numMax_Pan.Value) panoTmp.panMax = CInt(numMax_Pan.Value) Call VisualizarImagenPan() End Sub Private Sub numMin_Pan_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numMin_Pan.ValueChanged hsPanMin.Value = CInt(numMin_Pan.Value) panoTmp.panMin = CInt(numMin_Pan.Value) Call VisualizarImagenPan() End Sub Private Sub numMax_Tilt_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numMax_Tilt.ValueChanged hsTiltMax.Value = CInt(numMax_Tilt.Value) panoTmp.tiltMax = CInt(numMax_Tilt.Value) Call VisualizarImagentilt() End Sub Diseño de aplicación para la generación de tours virtuales Pág. 77 Private Sub numMin_Tilt_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numMin_Tilt.ValueChanged hsTiltMin.Value = CInt(numMin_Pan.Value) panoTmp.tiltMin = CInt(numMin_Pan.Value) Call VisualizarImagentilt() End Sub Private Sub numMax_fov_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numMax_fov.ValueChanged hsFovMax.Value = CInt(numMax_fov.Value) panoTmp.fovMax = CInt(numMax_fov.Value) Call VisualizarImagenFov() End Sub Private Sub numMin_fov_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numMin_fov.ValueChanged hsFovMin.Value = CInt(numMin_fov.Value) panoTmp.fovMin = CInt(numMin_fov.Value) Call VisualizarImagenFov() End Sub Private Sub GuardarDatosPano() guardarPC() tourActual.fotosEsfericas(numeroFE) = panoTmp End Sub Private Sub numCalidad_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numCalidad.ValueChanged panoTmp.quality = CInt(numCalidad.Value) End Sub Pág. 78 Anexos Private Sub numPosición_horizonte_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numPosición_horizonte.ValueChanged panoTmp.horizonPosition = CInt(numPosición_horizonte.Value) End Sub Private Sub btnExplorar_Imagen_abajo_dcha_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExplorar_Imagen_abajo_dcha.Click dlgFile = New OpenFileDialog dlgFile.Filter = "Imágenes JPG (*.jpg)|*.jpg|Mapas de bits (*.gif)|*.gif" dlgFile.Title = "Abre una imagen JPG o GIF" If dlgFile.ShowDialog() = DialogResult.OK Then txtImagen_mientras_se_carga.Text = dlgFile.FileName panoTmp.waitImagen = dlgFile.FileName End If End Sub Private Sub txtImagen_mientras_se_carga_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtImagen_mientras_se_carga.Click If txtImagen_mientras_se_carga.Text = "" Then dlgFile = New OpenFileDialog dlgFile.Filter = "Imágenes JPG (*.jpg)|*.jpg|Mapas (*.gif)|*.gif" dlgFile.Title = "Abre una imagen JPG o GIF" If dlgFile.ShowDialog() = DialogResult.OK Then txtImagen_mientras_se_carga.Text = dlgFile.FileName panoTmp.waitImagen = dlgFile.FileName End If End If de bits Diseño de aplicación para la generación de tours virtuales Pág. 79 End Sub Private Sub numTiempo_espera_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numTiempo_espera.ValueChanged panoTmp.waittime = CInt(numTiempo_espera.Value) End Sub Private Sub numAngulo_hor_inicio_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numAngulo_hor_inicio.ValueChanged scrAngulo_hor_inicio.Value = CInt(numAngulo_hor_inicio.Value) panoTmp.panInicio = CInt(numAngulo_hor_inicio.Value) End Sub Private Sub numAngulo_ver_inicio_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numAngulo_ver_inicio.ValueChanged scrAngulo_ver_inicio.Value = CInt(numAngulo_ver_inicio.Value) panoTmp.tiltInicio = CInt(numAngulo_ver_inicio.Value) End Sub Private Sub numFOV_inicio_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numFOV_inicio.ValueChanged scrFov_inicio.Value = CInt(numFOV_inicio.Value) panoTmp.fovInicio = CInt(numFOV_inicio.Value) End Sub Private Sub numInercia_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles numInercia.ValueChanged panoTmp.mass = CInt(numInercia.Value) End Sub Private Sub cboxAntialias_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboxAntialias.CheckedChanged Pág. 80 Anexos panoTmp.antialias = CBool(cboxAntialias.CheckState) End Sub Private Sub guardarPC() If dgrdPuntos_Calientes.Rows.Count > 0 Then ReDim panoTmp.hs(dgrdPuntos_Calientes.Rows.Count - 1) For i As Integer = 0 To dgrdPuntos_Calientes.Rows.Count - 1 panoTmp.hs(i) = New Hotspot() panoTmp.hs(i).nombreHS = CStr(dgrdPuntos_Calientes.Rows(i).Cells(0).Value) panoTmp.hs(i).xnumber = CInt(dgrdPuntos_Calientes.Rows(i).Cells(1).Value) panoTmp.hs(i).ynumber = CInt(dgrdPuntos_Calientes.Rows(i).Cells(2).Value) panoTmp.hs(i).enlaceHS = CStr(dgrdPuntos_Calientes.Rows(i).Cells(3).Value) 'Guardar datos de opciones avanzadas If CStr(dgrdPuntos_Calientes.Rows(i).Cells(6).Value) <> "" Then panoTmp.hs(i).mensajeHS = True panoTmp.hs(i).mensajeTextoHS = CStr(dgrdPuntos_Calientes.Rows(i).Cells(6).Value) End If panoTmp.hs(i).colorHS = CStr(dgrdPuntos_Calientes.Rows(i).Cells(7).Value) panoTmp.hs(i).popupHS = CBool(dgrdPuntos_Calientes.Rows(i).Cells(8).Value) panoTmp.hs(i).siempreVisible = CBool(dgrdPuntos_Calientes.Rows(i).Cells(9).Value) panoTmp.hs(i).accionHS.numComando = Diseño de aplicación para la generación de tours virtuales Pág. 81 CInt(dgrdPuntos_Calientes.Rows(i).Cells(10).Value) panoTmp.hs(i).accionHS.parametros = Split(CStr(dgrdPuntos_Calientes.Rows(i).Cells(11).Value), ",") Next i End If End Sub Private Sub btnAñadir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAñadir_HS.Click dgrdPuntos_Calientes.Rows.Add() 'Inicializamos la columna de color puntos calientes a rojo, que es su valor por defecto dgrdPuntos_Calientes.CurrentRow.Cells(7).Value = "ff0000" dgrdPuntos_Calientes.CurrentRow.Cells(10).Value = -1 End Sub Private Sub dgrdPuntos_Calientes_CellDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgrdPuntos_Calientes.CellDoubleClick If (dgrdPuntos_Calientes.CurrentCellAddress.X = 1) Or (dgrdPuntos_Calientes.CurrentCellAddress.X = 2) Then frmIndicar_posición_HD.ShowDialog() End If End Sub Private Sub cboxInits_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboxInits.SelectedIndexChanged If enInicio Then enInicio = False Exit Sub Pág. 82 Anexos End If Select Case cboxInits.SelectedIndex Case 6 frmParametros_Inits.num1.Visible = True frmParametros_Inits.lb1.Visible = True frmParametros_Inits.lb1.Text = "Ángulo horizontal" frmParametros_Inits.num2.Visible = True frmParametros_Inits.lb2.Visible = True frmParametros_Inits.lb2.Text = "Ángulo vertical" frmParametros_Inits.num3.Visible = True frmParametros_Inits.lb3.Visible = True frmParametros_Inits.lb3.Text = "Campo de visión" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Case 10 frmParametros_Inits.num1.Visible = True frmParametros_Inits.lb1.Visible = True frmParametros_Inits.lb1.Text = "Incremento de ángulo horizontal" frmParametros_Inits.num2.Visible = True frmParametros_Inits.lb2.Visible = True frmParametros_Inits.lb2.Text = "Incremento de ángulo vertical" frmParametros_Inits.num3.Visible = True frmParametros_Inits.lb3.Visible = True frmParametros_Inits.lb3.Text = "Zoom" Diseño de aplicación para la generación de tours virtuales Pág. 83 frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Case 12 frmParametros_Inits.num1.Visible = True frmParametros_Inits.lb1.Visible = True frmParametros_Inits.lb1.Text = "Número de panorámica a cargar" frmParametros_Inits.num2.Visible = True frmParametros_Inits.lb2.Visible = True frmParametros_Inits.lb2.Text = "Ángulo horizontal" frmParametros_Inits.num3.Visible = True frmParametros_Inits.lb3.Visible = True frmParametros_Inits.lb3.Text = "Ángulo vertical" frmParametros_Inits.num4.Visible = True frmParametros_Inits.lb4.Visible = True frmParametros_Inits.lb4.Text = "Campo de visión" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Case 13 frmParametros_Inits.num1.Visible = True frmParametros_Inits.lb1.Visible = True frmParametros_Inits.lb1.Text = "Ángulo horizontal de inicio" frmParametros_Inits.num2.Visible = True frmParametros_Inits.lb2.Visible = True frmParametros_Inits.lb2.Text = "Ángulo horizontal de fin" Pág. 84 Anexos frmParametros_Inits.num3.Visible = True frmParametros_Inits.lb3.Visible = True frmParametros_Inits.lb3.Text = "Ángulo vertical de inicio" frmParametros_Inits.num4.Visible = True frmParametros_Inits.lb4.Visible = True frmParametros_Inits.lb4.Text = "Ángulo vertical de fin" frmParametros_Inits.num5.Visible = True frmParametros_Inits.lb5.Visible = True frmParametros_Inits.lb5.Text = "Campo de visión de inicio" frmParametros_Inits.num6.Visible = True frmParametros_Inits.lb6.Visible = True frmParametros_Inits.lb6.Text = "Campo de visión de fin" frmParametros_Inits.num7.Visible = True frmParametros_Inits.lb7.Visible = True frmParametros_Inits.lb7.Text = "Número de ""frames"" " frmParametros_Inits.num8.Visible = True frmParametros_Inits.lb8.Visible = True frmParametros_Inits.lb8.Text = "Tiempo del movimiento" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Case 14 frmParametros_Inits.num1.Visible = True frmParametros_Inits.lb1.Visible = True frmParametros_Inits.lb1.Text = "Ángulo horizontal" Diseño de aplicación para la generación de tours virtuales Pág. 85 frmParametros_Inits.num2.Visible = True frmParametros_Inits.lb2.Visible = True frmParametros_Inits.lb2.Text = "Ángulo vertical" frmParametros_Inits.num3.Visible = True frmParametros_Inits.lb3.Visible = True frmParametros_Inits.lb3.Text = "Campo de visión" frmParametros_Inits.num4.Visible = True frmParametros_Inits.lb4.Visible = True frmParametros_Inits.lb4.Text = "Número de ""frames""" frmParametros_Inits.num5.Visible = True frmParametros_Inits.lb5.Visible = True frmParametros_Inits.lb5.Text = "Tiempo del movimiento" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Case 15 frmParametros_Inits.cbx1.Visible = True 'RELLENAR EL COMBOBOX DE SONIDOS frmParametros_Inits.lb1.Text = "Sonido a emitir" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Case 16 If tourActual.shs.Count <> 1 And tourActual.shs(0).nombreHS <> "" Then frmParametros_Inits.cbx1.Visible = True For i As Integer = 0 To tourActual.shs.Count - 1 Pág. 86 Anexos frmParametros_Inits.cbx1.Items.Add(tourActual.shs(i).nombreHS) Next i frmParametros_Inits.lb1.Text = "Punto caliente estático a mostrar" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Else MsgBox("No existe ningún punto caliente estático", MsgBoxStyle.Exclamation, "Advertencia") End If Case 17 If tourActual.shs.Count <> 1 And tourActual.shs(0).nombreHS <> "" Then frmParametros_Inits.cbx1.Visible = True For i As Integer = 0 To tourActual.shs.Count - 1 frmParametros_Inits.cbx1.Items.Add(tourActual.shs(i).nombreHS) Next i frmParametros_Inits.lb1.Text = "Punto caliente estático a esconder" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Else MsgBox("No existe MsgBoxStyle.Exclamation, "Advertencia") End If Case 18 ningún punto caliente estático", Diseño de aplicación para la generación de tours virtuales Pág. 87 If tourActual.shs.Count <> 1 And tourActual.shs(0).nombreHS <> "" Then frmParametros_Inits.cbx1.Visible = True For i As Integer = 0 To tourActual.shs.Count - 1 frmParametros_Inits.cbx1.Items.Add(tourActual.shs(i).nombreHS) Next i frmParametros_Inits.lb1.Text cambiar su = "Punto caliente estático a modo de visualización" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Else MsgBox("No existe ningún punto caliente estático", MsgBoxStyle.Exclamation, "Advertencia") End If Case 22 If tourActual.fotosEsfericas(numeroFE).rois.Count <> 1 And tourActual.fotosEsfericas(numeroFE).rois(0).nombreRoi <> "" Then frmParametros_Inits.cbx1.Visible = True For i As Integer = 0 To tourActual.fotosEsfericas(numeroFE).rois.Count - 1 frmParametros_Inits.cbx1.Items.Add(tourActual.fotosEsfericas(numeroFE).rois(i).nomb reRoi) Next i frmParametros_Inits.lb1.Text = "Imagen de alta resolución a insertar" frmParametros_Inits.ShowDialog() Pág. 88 Anexos frmParametros_Inits.Dispose() Else MsgBox("No existe ninguna imagen de alta resolución en la foto esférica actual", MsgBoxStyle.Exclamation, "Advertencia") End If Case 23 If tourActual.fotosEsfericas(numeroFE).rois.Count <> 1 And tourActual.fotosEsfericas(numeroFE).rois(0).nombreRoi <> "" Then frmParametros_Inits.cbx1.Visible = True frmParametros_Inits.cbx2.Visible = True For i As Integer = 0 To tourActual.fotosEsfericas(numeroFE).rois.Count - 1 frmParametros_Inits.cbx1.Items.Add(tourActual.fotosEsfericas(numeroFE).rois(i).nomb reRoi) frmParametros_Inits.cbx2.Items.Add(tourActual.fotosEsfericas(numeroFE).rois(i).nomb reRoi) Next i frmParametros_Inits.lb1.Text = "Primera imagen de alta = "Última imagen de alta resolución a insertar" frmParametros_Inits.lb2.Text resolución a insertar" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Else MsgBox("No existe MsgBoxStyle.Exclamation, "Advertencia") End If ningún punto caliente estático", Diseño de aplicación para la generación de tours virtuales Pág. 89 Case 24 frmParametros_Inits.num1.Visible = True frmParametros_Inits.lb1.Visible = True frmParametros_Inits.lb1.Text = "Calidad" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Case 28 frmParametros_Inits.txtParametro.Visible = True frmParametros_Inits.lb1.Visible = True frmParametros_Inits.lb1.Text = "Página web que se quiere abrir" frmParametros_Inits.ShowDialog() frmParametros_Inits.Dispose() Case Else panoTmp.inits.numComando = cboxInits.SelectedIndex End Select End Sub Private Sub dgrdPuntos_Calientes_CellContentClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgrdPuntos_Calientes.CellContentClick End Sub Private Sub Label39_Click(ByVal sender As System.Object, ByVal e As sender As System.Object, ByVal e As System.EventArgs) Handles Label39.Click End Sub Private Sub Label38_Click(ByVal System.EventArgs) Handles Label38.Click End Sub Pág. 90 Private Anexos Sub Label37_Click(ByVal sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As System.EventArgs) Handles Label37.Click End Sub Private Sub Label36_Click(ByVal System.EventArgs) Handles Label36.Click End Sub Private Sub Label35_Click(ByVal System.EventArgs) Handles Label35.Click End Sub Private Sub Label34_Click(ByVal System.EventArgs) Handles Label34.Click End Sub Private Sub Label33_Click(ByVal System.EventArgs) Handles Label33.Click End Sub Private Sub Label32_Click(ByVal System.EventArgs) Handles Label32.Click End Sub Private Sub Label31_Click(ByVal System.EventArgs) Handles Label31.Click End Sub Private Sub Label40_Click(ByVal System.EventArgs) Handles Label40.Click End Sub Private Sub Label30_Click(ByVal System.EventArgs) Handles Label30.Click End Sub Diseño de aplicación para la generación de tours virtuales Private Sub Label29_Click(ByVal Pág. 91 sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As sender As System.Object, ByVal e As System.EventArgs) Handles Label29.Click End Sub Private Sub Label28_Click(ByVal System.EventArgs) Handles Label28.Click End Sub Private Sub Label27_Click(ByVal System.EventArgs) Handles Label27.Click End Sub Private Sub Label26_Click(ByVal System.EventArgs) Handles Label26.Click End Sub Private Sub Label25_Click(ByVal System.EventArgs) Handles Label25.Click End Sub Private Sub Label24_Click(ByVal System.EventArgs) Handles Label24.Click End Sub Private Sub Label23_Click(ByVal System.EventArgs) Handles Label23.Click End Sub Private Sub cbxSin_limites_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbxSin_limites.CheckedChanged End Sub End Class Pág. 92 Anexos B.4 Pantalla Puntos_Calientes_Estaticos Public Class frmPuntos_Calientes_estáticos Private Sub frmPuntos_Calientes_estáticos_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load If tourActual.shs(0).nombreHS <> "" Then For j As Integer = 0 To tourActual.shs.Count - 1 dgrdPuntos_Calientes_Estaticos.Rows.Add() dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(0).Value = tourActual.shs(j).nombreHS dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(1).Value = tourActual.shs(j).xnumber dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(2).Value = tourActual.shs(j).anumber dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(3).Value = tourActual.shs(j).ynumber dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(4).Value = tourActual.shs(j).bnumber If tourActual.shs(0).nombreHS <> "" Then For i As Integer = 0 To tourActual.fotosEsfericas(numeroFE).hs.Count - 1 Dim textoTmp As String = "" dgrdPuntos_Calientes_Estaticos.Rows.Add() dgrdPuntos_Calientes_Estaticos.Rows(i).Cells(0).Value = tourActual.shs(i).nombreHS dgrdPuntos_Calientes_Estaticos.Rows(i).Cells(1).Value = tourActual.shs(i).xnumber dgrdPuntos_Calientes_Estaticos.Rows(i).Cells(2).Value tourActual.shs(i).anumber = Diseño de aplicación para la generación de tours virtuales Pág. 93 dgrdPuntos_Calientes_Estaticos.Rows(i).Cells(3).Value = tourActual.shs(i).ynumber dgrdPuntos_Calientes_Estaticos.Rows(i).Cells(6).Value = tourActual.shs(i).bnumber dgrdPuntos_Calientes_Estaticos.Rows(i).Cells(7).Value = tourActual.shs(i).enlaceHS dgrdPuntos_Calientes_Estaticos.Rows(i).Cells(8).Value = tourActual.shs(i).siempreVisible dgrdPuntos_Calientes_Estaticos.Rows(i).Cells(9).Value = tourActual.shs(i).popupHS dgrdPuntos_Calientes_Estaticos.Rows(i).Cells(10).Value = tourActual.shs(i).accionHS.numComando For k As Integer = 0 To 10 If tourActual.shs(i).accionHS.parametros(k) = "" Then Exit For End If If k <> 0 Then textoTmp = textoTmp & "," End If textoTmp = tourActual.shs(i).accionHS.parametros(k) Next k dgrdPuntos_Calientes_Estaticos.Rows(i).Cells(11).Value textoTmp Next i End If Next j End If End Sub = Pág. 94 Anexos Private Sub btnAnadir_SHS_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnadir_SHS.Click dgrdPuntos_Calientes_Estaticos.Rows.Add() End Sub 'Guardar todos los datos de la tabla de Puntos Calientes estáticos Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAceptar.Click If dgrdPuntos_Calientes_Estaticos.Rows.Count > 0 Then ReDim tourActual.shs(dgrdPuntos_Calientes_Estaticos.Rows.Count - 1) For j As Integer = 0 To dgrdPuntos_Calientes_Estaticos.Rows.Count - 1 tourActual.shs(j) = New Hotspot() tourActual.shs(j).nombreHS = CStr(dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(0).Value) tourActual.shs(j).xnumber = CInt(dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(1).Value) tourActual.shs(j).ynumber = CInt(dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(3).Value) tourActual.shs(j).anumber = CInt(dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(2).Value) tourActual.shs(j).bnumber = CInt(dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(4).Value) tourActual.shs(j).estatico = True tourActual.shs(j).enlaceHS = CStr(dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(7).Value) tourActual.shs(j).siempreVisible = CBool(dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(8).Value) tourActual.shs(j).popupHS CBool(dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(9).Value) = Diseño de aplicación para la generación de tours virtuales Pág. 95 tourActual.shs(j).accionHS.numComando = CInt(dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(10).Value) tourActual.shs(j).accionHS.parametros = Split(CStr(dgrdPuntos_Calientes_Estaticos.Rows(j).Cells(11).Value), ",") Next j End If dgrdPuntos_Calientes_Estaticos.Rows.Clear() Me.Close() End Sub Private Sub btnCancelar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancelar.Click Me.Close() End Sub Private Sub dgrdPuntos_Calientes_Estaticos_CellClick1(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgrdPuntos_Calientes_Estaticos.CellClick If dgrdPuntos_Calientes_Estaticos.CurrentCellAddress.X = 5 Then frmOpciones_puntos_calientes_estáticos.ShowDialog() End If If dgrdPuntos_Calientes_Estaticos.CurrentCellAddress.X = 6 Then If (MsgBox("¿Estás seguro que deseas eliminar el punto caliente estático " & dgrdPuntos_Calientes_Estaticos.CurrentCellAddress.Y & "?", vbYesNo) = vbYes) Then dgrdPuntos_Calientes_Estaticos.Rows.Remove(dgrdPuntos_Calientes_Estaticos.CurrentRo w) End If End If Pág. 96 End Sub End Class Anexos Diseño de aplicación para la generación de tours virtuales Pág. 97 B.5 Pantalla Parametros.vb Public Class frmParametros Private Property dlgFile As OpenFileDialog Public txtSinExtension As String Private Sub btnExplorar_Parametro_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExplorar_Parametro.Click dlgFile = New OpenFileDialog dlgFile.Filter = "Imágenes JPG (*.jpg)|*.jpg|Mapas de bits (*.gif)|*.gif" dlgFile.Title = "Abre una imagen JPG o GIF" If dlgFile.ShowDialog() = DialogResult.OK Then txtParametro.Text = dlgFile.FileName txtSinExtension = dlgFile.SafeFileName End If End Sub Private Sub frmParametros_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim matrizTmp() As String If frmOpciones_puntos_calientes.accionTmp <> "" Then matrizTmp = Split(frmOpciones_puntos_calientes.accionTmp, ",") Select Case frmOpciones_puntos_calientes.cboxComandos.SelectedIndex Case 0 txtParametro.Text = matrizTmp(0) Case 1 txtParametro.Text = matrizTmp(0) Pág. 98 Anexos Case 8, 12 If IsNumeric(matrizTmp(0)) Then num1.Value = CInt(matrizTmp(0)) If IsNumeric(matrizTmp(1)) Then num2.Value = CInt(matrizTmp(1)) If IsNumeric(matrizTmp(2)) Then num3.Value = CInt(matrizTmp(2)) Case 14 If IsNumeric(matrizTmp(0)) Then cbx1.SelectedIndex = CInt(matrizTmp(0)) If IsNumeric(matrizTmp(1)) Then num2.Value = CInt(matrizTmp(1)) If IsNumeric(matrizTmp(2)) Then num3.Value = CInt(matrizTmp(2)) If IsNumeric(matrizTmp(3)) Then num4.Value = CInt(matrizTmp(3)) Case 15 If IsNumeric(matrizTmp(0)) Then num1.Value = CInt(matrizTmp(0)) If IsNumeric(matrizTmp(1)) Then num2.Value = CInt(matrizTmp(1)) If IsNumeric(matrizTmp(2)) Then num3.Value = CInt(matrizTmp(2)) If IsNumeric(matrizTmp(3)) Then num4.Value = CInt(matrizTmp(3)) If IsNumeric(matrizTmp(4)) Then num5.Value = CInt(matrizTmp(4)) If IsNumeric(matrizTmp(5)) Then num6.Value = CInt(matrizTmp(5)) If IsNumeric(matrizTmp(6)) Then num7.Value = CInt(matrizTmp(6)) If IsNumeric(matrizTmp(7)) Then num8.Value = CInt(matrizTmp(7)) Case 16 If IsNumeric(matrizTmp(0)) Then num1.Value = CInt(matrizTmp(0)) If IsNumeric(matrizTmp(1)) Then num2.Value = CInt(matrizTmp(1)) If IsNumeric(matrizTmp(2)) Then num3.Value = CInt(matrizTmp(2)) If IsNumeric(matrizTmp(3)) Then num4.Value = CInt(matrizTmp(3)) If IsNumeric(matrizTmp(4)) Then num5.Value = CInt(matrizTmp(4)) Diseño de aplicación para la generación de tours virtuales Pág. 99 Case 17 If IsNumeric(matrizTmp(0)) Then cbx1.SelectedIndex = IsNumeric(matrizTmp(0)) Then cbx1.SelectedIndex = IsNumeric(matrizTmp(0)) Then cbx1.SelectedIndex = IsNumeric(matrizTmp(0)) Then cbx1.SelectedIndex = IsNumeric(matrizTmp(0)) Then cbx1.SelectedIndex = If IsNumeric(matrizTmp(0)) Then cbx1.SelectedIndex = If IsNumeric(matrizTmp(1)) Then cbx2.SelectedIndex = CInt(matrizTmp(0)) Case 18 If CInt(matrizTmp(0)) Case 19 If CInt(matrizTmp(0)) Case 20 If CInt(matrizTmp(0)) Case 24 If CInt(matrizTmp(0)) Case 25 CInt(matrizTmp(0)) CInt(matrizTmp(1)) Case 26 If IsNumeric(matrizTmp(0)) Then num1.Value = CInt(matrizTmp(0)) End Select End If End Sub Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal System.EventArgs) Handles btnAceptar.Click Select Case frmOpciones_puntos_calientes.cboxComandos.SelectedIndex e As Pág. 100 Anexos Case 0 frmOpciones_puntos_calientes.accionTmp = txtParametro.Text Case 1 frmOpciones_puntos_calientes.accionTmp = txtParametro.Text Case 8 frmOpciones_puntos_calientes.accionTmp = num1.Value & "," & = num1.Value & "," & num2.Value & "," & num3.Value Case 12 frmOpciones_puntos_calientes.accionTmp num2.Value & "," & num3.Value Case 14 frmOpciones_puntos_calientes.accionTmp = cbx1.SelectedIndex & "," & num2.Value & "," & num3.Value & ", " & num4.Value Case 15 frmOpciones_puntos_calientes.accionTmp = num1.Value & "," & num2.Value & "," & num3.Value & " , " & num4.Value & " , " & num5.Value & " , " & num6.Value & " , " & num7.Value & " , " & num8.Value Case 16 frmOpciones_puntos_calientes.accionTmp = num1.Value & "," num2.Value & "," & num3.Value & ", " & num4.Value & " , " & num5.Value Case 17 frmOpciones_puntos_calientes.accionTmp = CStr(cbx1.SelectedIndex) Case 18 frmOpciones_puntos_calientes.accionTmp = CStr(cbx1.SelectedIndex) Case 19 frmOpciones_puntos_calientes.accionTmp = CStr(cbx1.SelectedIndex) Case 20 & Diseño de aplicación para la generación de tours virtuales Pág. 101 frmOpciones_puntos_calientes.accionTmp = CStr(cbx1.SelectedIndex) Case 24 frmOpciones_puntos_calientes.accionTmp = CStr(cbx1.SelectedIndex) Case 25 frmOpciones_puntos_calientes.accionTmp = CStr(cbx1.SelectedIndex) & ", " & CStr(cbx2.SelectedIndex) Case 26 frmOpciones_puntos_calientes.accionTmp = CStr(num1.Value) End Select Me.Close() End Sub Private Sub btnCancelar_Click(ByVal sender System.EventArgs) Handles btnCancelar.Click txtParametro.Visible = False btnExplorar_Parametro.Visible = False num1.Visible = False num2.Visible = False num3.Visible = False num4.Visible = False num5.Visible = False num6.Visible = False num7.Visible = False num8.Visible = False lb1.Visible = False lb2.Visible = False As System.Object, ByVal e As Pág. 102 Anexos lb3.Visible = False lb4.Visible = False lb5.Visible = False lb6.Visible = False lb7.Visible = False lb8.Visible = False cbx1.Visible = False cbx2.Visible = False Me.Close() End Sub End Class Diseño de aplicación para la generación de tours virtuales Pág. 103 B.6 Pantalla Opciones_Puntos_Calientes_Estaticos Public Class frmOpciones_puntos_calientes_estáticos Public enlacetmp As String Public imagenSHS As String Public siempreVisible As Boolean Public popUp As Boolean Public acciontmp As String Private Property dlgFile As OpenFileDialog 'Al presionar el botón cancelar, ni se guarda nada y se cierra la ventana Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancelar.Click Me.Close() End Sub 'Al presionar Aceptar, además de guardar todos los datos se cierra la ventana Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAceptar.Click frmPuntos_Calientes_estáticos.dgrdPuntos_Calientes_Estaticos.CurrentRow.Cells(7).Va lue = txtVinculo.Text frmPuntos_Calientes_estáticos.dgrdPuntos_Calientes_Estaticos.CurrentRow.Cells(8).Va lue = cbxSiempre_Visible.Checked frmPuntos_Calientes_estáticos.dgrdPuntos_Calientes_Estaticos.CurrentRow.Cells(9).Va lue = cbxPop_Up.Checked frmPuntos_Calientes_estáticos.dgrdPuntos_Calientes_Estaticos.CurrentRow.Cells(10).V alue = cboxComandos.SelectedIndex Pág. 104 Anexos frmPuntos_Calientes_estáticos.dgrdPuntos_Calientes_Estaticos.CurrentRow.Cells(11).V alue = acciontmp Me.Close() End Sub Private Sub frmOpciones_puntos_calientes_estáticos_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load txtVinculo.Text = CStr(frmPuntos_Calientes_estáticos.dgrdPuntos_Calientes_Estaticos.CurrentRow.Cells( 7).Value) cbxSiempre_Visible.Checked = CBool(frmPuntos_Calientes_estáticos.dgrdPuntos_Calientes_Estaticos.CurrentRow.Cells (8).Value) cbxPop_Up.Checked = CBool(frmPuntos_Calientes_estáticos.dgrdPuntos_Calientes_Estaticos.CurrentRow.Cells (9).Value) If Not frmPuntos_Calientes_estáticos.dgrdPuntos_Calientes_Estaticos.CurrentRow.Cells(10).V alue Is Nothing Then cboxComandos.SelectedIndex = CInt(frmPuntos_Calientes_estáticos.dgrdPuntos_Calientes_Estaticos.CurrentRow.Cells( 10).Value) End If End Sub Private Sub cboxComandos_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboxComandos.SelectedIndexChanged Select Case cboxComandos.SelectedIndex Case 0 frmParametros_SHS.txtParametro.Visible = True frmParametros_SHS.btnExplorar_Parametro.Visible = True Diseño de aplicación para la generación de tours virtuales Pág. 105 frmParametros_SHS.lb1.Visible = True frmParametros_SHS.lb1.Text = "Imagen del punto caliente estático" frmParametros_SHS.ShowDialog() Case 7 frmParametros_SHS.num1.Visible = True frmParametros_SHS.lb1.Visible = True frmParametros_SHS.lb1.Text = "Ángulo horizontal" frmParametros_SHS.num2.Visible = True frmParametros_SHS.lb2.Visible = True frmParametros_SHS.lb2.Text = "Ángulo vertical" frmParametros_SHS.num3.Visible = True frmParametros_SHS.lb3.Visible = True frmParametros_SHS.lb3.Text = "Campo de visión" frmParametros_SHS.num1.Maximum = 360 frmParametros_SHS.num1.Minimum = 0 frmParametros_SHS.num2.Maximum = 90 frmParametros_SHS.num2.Minimum = -90 frmParametros_SHS.num3.Maximum = 165 frmParametros_SHS.num3.Minimum = 0 frmParametros_SHS.ShowDialog() Case 11 frmParametros_SHS.num1.Visible = True frmParametros_SHS.lb1.Visible = True frmParametros_SHS.lb1.Text = "Incremento de ángulo horizontal" Pág. 106 Anexos frmParametros_SHS.num2.Visible = True frmParametros_SHS.lb2.Visible = True frmParametros_SHS.lb2.Text = "Incremento de ángulo vertical" frmParametros_SHS.num3.Visible = True frmParametros_SHS.lb3.Visible = True frmParametros_SHS.lb3.Text = "Tiempo de autorotación" frmParametros_SHS.num1.Maximum = 360 frmParametros_SHS.num1.Minimum = 0 frmParametros_SHS.num2.Maximum = 90 frmParametros_SHS.num2.Minimum = 0 frmParametros_SHS.num3.Maximum = 600 frmParametros_SHS.num3.Minimum = 0 frmParametros_SHS.ShowDialog() Case 13 frmParametros_SHS.cbx1.Visible = True frmParametros_SHS.lb1.Visible = True frmParametros_SHS.lb1.Text = "Panorámica a cargar" frmParametros_SHS.cbx1.Visible = True For i As Integer = 0 To tourActual.fotosEsfericas.Count - 1 frmParametros_SHS.cbx1.Items.Add(tourActual.fotosEsfericas(i).nombreFile) Next i frmParametros_SHS.num2.Visible = True frmParametros_SHS.lb2.Visible = True frmParametros_SHS.lb2.Text = "Ángulo horizontal" Diseño de aplicación para la generación de tours virtuales frmParametros_SHS.num3.Visible = True frmParametros_SHS.lb3.Visible = True frmParametros_SHS.lb3.Text = "Ángulo vertical" frmParametros_SHS.num4.Visible = True frmParametros_SHS.lb4.Visible = True frmParametros_SHS.lb4.Text = "Campo de visión" frmParametros_SHS.num2.Maximum = 360 frmParametros_SHS.num2.Minimum = 0 frmParametros_SHS.num3.Maximum = 90 frmParametros_SHS.num3.Minimum = -90 frmParametros_SHS.num4.Maximum = 165 frmParametros_SHS.num4.Minimum = 0 frmParametros_SHS.ShowDialog() Case 14 frmParametros_SHS.num1.Visible = True frmParametros_SHS.lb1.Visible = True frmParametros_SHS.lb1.Text = "Ángulo horizontal de inicio" frmParametros_SHS.num2.Visible = True frmParametros_SHS.lb2.Visible = True frmParametros_SHS.lb2.Text = "Ángulo horizontal de fin" frmParametros_SHS.num3.Visible = True frmParametros_SHS.lb3.Visible = True frmParametros_SHS.lb3.Text = "Ángulo vertical de inicio" frmParametros_SHS.num4.Visible = True Pág. 107 Pág. 108 Anexos frmParametros_SHS.lb4.Visible = True frmParametros_SHS.lb4.Text = "Ángulo vertical de fin" frmParametros_SHS.num5.Visible = True frmParametros_SHS.lb5.Visible = True frmParametros_SHS.lb5.Text = "Campo de visión de inicio" frmParametros_SHS.num6.Visible = True frmParametros_SHS.lb6.Visible = True frmParametros_SHS.lb6.Text = "Campo de visión de fin" frmParametros_SHS.num7.Visible = True frmParametros_SHS.lb7.Visible = True frmParametros_SHS.lb7.Text = "Número de ""frames"" " frmParametros_SHS.num8.Visible = True frmParametros_SHS.lb8.Visible = True frmParametros_SHS.lb8.Text = "Tiempo del movimiento" frmParametros_SHS.num1.Maximum = 360 frmParametros_SHS.num1.Minimum = 0 frmParametros_SHS.num2.Maximum = 360 frmParametros_SHS.num2.Minimum = 0 frmParametros_SHS.num3.Maximum = 90 frmParametros_SHS.num3.Minimum = -90 frmParametros_SHS.num4.Maximum = 90 frmParametros_SHS.num4.Minimum = -90 frmParametros_SHS.num5.Maximum = 165 frmParametros_SHS.num5.Minimum = 0 Diseño de aplicación para la generación de tours virtuales frmParametros_SHS.num6.Maximum = 165 frmParametros_SHS.num6.Minimum = 0 frmParametros_SHS.num7.Maximum = 50 frmParametros_SHS.num7.Minimum = 1 frmParametros_SHS.num8.Maximum = 600 frmParametros_SHS.num8.Minimum = 1 frmParametros_SHS.ShowDialog() Case 15 frmParametros_SHS.num1.Visible = True frmParametros_SHS.lb1.Visible = True frmParametros_SHS.lb1.Text = "Ángulo horizontal" frmParametros_SHS.num2.Visible = True frmParametros_SHS.lb2.Visible = True frmParametros_SHS.lb2.Text = "Ángulo vertical" frmParametros_SHS.num3.Visible = True frmParametros_SHS.lb3.Visible = True frmParametros_SHS.lb3.Text = "Campo de visión" frmParametros_SHS.num4.Visible = True frmParametros_SHS.lb4.Visible = True frmParametros_SHS.lb4.Text = "Número de ""frames""" frmParametros_SHS.num5.Visible = True frmParametros_SHS.lb5.Visible = True frmParametros_SHS.lb5.Text = "Tiempo del movimiento" frmParametros_SHS.num1.Maximum = 360 Pág. 109 Pág. 110 Anexos frmParametros_SHS.num1.Minimum = 0 frmParametros_SHS.num2.Maximum = 90 frmParametros_SHS.num2.Minimum = -90 frmParametros_SHS.num3.Maximum = 165 frmParametros_SHS.num3.Minimum = 0 frmParametros_SHS.num4.Maximum = 50 frmParametros_SHS.num4.Minimum = 1 frmParametros_SHS.num5.Maximum = 600 frmParametros_SHS.num5.Minimum = 1 frmParametros_SHS.ShowDialog() Case 16 frmParametros_SHS.cbx1.Visible = True For i As Integer = 0 To tourActual.infoSonidos.Count - 1 frmParametros_SHS.cbx1.Items.Add(tourActual.infoSonidos(i).nombreSonido) Next i frmParametros_SHS.lb1.Visible = True frmParametros_SHS.lb1.Text = "Sonido a emitir" frmParametros_SHS.ShowDialog() Case 17 If tourActual.shs.Count <> 1 And tourActual.shs(0).nombreHS <> "" Then frmParametros_SHS.cbx1.Visible = True For i As Integer = 0 To tourActual.shs.Count - 1 frmParametros_SHS.cbx1.Items.Add(tourActual.shs(i).nombreHS) Diseño de aplicación para la generación de tours virtuales Pág. 111 Next i frmParametros_SHS.lb1.Text = "Punto caliente estático a mostrar" frmParametros_SHS.ShowDialog() Else MsgBox("No existe ningún punto caliente estático", MsgBoxStyle.Exclamation, "Advertencia") End If Case 18 If tourActual.shs.Count <> 1 And tourActual.shs(0).nombreHS <> "" Then frmParametros_SHS.cbx1.Visible = True For i As Integer = 0 To tourActual.shs.Count - 1 frmParametros_SHS.cbx1.Items.Add(tourActual.shs(i).nombreHS) Next i frmParametros_SHS.lb1.Text = "Punto caliente estático a esconder" frmParametros_SHS.ShowDialog() Else MsgBox("No existe ningún punto caliente estático", MsgBoxStyle.Exclamation, "Advertencia") End If Case 19 If tourActual.shs.Count <> 1 And tourActual.shs(0).nombreHS <> "" Then frmParametros_SHS.cbx1.Visible = True For i As Integer = 0 To tourActual.shs.Count - 1 Pág. 112 Anexos frmParametros_SHS.cbx1.Items.Add(tourActual.shs(i).nombreHS) Next i frmParametros_SHS.lb1.Text = "Punto caliente estático a cambiar su modo de visualización" frmParametros_SHS.ShowDialog() Else MsgBox("No existe ningún punto caliente estático", MsgBoxStyle.Exclamation, "Advertencia") End If Case 23 If tourActual.fotosEsfericas(numeroFE).rois.Count <> 1 And tourActual.fotosEsfericas(numeroFE).rois(0).nombreRoi <> "" Then frmParametros_SHS.cbx1.Visible = True For i As Integer = 0 To tourActual.fotosEsfericas(numeroFE).rois.Count - 1 frmParametros_SHS.cbx1.Items.Add(tourActual.fotosEsfericas(numeroFE).rois(i).nombre Roi) Next i frmParametros_SHS.lb1.Text = "Imagen de alta resolución a insertar" frmParametros_SHS.ShowDialog() Else MsgBox("No existe ninguna imagen de alta resolución en la foto esférica actual", MsgBoxStyle.Exclamation, "Advertencia") End If Case 24 If tourActual.fotosEsfericas(numeroFE).rois.Count <> 1 And Diseño de aplicación para la generación de tours virtuales Pág. 113 tourActual.fotosEsfericas(numeroFE).rois(0).nombreRoi <> "" Then frmParametros_SHS.cbx1.Visible = True frmParametros_SHS.cbx2.Visible = True For i As Integer = 0 To tourActual.fotosEsfericas(numeroFE).rois.Count - 1 frmParametros_SHS.cbx1.Items.Add(tourActual.fotosEsfericas(numeroFE).rois(i).nombre Roi) frmParametros_SHS.cbx2.Items.Add(tourActual.fotosEsfericas(numeroFE).rois(i).nombre Roi) Next i frmParametros_SHS.lb1.Text = "Primera imagen de alta resolución a insertar" frmParametros_SHS.lb2.Text = "Última imagen de alta resolución a insertar" frmParametros_SHS.ShowDialog() Else MsgBox("No existe ningún punto MsgBoxStyle.Exclamation, "Advertencia") End If Case 25 frmParametros_SHS.num1.Visible = True frmParametros_SHS.lb1.Visible = True frmParametros_SHS.lb1.Text = "Calidad" frmParametros_SHS.num1.Maximum = 6 frmParametros_SHS.num2.Minimum = 1 frmParametros_SHS.ShowDialog() caliente estático", Pág. 114 Anexos Case Else End Select End Sub End Class