Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura 1 Cargar archivo de datos terrestres Vamos a comenzar leyendo un archivo de puntos de datos Terrestre con las coordenadas xyz de los mismos. Utilizaremos algo de lo usado en el ejercicio 9 de la parte de introducción para permitir leer un archivo de puntos y mostrar las coordenadas en una tabla, en este caso los archivos que vamos a leer utilizan como separador el tabulador. Después probaremos a representar los puntos leídos ayudándonos de un componente de evaluación. Comenzamos un proyecto nuevo que se llamará “LeerFicherosTerrestre”. Vamos a intentar leer ficheros de puntos en coordenadas X Y Z, separados por “tabulador”. Y vamos a representar esos puntos. Creamos el menú con el control MenuStrip en el grupo Menús y Barras de Herramientas. El formulario presentará el aspecto: Las etiquetas que vemos, un cuadro de texto con nombre “txt_ruta” para ver la ruta del archivo leído, un cuadro de texto “txt_leidos” en el que mostraremos el número de puntos que se lean, un cuadro de texto “txt_visor” en el que pondremos la propiedad Multiline a True, para mostrar las líneas que vamos leyendo del fichero y un DataGridView que encontramos en la categoría de Datos y llamamos “dgv_tabla”. Al insertar la tabla le agregamos tres columnas con los nombres de las coordenadas de los puntos X, Y, Z. Escuela Politécnica Superior de Ávila Universidad de Salamanca 1 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Para el acceso al sistema de archivos utilizaremos el diálogo OpenFileDialog del grupo de controles Diálogos. Comenzamos con la opción la operación de leer que asociaremos al menú Archivo/Abrir. Para el utilizar las clases relacionadas con la entrada y salida, importamos el espacio de nombres Imports System.IO al comienzo del código. Escribimos el código siguiente: Private Sub AbrirToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AbrirToolStripMenuItem.Click OpenFileDialog1.Filter = "Archivos Ascii(*.asc)|*.asc|Archivos de Texto(*.txt)|*.txt|Todos los Archivos|*.*" 'Le indicamos los filtros que aparecerán al seleccionar los archivos. asc, txt, o todos. OpenFileDialog1.ShowDialog() 'Mostramos diálogo de Abrir txt_ruta.Text = OpenFileDialog1.FileName 'Colocamos en el cuadro de texto la ruta y nombre del fichero seleccionado Dim leer As New StreamReader(New FileStream(OpenFileDialog1.FileName, FileMode.Open)) 'Creamos la variable de tipo StreamReader que nos permitirá manejar el fichero 'la variable se crea a partir otra de tipo FileStream asociada al archivo seleccionado y 'Abiendo el archivo Dim linea As String txt_visor.Clear() 'Borramos el cuadro que visionará las lineas leídas dgv_tabla.Rows.Clear() 'Borramos la tabla que muestra las coordenadas de los puntos Dim punto(2) As String 'Vector de tres cadenas para guardar la X,Y,Z de cada punto Do linea = leer.ReadLine 'Leemos una linea del fichero If Not linea Is Nothing Then 'Si la linea no está vacia punto = Split(linea, vbTab, 3) 'Separamos con la función Split la linea por la posición del separador "tabulador" 'Limitamos el número de trozos a 3 para no desbordar el vector If punto.Length = 3 Then 'Si no hay tres coordenadas descartamos el dato dgv_tabla.Rows.Add(punto(0), punto(1), punto(2)) 'Añado las coordenadas del punto a la tabla End If txt_visor.AppendText(linea & vbCrLf) 'Añado la linea leída al visor. vbCrLf es un salto de linea End If Loop Until linea Is Nothing 'Repetimos hasta que linea sea vacia que se habrá terminado el fichero leer.Close() 'Cerramos el fichero leer = Nothing txt_leidos.Text = dgv_tabla.Rows.Count - 1 'Pongo en txt_leidos el numero de puntos añadidos a la tabla. End Sub Escuela Politécnica Superior de Ávila Universidad de Salamanca 2 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Se puede entender el código a partir de los comentarios. Se podría realizar un control más preciso de errores para contemplar casos en que los archivos proporcionados no se ajusten al formato previsto. Pero como comienzo lo dejamos así. Intentamos probar el código que hemos escrito hasta el momento. Abrimos el fichero “CuatroPostesmini.asc” que se proporciona como ejemplo, tiene 16650 puntos. Luego probamos con el completo. Guardamos el proyecto y lo cerramos. Escuela Politécnica Superior de Ávila Universidad de Salamanca 3 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura 2 Convertir los puntos a DXF. Cuando realicemos algunas operaciones sobre los puntos y queramos utilizarlos en alguno de los programas habituales de diseño gráfico, necesitaremos tenerlos en algún formato estándar. El formato DXF nos lo reconocerá la mayoría de los programas. Podríamos utilizar algún componente existente para la conversión a DXF, pero algunos no son gratuitos. Otros no están disponibles para Visual .Net. Además así lo conocemos y podemos añadir esa funcionalidad a nuestras aplicaciones. Vamos a intentar entender la estructura de un archivo DXF, y vamos a programar una aplicación sencilla para realizar la conversión sólo de puntos. Después en otro ejercicio posterior, crearemos una biblioteca de clases para dejar preparada la conversión a DXF para otras aplicaciones futuras. 2.1 ESTRUCTURA DE UN ARCHIVO DXF. DXF viene de Drawing eXchange Format, es un archivo de intercambio de dibujos de CAD. Los archivos DXF son archivos ASCII. También hay DXF binarios pero con el tiempo los ASCII han ganado protagonismo y si no se indica lo contrario cuando nos hablan de DXF se refieren a estos. Los archivos DXF se componen de pares de códigos y valores asociados. Los códigos, se llaman códigos de grupo e indican el tipo de valor que les sigue. Los archivos DXF se organizan en secciones, que constan de registros a su vez compuestos o por un código de grupo o un elemento de datos: cada código de grupo y su valor cuentan con su propia línea en el archivo DXF. Cada sección comienza con un código de grupo 0 seguido por la cadena SECTION. A continuación aparece un código de grupo 2 y una cadena que indica el nombre de la sección (por ejemplo, HEADER). Las secciones terminan con un 0 seguido de la cadena ENDSEC. Las principales secciones de un archivo DXF y su orden son: SECCIÓN DESCRIPCIÓN Sección HEADER Información de carácter general sobre el dibujo. Se compone de un número de versión de base de datos de AutoCAD y de una serie de variables de sistema. Cada uno de los parámetros contiene un nombre de variable y su valor asociado. Sección CLASSES Información de las clases definidas por la aplicación, cuyas apariciones se contienen en las secciones BLOCKS, ENTITIES y OBJECTS de la base de datos Sección TABLES Definiciones de las siguientes tablas: APPID (tabla de identificación de las aplicaciones) BLOCK_RECORD (tabla de referencia de bloques) DIMSTYLE (tabla de estilos de acotación) LAYER (tabla de capas) LTYPE (tabla de tipos de línea) STYLE (tabla de estilos de texto) UCS (tabla del Sistema de coordenadas personales) VIEW (tabla de visualización) VPORT (tabla de configuración de la ventana gráf.) Sección BLOCKS Definiciones de bloques Sección ENTITIES Contiene los objetos gráficos (entidades) del dibujo, incluidas las referencias a bloques (entidades insertadas). Sección OBJECTS Los objetos no gráficos del dibujo. En esta sección es donde se almacenan todos los objetos que no sean entidades ni registros de la tabla de símbolos. Escuela Politécnica Superior de Ávila Universidad de Salamanca 4 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Los códigos de grupo definen el tipo de valor asociado como un número entero, un número de coma flotante o una cadena, según la siguiente tabla de rangos de código de grupo. RANGO DE CÓDIGO 0-9 10 - 59 60 - 79 90-99 100 y 102 105 140 - 147 170 - 175 280 - 289 300 - 309 310-319 320-329 330-369 999 1000 - 1009 1010-1059 1060 - 1069 1071 TIPO DE VALOR DE GRUPO Cadena Punto 3D de doble precisión Valor entero de 16 bits Valor entero de 32 bits Cadena Cadena con un valor de identificador hexadecimal Valor de coma flotante escalar de doble precisión Valor entero de 16 bits Valor entero de 8 bits. Cadena de texto arbitraria Cadena que representa el valor hexadecimal de un bloque binario Cadena que representa un valor de identificador Hexadecimal Cadena que representa identificador de objeto hexadecimal Comentario Cadena Valor de coma flotante Valor entero de 16 bits Valor entero de 32 bits Hay algunos valores que por lo que se usan conviene tratar con más detalle: CÓDIGO 0 1 2 5 6 7 8 9 40-48 62 66 67 70-78 DESCRIPCIÓN Cadena de texto que indica el tipo de entidad (fijo) Valor de texto principal de una entidad identificador de atributos, nombre de bloque, etc. Identificador de entidad. Cadena de texto de hasta 16 dígitos hexadecimales (fijo) Nombre de tipo de línea (fijo) Nombre de estilo de texto (fijo) Nombre de capa (fijo) DXF: identificador de nombre de variable (sólo se utiliza en la sección HEADER (encabezamiento) del archivo DXF) Valores de coma flotante (altura de texto, factores de escala,etc.) Número de color (fijo) Indica que siguen entidades. Caso de entidades complejas Espacio (modelo o papel). Valores enteros, como número de repeticiones, bits indicadores o modos. Escuela Politécnica Superior de Ávila Universidad de Salamanca 5 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Algunas entidades del formato DXF: ALGUNAS ENTIDADES POINT LINE POLYLINE 3DFACE 3DSOLID ARC CIRCLE DIMENSION ELLIPSE SOMBREADO TEXT SPLINE IMAGE SHAPE SOLID VERTEX En el archivo siguiente se aprecia un documento básico en DXF con dos entidades punto y una Línea. Usamos alguna capa sin definirla antes, de esta forma se le asigna el tipo de línea continuo y el color 7 (Blanco). Lo hacemos así por ahorrar todo el código posible. Tampoco indicamos las variables de la cabecera. Si cogemos un DXF de alguna aplicación CAD nos daríamos cuenta de la gran cantidad de variables que aparecen. Para un ejemplo sencillo prescindimos de ellas. 0 SECTION 2 ENTITIES 0 POINT 8 Puntos 10 150.000 20 125.000 30 75.000 0 POINT 8 Puntos 10 250.000 20 225.000 30 75.000 0 LINE 8 Lineas 62 5 10 100.000 20 100.000 30 100.000 11 200.000 21 200.000 31 200.000 0 ENDSEC 0 EOF COMIENZO DE SECCIÓN INDICADOR DE SECCIÓN CÓDIGO DE GRUPO INDICADOR DE QUE ES LA SECCIÓN ENTIDADES CODIGO DE COMIENZO DE ENTIDAD TIPO DE ENTIDAD PUNTO CÓDIGO QUE INDICA QUE SIGUE UNA CAPA 8 NOMBRE DE LA CAPA EN ESTE CASO PUNTOS CÓDIGO DE LA COORDENADA X VALOR DE LA X DEL PUNTO CÓDIGO DE LA Y VALOR DE LA Y DEL PUNTO CÓDIGO DE LA Z VALOR DE LA Z COMIENZO DE OTRA ENTIDAD INDICA QUE ES UN PUNTO COMO ANTES LA CAPA Y LA X, Y, Z DEL PUNTO COMIENZO DE OTRA ENTIDAD ES UNA LINEA INDICADOR DE QUE SIGUE UNA CAPA NOMBRE DE LA CAPA CODIGO PARA INDICAR UN COLOR DE ENTIDAD COLOR 5 AZUL CODIGO DE LA X DEL PUNTO INICIAL DE LA LINEA VALOR DE LA X DEL INICIO DE LINEA CÓDIGO DE LA Y VALOR DE LA Y DEL INICIO DE LINEA CÓDIGO DE LA Z VALOR DE LA z DEL INICIO CÓDIGO DE LA X DEL FIN DE LINEA VALOR DE LA X DEL FINAL CÓDIGO DE LA Y VALOR DE LA Y DEL FINAL CÓDIGO DE LA Z VALOR DE LA Z DEL FINAL DE LA LINEA PARA INDICAR QUE SIGUE UNA PALABRA A ANALIZAR FINAL DE LA SECCIÓN DE ENTIDADES QUE SIGUE UNA PALABRA FINAL DEL FICHERO Escuela Politécnica Superior de Ávila Universidad de Salamanca 6 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura 2.2 CREACIÓN DE LA APLICACIÓN. Creamos ahora el programa que leerá puntos en formato XYZ, con o sin información de color RGB. Creamos la aplicación de tipo Aplicación para Windows como en otras ocasiones y asignamos el nombre convertir_a_DXF a la misma. Sólo tendremos un formulario principal en el programa, le ponemos como nombre frm_convertir.vb. Presentará el aspecto: Como vemos hemos colocado un GroupBox con el título “Convertir a DXF” a modo de contenedor. Sobre él, dos cuadros de texto a los que llamaremos txt_Original y txt_Destino y los cuatro botones que vemos. El mensaje de aviso sobre los puntos que podemos utilizar lo hemos puesto con una etiqueta (Label). También necesitamos los cuadros de diálogo para abrir el archivo de puntos y para seleccionar el nombre y la ubicación en la que se guardará el archivo DXF generado. Agregaremos un OpenFileDialog del grupo Cuadros de diálogo, y un SaveFileDialog del mismo grupo. Al botón Archivo Original le asignamos el código: Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click OpenFileDialog1.Filter = "Archivos Ascii(*.asc)|*.asc|Archivos de Texto(*.txt)|*.txt|Archivos XYZ(*.xyz)|*.xyz|Todos los Archivos|*.*" 'Le indicamos los filtros que aparecerán al seleccionar los archivos. asc, txt, xyz o todos. OpenFileDialog1.ShowDialog() 'Mostramos diálogo de Abrir txt_Original.Text = OpenFileDialog1.FileName 'Colocamos en el cuadro de texto la ruta y nombre del fichero seleccionado End Sub Al botón Archivo Destino le asignamos el código: Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click SaveFileDialog1.Filter = "Archivo DXF(*.dxf)|*.dxf" 'Establecemos el formato de archivo de salida a *.dxf SaveFileDialog1.ShowDialog() 'Abrimos el diálogo de guardar txt_Destino.Text = SaveFileDialog1.FileName 'Ponemos en el cuadro la ruta de guardar el nombre y ruta del archivo. End Sub Escuela Politécnica Superior de Ávila Universidad de Salamanca 7 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Dejamos la parte de convertir el código para el final y colocamos el fragmento de salir: Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Me.Close() End Sub Los archivos colores en DXF siguen una distribución diferente a los RGB que nosotros leemos. Crearemos un módulo para definir en el una función que nos convierta los colores de RGB al formato compatible con DXF. Para Agregar el módulo pulsamos en el menú Proyecto/Agregar Módulo y añadimos un módulo con nombre Funciones.vb. Este módulo contiene: Module Funciones Dim ACI_RGBValues(,) As Integer = New Integer(,) {{0, 0, 0}, _ {255, 0, 0}, _ {255, 255, 0}, _ {0, 255, 0}, _ {0, 255, 255}, _ {0, 0, 255}, _ {255, 0, 255}, _ {255, 255, 255}, _ {65, 65, 65}, _ {128, 128, 128}, _ {255, 0, 0}, _ {255, 170, 170}, _ {189, 0, 0}, _ {189, 126, 126}, _ {129, 0, 0}, _ {129, 86, 86}, _ {104, 0, 0}, _ {104, 69, 69}, _ {79, 0, 0}, _ {79, 53, 53}, _ {255, 63, 0}, _ {255, 191, 170}, _ {189, 46, 0}, _ {189, 141, 126}, _ {129, 31, 0}, _ {129, 96, 86}, _ {104, 25, 0}, _ {104, 78, 69}, _ {79, 19, 0}, _ {79, 59, 53}, _ {255, 127, 0}, _ {255, 212, 170}, _ {189, 94, 0}, _ {189, 157, 126}, _ {129, 64, 0}, _ {129, 107, 86}, _ {104, 52, 0}, _ {104, 86, 69}, _ {79, 39, 0}, _ {79, 66, 53}, _ {255, 191, 0}, _ {255, 234, 170}, _ {189, 141, 0}, _ {189, 173, 126}, _ {129, 96, 0}, _ {129, 118, 86}, _ {104, 78, 0}, _ {104, 95, 69}, _ {79, 59, 0}, _ {79, 73, 53}, _ {255, 255, 0}, _ {255, 255, 170}, _ {189, 189, 0}, _ {189, 189, 126}, _ {129, 129, 0}, _ {129, 129, 86}, _ Escuela Politécnica Superior de Ávila Universidad de Salamanca {104, 104, 0}, _ {104, 104, 69}, _ {79, 79, 0}, _ {79, 79, 53}, _ {191, 255, 0}, _ {234, 255, 170}, _ {141, 189, 0}, _ {173, 189, 126}, _ {96, 129, 0}, _ {118, 129, 86}, _ {78, 104, 0}, _ {95, 104, 69}, _ {59, 79, 0}, _ {73, 79, 53}, _ {127, 255, 0}, _ {212, 255, 170}, _ {94, 189, 0}, _ {157, 189, 126}, _ {64, 129, 0}, _ {107, 129, 86}, _ {52, 104, 0}, _ {86, 104, 69}, _ {39, 79, 0}, _ {66, 79, 53}, _ {63, 255, 0}, _ {191, 255, 170}, _ {46, 189, 0}, _ {141, 189, 126}, _ {31, 129, 0}, _ {96, 129, 86}, _ {25, 104, 0}, _ {78, 104, 69}, _ {19, 79, 0}, _ {59, 79, 53}, _ {0, 255, 0}, _ {170, 255, 170}, _ {0, 189, 0}, _ {126, 189, 126}, _ {0, 129, 0}, _ {86, 129, 86}, _ {0, 104, 0}, _ {69, 104, 69}, _ {0, 79, 0}, _ {53, 79, 53}, _ {0, 255, 63}, _ {170, 255, 191}, _ {0, 189, 46}, _ {126, 189, 141}, _ {0, 129, 31}, _ {86, 129, 96}, _ {0, 104, 25}, _ {69, 104, 78}, _ {0, 79, 19}, _ {53, 79, 59}, _ {0, 255, 127}, _ {170, 255, 212}, _ {0, 189, 94}, _ {126, 189, 157}, _ 8 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura {0, 129, 64}, _ {86, 129, 107}, _ {0, 104, 52}, _ {69, 104, 86}, _ {0, 79, 39}, _ {53, 79, 66}, _ {0, 255, 191}, _ {170, 255, 234}, _ {0, 189, 141}, _ {126, 189, 173}, _ {0, 129, 96}, _ {86, 129, 118}, _ {0, 104, 78}, _ {69, 104, 95}, _ {0, 79, 59}, _ {53, 79, 73}, _ {0, 255, 255}, _ {170, 255, 255}, _ {0, 189, 189}, _ {126, 189, 189}, _ {0, 129, 129}, _ {86, 129, 129}, _ {0, 104, 104}, _ {69, 104, 104}, _ {0, 79, 79}, _ {53, 79, 79}, _ {0, 191, 255}, _ {170, 234, 255}, _ {0, 141, 189}, _ {126, 173, 189}, _ {0, 96, 129}, _ {86, 118, 129}, _ {0, 78, 104}, _ {69, 95, 104}, _ {0, 59, 79}, _ {53, 73, 79}, _ {0, 127, 255}, _ {170, 212, 255}, _ {0, 94, 189}, _ {126, 157, 189}, _ {0, 64, 129}, _ {86, 107, 129}, _ {0, 52, 104}, _ {69, 86, 104}, _ {0, 39, 79}, _ {53, 66, 79}, _ {0, 63, 255}, _ {170, 191, 255}, _ {0, 46, 189}, _ {126, 141, 189}, _ {0, 31, 129}, _ {86, 96, 129}, _ {0, 25, 104}, _ {69, 78, 104}, _ {0, 19, 79}, _ {53, 59, 79}, _ {0, 0, 255}, _ {170, 170, 255}, _ {0, 0, 189}, _ {126, 126, 189}, _ {0, 0, 129}, _ {86, 86, 129}, _ {0, 0, 104}, _ {69, 69, 104}, _ {0, 0, 79}, _ {53, 53, 79}, _ {63, 0, 255}, _ {191, 170, 255}, _ {46, 0, 189}, _ {141, 126, 189}, _ {31, 0, 129}, _ {96, 86, 129}, _ {25, 0, 104}, _ {78, 69, 104}, _ {19, 0, 79}, _ Escuela Politécnica Superior de Ávila Universidad de Salamanca {78, 69, 104}, _ {19, 0, 79}, _ {59, 53, 79}, _ {127, 0, 255}, _ {212, 170, 255}, _ {94, 0, 189}, _ {157, 126, 189}, _ {64, 0, 129}, _ {107, 86, 129}, _ {52, 0, 104}, _ {86, 69, 104}, _ {39, 0, 79}, _ {66, 53, 79}, _ {191, 0, 255}, _ {234, 170, 255}, _ {141, 0, 189}, _ {173, 126, 189}, _ {96, 0, 129}, _ {118, 86, 129}, _ {78, 0, 104}, _ {95, 69, 104}, _ {59, 0, 79}, _ {73, 53, 79}, _ {255, 0, 255}, _ {255, 170, 255}, _ {189, 0, 189}, _ {189, 126, 189}, _ {129, 0, 129}, _ {129, 86, 129}, _ {104, 0, 104}, _ {104, 69, 104}, _ {79, 0, 79}, _ {79, 53, 79}, _ {255, 0, 191}, _ {255, 170, 234}, _ {189, 0, 141}, _ {189, 126, 173}, _ {129, 0, 96}, _ {129, 86, 118}, _ {104, 0, 78}, _ {104, 69, 95}, _ {79, 0, 59}, _ {79, 53, 73}, _ {255, 0, 127}, _ {255, 170, 212}, _ {189, 0, 94}, _ {189, 126, 157}, _ {129, 0, 64}, _ {129, 86, 107}, _ {104, 0, 52}, _ {104, 69, 86}, _ {79, 0, 39}, _ {79, 53, 66}, _ {255, 0, 63}, _ {255, 170, 191}, _ {189, 0, 46}, _ {189, 126, 141}, _ {129, 0, 31}, _ {129, 86, 96}, _ {104, 0, 25}, _ {104, 69, 78}, _ {79, 0, 19}, _ {79, 53, 59}, _ {51, 51, 51}, _ {80, 80, 80}, _ {105, 105, 105}, _ {130, 130, 130}, _ {190, 190, 190}, _ {255, 255, 255}} 'Vector con los colores en DXF 9 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura 'Función que recibe los colores en RGB y devuelve el equivalente en DXF considerando el más cercano Function ACI_Cercano_RGB(ByVal r As Integer, ByVal g As Integer, ByVal b As Integer) As Integer Dim i As Integer Dim Varianza, menorVarianza As Single menorVarianza = 3 For i = 0 To 255 Varianza = Math.Abs(ACI_RGBValues(i, 0) - r) / 255 _ + Math.Abs(ACI_RGBValues(i, 1) - g) / 255 _ + Math.Abs(ACI_RGBValues(i, 2) - b) / 255 If Varianza < menorVarianza Then menorVarianza = Varianza ACI_Cercano_RGB = i End If Next End Function End Module Queda un listado muy largo. Son los componentes RGB de los colores con número que se usan en DXF. LA función devolverá el más aproximado al número de color en DXF. En DXF le indicamos el color con el código 62 y en la línea siguiente el número. En las versiones nuevas nos reconoce el color en color verdadero. Se indicaría con el código 420 y a continuación el valor del color. Hemos preferido mantener el color por el sistema tradicional para hacerlo más compatible con distintas aplicaciones CAD. En concreto se pondría 420 como código fr color verdadero y en la línea siguiente el número decimal correspondiente al valor hexadecimal de RRGGBB. Por ejemplo para un valor de Rojo=200, Verde=100 y Azul=50 quedaría C86432 que en decimal es 13132850. Por último al botón, Comenzar conversión le asociamos: Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.Cursor = Cursors.WaitCursor 'Para que aparezca el Reloj de Arena si tarda If txt_Original.Text.Length > 0 And txt_Destino.Text.Length > 0 Then Dim leer As New StreamReader(New FileStream(txt_Original.Text, FileMode.Open)) 'Creamos la variable de tipo StreamReader que nos permitirá manejar el fichero 'la variable se crea a partir otra de tipo FileStream asociada al archivo seleccionado y 'Abiendo el archivo Dim linea As String Dim punto(5) As String 'Vector de seis cadenas para guardar la X,Y,Z de cada punto y los colores RGB Dim escribir As New StreamWriter(New FileStream(txt_Destino.Text, FileMode.OpenOrCreate)) 'Usamos la variable de tipo StreamWriter para asociarsela al fichero que nos han indicado. 'Le ponemos que nos abra o nos cree el archivo si no existiese escribir.WriteLine("0") 'Escribimos las lineas de comienzo del DXF en el fichero de salida. escribir.WriteLine("SECTION") escribir.WriteLine("2") escribir.WriteLine("ENTITIES") Escuela Politécnica Superior de Ávila Universidad de Salamanca 10 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Do linea = leer.ReadLine 'Leemos una linea del fichero de puntos XYZ If Not linea Is Nothing Then 'Si la linea no está vacia punto = Split(linea, vbTab, 6) 'Separamos con la función Split la linea por la posición del separador "tabulador" 'Limitamos el número de trozos a 6 para no desbordar el vector If punto.Length = 6 Then 'Si hay tres coordenadas y 3 colores escribimos en el DXF el color escribir.WriteLine("0") 'Que sigue el indicador de entidad escribir.WriteLine("POINT") 'Escribimos cada punto escribir.WriteLine("8") 'Para decirle que lo siguiente es una capa escribir.WriteLine("Puntos") 'Nombre de la capa en la que va el punto. LA crea aunque no la hayamos definido previamente escribir.WriteLine("62") 'Código para decirle que lo siguiente es el color escribir.WriteLine(CStr(ACI_Cercano_RGB(CInt(punto(3)), CInt(punto(4)), CInt(punto(5))))) 'Número de color escribir.WriteLine("10") 'Código para indicar que lo que sigue es la X escribir.WriteLine(punto(0)) 'Coordenada X del punto escribir.WriteLine("20") 'Código para indicar que sigue la coordenada Y escribir.WriteLine(punto(1)) 'Valor de la coordenada Y escribir.WriteLine(30) 'Código que indica que sigue la Z escribir.WriteLine(punto(2)) 'Valor de la coordenada Z ElseIf punto.Length = 3 Then 'Si hay tres coordenadas escribimos el punto, si no descartamos el dato escribir.WriteLine("0") 'Que sigue el indicador de entidad escribir.WriteLine("POINT") 'Escribimos cada punto escribir.WriteLine("8") 'Para decirle que lo siguiente es una capa escribir.WriteLine("Puntos") 'Nombre de la capa en la que va el punto. LA crea aunque no la hayamos definido previamente escribir.WriteLine("62") 'Código para decirle que lo siguiente es el color. Si no se indica sería por capa escribir.WriteLine("4") 'Número del color en Autocad. El 4 es Cián escribir.WriteLine("10") 'Código para indicar que lo que sigue es la X escribir.WriteLine(punto(0)) 'Coordenada X del punto escribir.WriteLine("20") 'Código para Escuela Politécnica Superior de Ávila Universidad de Salamanca 11 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura escribir.WriteLine("20") 'Código para indicar que sigue la coordenada Y escribir.WriteLine(punto(1)) 'Valor de la coordenada Y escribir.WriteLine(30) 'Código que indica que sigue la Z escribir.WriteLine(punto(2)) 'Valor de la coordenada Z End If End If Loop Until linea Is Nothing 'Repetimos hasta que linea sea vacia que se habrá terminado el fichero leer.Close() 'Cerramos el fichero original leer = Nothing escribir.WriteLine("0") 'Escribimos la parte final del fichero DXF escribir.WriteLine("ENDSEC") 'Fin de sección de entidades escribir.WriteLine("0") escribir.WriteLine("EOF") 'Fin del fichero escribir.Close() 'Cerramos el fichero de destino escribir = Nothing MessageBox.Show("Conversión Finalizada", "Conversión a DXF") Else MessageBox.Show("Debe seleccionar el fichero de origen y el de destino", "Conversión a DXF") End If Me.Cursor = Cursors.Default 'Para volver al puntero del ratón normal End Sub Resaltar que la operación puede durar un tiempo si los archivos de puntos son muy grandes. Para que el usuario note que se están realizando cálculos, hemos colocado la instrucción: Me.Cursor = Cursors.WaitCursor Al comienzo del código para que salga el puntero del ratón transformado en el reloj de arena al comenzar la conversión. Y hemos puesto: Me.Cursor = Cursors.Default Al final del código para que vuelva a dejar el puntero normal. No hay que olvidar incorporar la línea: Imports System.IO Al comienzo del código para que se carguen las bibliotecas de entrada y salida necesarias para el manejo de ficheros. Probamos a convertir alguno de los archivos que se proporcionan como ejemplo, y probamos a visualizar su contenido con un editor de texto, o a importarlos a un programa CAD. Escuela Politécnica Superior de Ávila Universidad de Salamanca 12 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura 3 Triangular puntos. Se hace necesario triangular nubes de puntos para generar mallas que ayuden a la representación del Modelo Digital del Terreno. De los distintos tipos de mallas la más usada es la Triangulación de Delaunay. Utilizaremos en este ejercicio una librería ya creada para ilustrar el funcionamiento de la Triangulación de Delaunay y los diagramas de Voronoi. Después intentaremos crear nosotros una Biblioteca de Clases que se encargue de realizar el proceso para los puntos reales. 3.1 Triangulación de Delaunay. En la triangulación de Delaunay los triángulos formados son lo mas regulares posibles, la longitud de los lados de los triángulos es mínima, y la triangulación formada es única, dando lugar a la red irregular de triángulos que aparentemente ofrece una imagen mas fiel del terreno real, y que permite una interpolación coherente entre los valores de altitud de cada uno de los puntos o vértices. La triangulación de Delaunay tiene la propiedad de que la circunferencia circunscrita a cada triángulo no contiene a ningún otro punto de la triangulación. Otra propiedad es que dos puntos pi y pj pertenecientes a P forman un lado de la Triangulación de Delaunay de P, si y solamente si, existe un círculo que contiene a pi y pj en su circunferencia y no contiene en su interior ningún punto de P. Se podría definir la triangulación de Delaunay como: Sea P un conjunto de puntos en el plano y T una triangulación de P, T es una triangulación de Delaunay de P, si y solamente si, la circunferencia circunscrita de cualquier triángulo de T no contiene puntos de P. 3.2 Creación de la aplicación que ilustra el proceso. Creamos una aplicación nueva con nombre ver_triangulación. Al formulario le ponemos el nombre frm_triangulacion.vb. Colocamos un GroupBox, dos botones y un PictureBox para la zona inferior. Cambiamos el color al Picture poniéndole color blanco en la propiedad BackColor. El aspecto del Formulario será: Escuela Politécnica Superior de Ávila Universidad de Salamanca 13 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Vamos a utilizar la Librería que se proporciona como recurso. Para importarla damos al menú “Proyecto/Agregar Referencias” y en la solapa examinar seleccionamos el fichero FortuneVoronoi.dll. Ahora añadiremos los espacios de nombres que vamos a necesitar en concreto ponemos: Imports Voronoi.Data Imports Voronoi.Mathematics Imports System.Drawing Los dos primeros se corresponden con la dll proporcionada, el último es para acceder a las utilidades de dibujo. Queremos que al redimensionar el formulario se ajuste el tamaño del PictureBox1 sobre el que vamos a dibujar los puntos y las líneas. Asociamos lo siguiente a la propiedad Resize del formulario. Private Sub frm_triangulacion_Resize(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Resize PictureBox1.Width = Me.Width - 12 'Igualamos el ancho del Picture al ancho del formulario PictureBox1.Height = Me.Height - 80 'Igualamos el alto End Sub Al botón Triangulación de Delaunay le asociamos el código: Escuela Politécnica Superior de Ávila Universidad de Salamanca 14 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim puntos As New HashSet 'Creamos una variable con la coleccion de puntosDim puntos As New HashSet 'Creamos una variable con la coleccion de puntos Dim r As Random = New Random() puntos.Clear() 'borramos los puntos Dim i As Integer For i = 0 To 200 'Creamos 201 puntos aleatorios y los añadimos a la coleccion puntos.Add(New Vector(10.0 + r.NextDouble() * (Me.PictureBox1.Width - 40), 10.0 + r.NextDouble() * (Me.PictureBox1.Height - 30))) Next Dim imagen As New Bitmap(Me.PictureBox1.Width, Me.PictureBox1.Height) 'Llamamos a la funcion que nos proporciona la biblioteca que nos devuelve un Bitmap Dim g As Graphics = Graphics.FromImage(imagen) Dim graph As VoronoiGraph = Fortune.ComputeVoronoiGraph(puntos) For Each v As Vector In puntos 'Dibujamos los puntos. Como GDI+ no permite puntos hacemos un pequeño circulo g.DrawEllipse(Pens.Red, CInt(v(0)) - 1, CInt(v(1)) - 1, 2, 2) g.DrawEllipse(Pens.Black, CInt(v(0)) - 2, CInt(v(1)) 2, 4, 4) For Each borde As VoronoiEdge In graph.Edges If ((borde.LeftData(0) = v(0)) And (borde.LeftData(1) = v(1))) Then 'Dibujamos las lineas. g.DrawLine(Pens.Blue, CInt(borde.LeftData(0)), CInt(borde.LeftData(1)), CInt(borde.RightData(0)), CInt(borde.RightData(1))) End If Next Next Me.PictureBox1.Image = imagen End Sub Y al botón Diagrama de Voronoi le ponemos: Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim puntos As New HashSet 'Creamos una variable con la coleccion de puntos Dim r As Random = New Random() puntos.Clear() 'borramos los puntos Dim i As Integer For i = 0 To 200 'Creamos 201 puntos aleatorios y los añadimos a la coleccion puntos.Add(New Vector(10.0 + r.NextDouble() * (Me.PictureBox1.Width - 40), 10.0 + r.NextDouble() * (Me.PictureBox1.Height - 30))) Next Dim imagen As New Bitmap(Me.PictureBox1.Width, Me.PictureBox1.Height) 'Llamamos a la funcion que nos proporciona la biblioteca que nos devuelve un Bitmap Escuela Politécnica Superior de Ávila Universidad de Salamanca 15 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Dim g As Graphics = Graphics.FromImage(imagen) Dim graph As VoronoiGraph = Fortune.ComputeVoronoiGraph(puntos) For Each v As Vector In graph.Vertizes 'Dibujamos los puntos. Como GDI+ no permite puntos hacemos un pequeño circulo negro y abajo otro rojo g.DrawEllipse(Pens.Black, CInt(v(0)) - 2, CInt(v(1)) 2, 4, 4) g.DrawEllipse(Pens.Red, CInt(v(0)) - 1, CInt(v(1)) - 1, 2, 2) Next For Each borde As VoronoiEdge In graph.Edges Try 'Dibujamos las lineas. g.DrawLine(Pens.Brown, CInt(borde.VVertexA(0)), CInt(borde.VVertexA(1)), CInt(borde.VVertexB(0)), CInt(borde.VVertexB(1))) Catch End Try Next Me.PictureBox1.Image = imagen End Sub Al ejecutar el programa si pulsamos en el primer botón nos creará algo así Escuela Politécnica Superior de Ávila Universidad de Salamanca 16 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Y en el segundo pondrá: Guardamos el proyecto. Escuela Politécnica Superior de Ávila Universidad de Salamanca 17 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura 4 Creación de Biblioteca para manejar puntos. En la mayoría de los ejercicios anteriores no cargamos los puntos en memoria. Los leemos y los dibujamos, o los leemos y los escribimos en otro archivo, en el caso de la conversión a DXF. Cuando necesitamos trabajar con esos datos, sería conveniente crearse una estructura que los use. Vamos a crear una clase para manejar los puntos, será una versión ampliada de la de Punto3D de la introducción. Tendremos también otra para líneas. Así como una colección para guardar un conjunto de puntos y otra para un conjunto de líneas. Llamaremos a la biblioteca de clases LidarBase. Comenzamos creando la clase PuntoLidar.vb en Proyecto/Agregar elemento y elegimos clase. En esta biblioteca vamos a necesitar la referencia a System.Windows.Forms. Lo añadimos desde Proyecto/Agregar referencia. Ahora crearemos una clase con nombre PuntoLidar.vb. En ella declaramos un punto con las coordenadas XYZ y los colores. También los constructores necesarios y una función para calcular la distancia. El código de la clase punto queda: Public Class PuntoLidar Public x, y, z As Double 'Variables de la clase Punto son públicas, permitirán acceder a ellas. 'Se podrían haber creado como propiedades Public rojo, verde, azul As Byte 'Para los colores Public colorDXF As Boolean 'Para indicar si es color DXF o RGB True indica DXF y en el rojo metemos el color Sub New() 'Constructor por Defecto. Inicializa las Variables y muestra un mensaje cuando es invocado x = 0 y = 0 z = 0 rojo = 7 'Aprovechamos el rojo para asignar el color en el caso de que usemos color DXF Escuela Politécnica Superior de Ávila Universidad de Salamanca 18 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura verde = 0 azul = 0 colorDXF = True End Sub Sub New(ByVal coord_x As Double, ByVal coord_y As Double, ByVal coord_z As Double) 'Constructor de parámetros x = coord_x y = coord_y z = coord_z End Sub Sub New(ByVal p2 As PuntoLidar) 'Constructor de copia x = p2.x y = p2.y z = p2.z colorDXF = p2.colorDXF rojo = p2.rojo verde = p2.verde azul = p2.azul End Sub Function distanciaA(ByVal p2 As PuntoLidar) As Double 'Función distancia. Calcula la distancia al 'punto que nos pasan como argumento Dim distanciax, distanciay, distanciaz As Double distanciax = p2.x - x distanciay = p2.y - y distanciaz = p2.z - z distanciaA = Math.Sqrt(distanciax * distanciax + distanciay * distanciay + distanciaz * distanciaz) 'Calculamos la distancia y se la asignamos al nombre de la función. Así devolvemos el valor End Function End Class Tendremos otra clase LineaLidar.vb para almacenar una línea con una variable de tipo PuntoLidar para el punto inicial y otra del mismo tipo para el final. El código queda: Public Class LineaLidar Public inicio, final As PuntoLidar Sub New() 'Constructor por Defecto. Inicializa las Variables y muestra un mensaje cuando es invocado inicio = New PuntoLidar final = New PuntoLidar End Sub Sub New(ByVal ini As PuntoLidar, ByVal fin As PuntoLidar) 'Constructor de parámetros inicio = New PuntoLidar(ini) final = New PuntoLidar(fin) End Sub Sub New(ByVal l2 As LineaLidar) 'Constructor de copia inicio = New PuntoLidar(l2.inicio) final = New PuntoLidar(l2.final) End Sub End Class Escuela Politécnica Superior de Ávila Universidad de Salamanca 19 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Ahora creamos dos clases como colecciones de datos. Serán listas para almacenar los puntos por un lado y las líneas por el otro. La clase ListaPuntos.vb quedará: Public Class ListaPuntos Inherits System.Collections.CollectionBase 'Lista que hereda de CollectionBase Public Sub Add(ByRef punto As PuntoLidar) List.Add(punto) End Sub Public Sub Remove(ByVal indice As Integer) 'Redefinimos Remove para controlar el rango If indice > Count - 1 Or indice < 0 Then System.Windows.Forms.MessageBox.Show("Punto fuera de rango!") Else List.RemoveAt(indice) End If End Sub Public ReadOnly Property Item(ByVal indice As Integer) As PuntoLidar 'Redefinimos item para que maneje PuntoLidar y no Object Get If indice > Count - 1 Or indice < 0 Then System.Windows.Forms.MessageBox.Show("Punto fuera de rango!") Return Nothing Else Return CType(List.Item(indice), PuntoLidar) End If End Get End Property Public Function MaximoX() As Double 'Creamos funciones para el máximo y mínimo de X,Y,Z Dim i As Integer If Count > 0 Then MaximoX = CType(List.Item(0), PuntoLidar).x For i = 0 To Count - 1 If MaximoX < CType(List.Item(i), PuntoLidar).x Then MaximoX = CType(List.Item(i), PuntoLidar).x End If Next Else MaximoX = 0 End If End Function Public Function MinimoX() As Double If count > 0 Then Dim i As Integer MinimoX = CType(List.Item(0), PuntoLidar).x For i = 0 To Count - 1 If MinimoX > CType(List.Item(i), PuntoLidar).x Then MinimoX = CType(List.Item(i), PuntoLidar).x End If Next Else minimoX = 0 End If End Function Escuela Politécnica Superior de Ávila Universidad de Salamanca 20 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Public Function MaximoY() As Double If count > 0 Then Dim i As Integer MaximoY = CType(List.Item(0), PuntoLidar).y For i = 0 To Count - 1 If MaximoY < CType(List.Item(i), PuntoLidar).y Then MaximoY = CType(List.Item(i), PuntoLidar).y End If Next Else maximoy = 0 End If End Function Public Function MinimoY() As Double If count > 0 Then Dim i As Integer MinimoY = CType(List.Item(0), PuntoLidar).y For i = 0 To Count - 1 If MinimoY > CType(List.Item(i), PuntoLidar).y Then MinimoY = CType(List.Item(i), PuntoLidar).y End If Next Else minimoy = 0 End If End Function Public Function MaximoZ() As Double If count > 0 Then Dim i As Integer MaximoZ = CType(List.Item(0), PuntoLidar).z For i = 0 To Count - 1 If MaximoZ < CType(List.Item(i), PuntoLidar).z Then MaximoZ = CType(List.Item(i), PuntoLidar).z End If Next Else maximoz = 0 End If End Function Public Function MinimoZ() As Double If count > 0 Then Dim i As Integer Minimoz = CType(List.Item(0), PuntoLidar).z For i = 0 To Count - 1 If Minimoz > CType(List.Item(i), PuntoLidar).z Then Minimoz = CType(List.Item(i), PuntoLidar).z End If Next Else minimoz = 0 End If End Function End Class Escuela Politécnica Superior de Ávila Universidad de Salamanca 21 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura La clase ListaLineas.vb queda: Public Class ListaLineas Inherits System.Collections.CollectionBase Public Sub Add(ByRef linea As LineaLidar) List.Add(linea) End Sub Public Sub Remove(ByVal indice As Integer) If indice > Count - 1 Or indice < 0 Then System.Windows.Forms.MessageBox.Show("¡Linea fuera de rango!") Else List.RemoveAt(indice) End If End Sub Public ReadOnly Property Item(ByVal indice As Integer) As LineaLidar Get Return CType(List.Item(indice), LineaLidar) End Get End Property End Class Guardamos el proyecto y Generamos la Biblioteca en Generar/Generar LidarBase. Recordamos que en la ruta \Visual Studio 2005\Projects\LidarBase\LidarBase\bin\ Release si guardamos el proyecto en la ruta por defecto nos habrá dejado el archivo LidarBase.dll. 5 Creación de la Biblioteca para Generar DXF. Creamos ahora una Biblioteca de Clases que nos permita automatizar la forma de exportar a DXF que utilizamos en uno de los ejercicios anteriores, para incorporar esta utilidad en futuras aplicaciones. Damos el nombre Biblio_A_DXF a la Biblioteca creada. En esta biblioteca vamos a necesitar la referencia a System.Windows.Forms. Lo añadimos desde Proyecto/Agregar referencia. Escuela Politécnica Superior de Ávila Universidad de Salamanca 22 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura También la Biblioteca LidarBase.dll creada en el ejercicio anterior. En esta biblioteca tendremos una clase con nombre ListaFichero que contendrá la lista de las líneas que se escribirán en el DXF. Imports System.IO Imports LidarBase Public Class ListaFichero Inherits System.Collections.CollectionBase Public Sub Add(ByRef renglon As String) List.Add(renglon) End Sub Public Sub Remove(ByVal indice As Integer) If indice > Count - 1 Or indice < 0 Then System.Windows.Forms.MessageBox.Show("¡renglon fuera de rango!") Else List.RemoveAt(indice) End If End Sub Public ReadOnly Property Item(ByVal indice As Integer) As String Get Return CType(List.Item(indice), String) End Get End Property Public Sub escribir_DXF(ByVal nombre_fich As String) Dim escribir As New StreamWriter(New FileStream(nombre_fich, FileMode.OpenOrCreate)) 'Usamos la variable de tipo StreamWriter para asociarsela al fichero que nos han indicado. 'Le ponemos que nos abra o nos cree el archivo si no existiese Dim i As Integer For i = 0 To List.Count - 1 'Recorremos los renglones y los escribimos en el fichero escribir.WriteLine(List.Item(i).ToString) Next escribir.Close() 'cerramos el archivo End Sub Escuela Politécnica Superior de Ávila Universidad de Salamanca 23 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Public Sub agregar_comienzo() List.Add("0") 'Escribimos las lineas de comienzo del DXF en la lista de renglones. List.Add("SECTION") List.Add("2") List.Add("ENTITIES") End Sub Public Sub agregar_fin() List.Add("0") 'Escribimos la parte final del fichero DXF List.Add("ENDSEC") 'Fin de sección de entidades List.Add("0") List.Add("EOF") 'Fin del fichero End Sub Public Sub agregar_Lista_Puntos(ByVal listapun As ListaPuntos, ByVal capa As String) Dim i As Integer For i = 0 To listapun.Count - 1 List.Add("0") 'Que sigue el indicador de entidad List.Add("POINT") 'Escribimos cada punto List.Add("8") 'Para decirle que lo siguiente es una capa List.Add(capa) 'Nombre de la capa en la que va el punto. LA crea aunque no la hayamos definido previamente List.Add("62") 'Código para decirle que lo siguiente es el color List.Add(CStr(ACI_Cercano_RGB(listapun.Item(i).rojo, listapun.Item(i).verde, listapun.Item(i).azul))) 'Número de color List.Add("10") 'Código para indicar que lo que sigue es la X List.Add(listapun.Item(i).x) 'Coordenada X del punto List.Add("20") 'Código para indicar que sigue la coordenada Y List.Add(listapun.Item(i).y) 'Valor de la coordenada Y List.Add("30") 'Código que indica que sigue la Z List.Add(listapun.Item(i).z) 'Valor de la coordenada Z Next End Sub Public Sub agregar_Lista_Lineas(ByVal listalin As ListaLineas, ByVal capa As String, ByVal color As Byte) Dim i As Integer For i = 0 To listalin.Count - 1 List.Add("0") 'Que sigue el indicador de entidad List.Add("LINE") 'Escribimos cada Linea List.Add("8") 'Para decirle que lo siguiente es una capa List.Add(capa) 'Nombre de la capa en la que va la linea List.Add("62") 'Código para decirle que lo siguiente es el color List.Add("" & color) 'Número de color List.Add("10") 'Código para indicar que lo que sigue es la X del inicio de la linea List.Add(listalin.Item(i).inicio.x) 'Coordenada X List.Add("20") 'Código para indicar que sigue la coordenada Y List.Add(listalin.Item(i).inicio.y) 'Valor de la coordenada Y List.Add("30") 'Código que indica que sigue la Z List.Add(listalin.Item(i).inicio.z) 'Valor de la coordenada Z Escuela Politécnica Superior de Ávila Universidad de Salamanca 24 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura List.Add("11") 'Código para indicar que lo que sigue es la X del final de la linea List.Add(listalin.Item(i).final.x) 'Coordenada X del final List.Add("21") 'Código para indicar que sigue la coordenada Y List.Add(listalin.Item(i).final.y) 'Valor de la coordenada Y List.Add("31") 'Código que indica que sigue la Z List.Add(listalin.Item(i).final.z) 'Valor de la coordenada Z Next End Sub End Class Además creamos un módulo con nombre Funciones.vb en el que situamos la información de los colores DXF y además la función de conversión. Esté módulo queda igual que el del ejercicio de prueba de conversión. Guardamos el proyecto y Generamos la Biblioteca en Generar/Generar Biblio_A_DXF. En la ruta \bin\Release dentro de la carpeta del proyecto nos habrá dejado el archivo Biblio_A_DXF.dll. 6 Procesar puntos. Vamos a crear un proyecto nuevo con nombre ProcesarPuntos. En el colocamos un formulario al que llamaremos frm_Procesar.vb. En el colocaremos una tabla DataViewGrid, un panel sobre el que colocamos las etiquetas y cuadros de texto que se observan, el menú, un OpenFileDialog y un SaveFileDialog. Presentará el siguiente aspecto: Escuela Politécnica Superior de Ávila Universidad de Salamanca 25 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura En la tabla hemos añadido las columnas con lo nombres que vemos, dando al botón derecho sobre ella y luego Editar/Columnas, pulsamos Agregar y aparece: Recordamos que el nombre no puede contener espacios pero el texto del encabezado que es lo que se mostrará sí puede tenerlos. Para los Cuadros de Texto de la derecha se ha añadido un GroupBox, y sobre él se han ido colocando. El primero se llama txt_total, el siguiente txt_xMax, y los demás siguiendo el nombre de este último cambiando x por y o z y Max por Min según el caso. En este proyecto utilizaremos las bibliotecas de los ejercicios anteriores Biblio_A_DXF.dll y LidarBase.dll. Las cargamos desde Proyecto/Agregar Referencia. Escuela Politécnica Superior de Ávila Universidad de Salamanca 26 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura La parte inicial de la clase queda: Imports System.IO Imports LidarBase Imports Biblio_A_DXF Public Class frm_Procesar Dim Listado As New ListaPuntos Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Application.CurrentCulture = New System.Globalization.CultureInfo("en-US") End Sub Como vemos hemos importado las bibliotecas anteriores y la de entrada y salida para leer y escribir en ficheros. En el formulario Creamos una instancia de la clase ListaPuntos definida en la biblioteca LidarBase que es la que usaremos para almacenar los puntos leídos. A la hora de manejar algunos datos Visual usa el formato numérico por defecto de Windows. Si nuestros puntos tienen el separador decimal “.” podría no convertirlos bien. Para solucionarlo le asociamos al evento cargar el formulario(Load) el código indicado que cambia la configuración de idioma de la aplicación actual al Ingles US para que coja como separador decimal el “.” En el menú Archivo/Abrir colocamos el código: Private Sub AbrirToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AbrirToolStripMenuItem.Click OpenFileDialog1.Filter = "Archivos XYZ(*.xyz)|*.xyz|Archivos Ascii(*.asc)|*.asc|Archivos de Texto(*.txt)|*.txt|Todos los Archivos|*.*" 'Le indicamos los filtros que aparecerán al seleccionar los archivos. asc, txt, o todos. If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then 'Mostramos diálogo de Abrir Me.Cursor = Cursors.WaitCursor 'Para que aparezca el Reloj de Arena si tarda Me.Text = "PROCESANDO ARHIVO" & OpenFileDialog1.FileName 'Colocamos en el titulo del formulario la ruta y nombre del fichero seleccionado Dim leer As New StreamReader(New FileStream(OpenFileDialog1.FileName, FileMode.Open)) 'Creamos la variable de tipo StreamReader que nos permitirá manejar el fichero 'la variable se crea a partir otra de tipo FileStream asociada al archivo seleccionado y 'Abiendo el archivo Dim linea As String Dim unpuntoLidar As PuntoLidar 'Borramos el cuadro que visionará las lineas leídas dgv_tabla.Rows.Clear() 'Borramos la tabla que muestra las coordenadas de los puntos Dim punto(5) As String 'Vector de tres cadenas para guardar la X,Y,Z de cada punto Escuela Politécnica Superior de Ávila Universidad de Salamanca 27 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Do linea = leer.ReadLine 'Leemos una linea del fichero If Not linea Is Nothing Then 'Si la linea no está vacia punto = Split(linea, vbTab, 6) 'Separamos con la función Split la linea por la posición del separador "tabulador" 'Limitamos el número de trozos a 6 para no desbordar el vector If punto.Length = 6 Then 'Si hay tres coordenadas y 3 colores escribimos en el DXF el color unpuntoLidar = New PuntoLidar(CDbl(punto(0)), CDbl(punto(1)), CDbl(punto(2))) 'Creamos un punto del tipo definido en la biblioteca de clase unpuntoLidar.rojo = CByte(punto(3)) unpuntoLidar.verde = CByte(punto(4)) unpuntoLidar.azul = CByte(punto(5)) unpuntoLidar.colorDXF = False Listado.Add(unpuntoLidar) dgv_tabla.Rows.Add(punto(0), punto(1), punto(2), punto(3), punto(4), punto(5)) 'Añado las coordenadas del punto a la tabla ElseIf punto.Length = 3 Then unpuntoLidar = New PuntoLidar(CDbl(punto(0)), CDbl(punto(1)), CDbl(punto(2))) 'Creamos un punto del tipo definido en la biblioteca de clase unpuntoLidar.rojo = 7 'Color Blanco en DXF unpuntoLidar.verde = 0 unpuntoLidar.azul = 0 unpuntoLidar.colorDXF = True Listado.Add(unpuntoLidar) dgv_tabla.Rows.Add(punto(0), punto(1), punto(2), 7) 'Añado las coordenadas del punto a la tabla End If End If Loop Until linea Is Nothing 'Repetimos hasta que linea sea vacia que se habrá terminado el fichero leer.Close() 'Cerramos el fichero leer = Nothing txt_total.Text = Listado.Count 'Pongo en txt_leidos el numero de puntos añadidos a la tabla. txt_xmax.Text = Listado.MaximoX txt_Ymax.Text = Listado.MaximoY txt_Zmax.Text = Listado.MaximoZ txt_Xmin.Text = Listado.MinimoX txt_Ymin.Text = Listado.MinimoY txt_Zmin.Text = Listado.MinimoZ Me.Cursor = Cursors.Default 'Para volver al puntero del ratón normal End If End Sub Escuela Politécnica Superior de Ávila Universidad de Salamanca 28 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Además de la Opción Abrir en el menú añadimos: En la opción Guardar en XYZ guardaremos en formato de texto delimitado por tabulaciones como en algún otro ejercicio. El código quedará: Private Sub GuardarEnXYZToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GuardarEnXYZToolStripMenuItem.Click SaveFileDialog1.Filter = "Archivos de Texto delimitado por tabulaciones(*.txt)|*.txt" 'Establecemos el formato de archivo de salida a *.txt If SaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then 'Abrimos el diálogo de guardar Dim linea As String Dim i As Integer Dim escribir As New StreamWriter(New FileStream(SaveFileDialog1.FileName, FileMode.OpenOrCreate)) 'Usamos la variable de tipo StreamWriter para asociarsela al fichero que nos han indicado. 'Le ponemos que nos abra o nos cree el archivo si no existiese 'Ponemos en el cuadro la ruta de guardar el nombre y ruta del archivo. For i = 0 To Listado.Count - 1 'Recorremos las filas del listado de puntos linea = Listado.Item(i).x.ToString & vbTab & Listado.Item(i).x.ToString & vbTab & Listado.Item(i).x.ToString 'Generamos una linea con las coordenadas de los puntos, el tabulador(vbTab) entre ellas y un salto de linea al final escribir.WriteLine(linea) 'Escribimos la linea generada en el fichero. Next escribir.Close() 'Cerramos el fichero escribir = Nothing End If End Sub Para la opción guardar en DXF utilizamos la biblioteca creada. Nos quedará: Private Sub GuardarComoDXFToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GuardarComoDXFToolStripMenuItem.Click SaveFileDialog1.Filter = "Archivo DXF(*.dxf)|*.dxf" 'Establecemos el formato de archivo de salida a *.dxf If SaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then 'Abrimos el diálogo de guardar Dim listafich As New ListaFichero listafich.agregar_comienzo() 'ESCRIBIMOS LA PARTE INICIAL Escuela Politécnica Superior de Ávila Universidad de Salamanca 29 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura listafich.agregar_Lista_Puntos(Listado, "Puntos") 'LLAMAMOS A LA FUNCIÓN QUE ESCRIBE LOS PUNTOS 'EL CODIGO SIGUIETE SERÍA UN EJEMPLO DE LA LLAMADA DXF PARA LINEAS 'CREAMOS UNA LINEA DEL PRIMER PUNTO AL ÚLTIMO Y SE LA AÑADIMOS A LA LISTA 'LUEGO AGREGAMOS LA LISTA DE LINEAS AL LISTADO DE INSTRUCCIONES PARA EL DXF 'Dim listali As New ListaLineas 'listali.Add(New LineaLidar(Listado.Item(0), Listado.Item(Listado.Count - 1))) 'listafich.agregar_Lista_Lineas(listali, "LINEAS", 5) listafich.agregar_fin() 'AGREGAMOS LA PARTE FINAL listafich.escribir_DXF(SaveFileDialog1.FileName) 'ESCRIBIMOS REALMENTE EN EL ARCHIVO End If End Sub Probamos a ejecutar el Programa y vemos su uso con el archivo Andarax_Micro.xyz proporcionado. Ahora probamos a analizar los puntos en el menú incluimos: En la opción reducir por distancia mínima incluimos: Private Sub mnu_Filtrardistancia_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnu_Filtrardistancia.Click Dim dialogo As New Filtrado Dim i, j As Integer Dim distanciaminima As Double If dialogo.ShowDialog() = Windows.Forms.DialogResult.OK And Listado.Count > 0 Then distanciaminima = CDbl(dialogo.txt_distancia.Text) 'Recogemos el valor del formulario dialogo Me.Cursor = Cursors.WaitCursor 'Para que aparezca el Reloj de Arena si tarda i = 0 While i < Listado.Count - 1 j = i + 1 While j < Listado.Count If Listado.Item(i).distanciaA(Listado.Item(j)) < distanciaminima Then Listado.RemoveAt(j) Else j = j + 1 End If End While i = i + 1 End While dgv_tabla.Rows.Clear() For i = 0 To Listado.Count - 1 dgv_tabla.Rows.Add(Listado.Item(i).x, Listado.Item(i).y, Listado.Item(i).z, Listado.Item(i).rojo, Listado.Item(i).verde, Listado.Item(i).azul) Escuela Politécnica Superior de Ávila Universidad de Salamanca 30 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura txt_total.Text = Listado.Count 'Pongo en txt_leidos el numero de puntos añadidos a la tabla. txt_xmax.Text = Listado.MaximoX txt_Ymax.Text = Listado.MaximoY txt_Zmax.Text = Listado.MaximoZ txt_Xmin.Text = Listado.MinimoX txt_Ymin.Text = Listado.MinimoY txt_Zmin.Text = Listado.MinimoZ Me.Cursor = Cursors.Default'Para dejar el puntero normal End If End Sub Previamente habremos creado el formulario Filtrado.vb con el aspecto En el botón Reducir puntos escribimos: Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click If Me.txt_distancia.Text.Length > 0 Then If IsNumeric(Me.txt_distancia.Text) Then Me.DialogResult = Windows.Forms.DialogResult.OK Else MessageBox.Show("Escriba una distancia válida", "REducir puntos por distancia") End If Else MessageBox.Show("Escriba una distancia válida", "REducir puntos por distancia") End If End Sub Lo suyo sería contemplar en un único formulario varios filtros. Para probar lo estamos haciendo en varios para no complicar. Creamos otro para descartar puntos por cota con nombre fi y el aspecto: Escuela Politécnica Superior de Ávila Universidad de Salamanca 31 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura En el botón reducir escribiremos: Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click If Me.txt_Zminima.Text.Length > 0 And Me.txt_Zmaxima.Text.Length > 0 Then If IsNumeric(Me.txt_Zminima.Text) And IsNumeric(Me.txt_Zmaxima.Text) Then If CDbl(Me.txt_Zminima.Text) < CDbl(Me.txt_Zmaxima.Text) Then Me.DialogResult = Windows.Forms.DialogResult.OK Else MessageBox.Show("Escriba unos valores validos minima debe ser menor maximo") End If Else MessageBox.Show("Escriba unos valores validos no son numeros") End If Else MessageBox.Show("Escriba unos valores validos") End If End Sub En el menú reducir por cota del formulario principal le asociamos Private Sub mnu_filtrarcota_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnu_filtrarcota.Click Dim dialogo As New frm_filtrado_cota Dim i As Integer Dim cotaminima, cotamaxima As Double If dialogo.ShowDialog() = Windows.Forms.DialogResult.OK And Listado.Count > 0 Then cotaminima = CDbl(dialogo.txt_Zminima.Text) 'Recogemos el valor del formulario dialogo cotamaxima = CDbl(dialogo.txt_Zmaxima.Text) 'Recogemos el valor del formulario dialogo Me.Cursor = Cursors.WaitCursor 'Para que aparezca el Reloj de Arena si tarda i = 0 While i < Listado.Count If Listado.Item(i).z < cotaminima Or Listado.Item(i).z > cotamaxima Then Listado.RemoveAt(i) Else i = i + 1 End If End While dgv_tabla.Rows.Clear() For i = 0 To Listado.Count - 1 dgv_tabla.Rows.Add(Listado.Item(i).x, Listado.Item(i).y, Listado.Item(i).z, Listado.Item(i).rojo, Listado.Item(i).verde, Listado.Item(i).azul) Next Escuela Politécnica Superior de Ávila Universidad de Salamanca 32 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura txt_total.Text = Listado.Count 'Pongo en txt_leidos el numero de puntos añadidos a la tabla. txt_xmax.Text = Listado.MaximoX txt_Ymax.Text = Listado.MaximoY txt_Zmax.Text = Listado.MaximoZ txt_Xmin.Text = Listado.MinimoX txt_Ymin.Text = Listado.MinimoY txt_Zmin.Text = Listado.MinimoZ Me.Cursor = Cursors.Default 'Para que aparezca el puntero normal End If End Sub Guardamos el proyecto y generamos el ejecutable. Escuela Politécnica Superior de Ávila Universidad de Salamanca 33 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura 7 Algunos componentes para CAD. Para comenzar con la representación de puntos en la pantalla vamos a utilizar algunos componentes. Estos que comentamos en su versión de Evaluación tienen algunas limitaciones. Nos decantamos por estos porque así cualquiera tiene acceso a probarlos descargándolos de la página del autor. 7.1 MTBCadViewerX. En su versión de Evaluación sólo nos permite cargar archivos en varios formatos CAD, visualizarlos y guardarlos igualmente en varios formatos. Además presenta un mensaje indicativo de versión de pruebas en la parte inferior de la pantalla. La web de la empresa creadora es: http://www.mtbsoftware.net/ Lo podemos descargar en: http://www.mtbsoftware.net/download/MTBCadViewerX_Install.zip Una vez descargado lo instalaremos siguiendo los pasos por defecto y nos dejará el componente en la carpeta C:\Archivos de programa\Archivos comunes\MTBCadViewer v.3. Allí nos dejará el componente mtbcadviewer.ocx que es el que incorporaremos al proyecto, también un fichero de ayuda ‘Manual MTBCadViewer.pdf’ en la carpeta C:\Archivos de programa\MTB SOFTWARE\MTBCadViewer v.3. Para utilizar el componente en .NET, procederemos a importarlo. Vamos a crear un proyecto nuevo con nombre MTBPrueba. En el mismo añadimos el control, para ello iremos al cuadro de herramientas. En la parte de abajo en la ficha general pulsamos al botón derecho del ratón y elegimos ‘Agregar Ficha’ con esto creamos un nuevo grupo que llamaremos ‘Controles CAD’. Dentro de esta ficha damos de nuevo al botón derecho del ratón y seleccionamos ‘Elegir Elementos’. Nos muestra ahora la ventana de la página siguiente. En ella pulsamos la pestaña Componentes COM, luego el botón de Examinar y localizamos el componente mtbcadviewer.ocx en la ruta que elegimos durante la instalación. Después de seleccionarlo nos aparecerá el componente en la lista seleccionado como se ve en la segunda ventana de la página siguiente. Escuela Politécnica Superior de Ávila Universidad de Salamanca 34 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Pulsamos Aceptar y en el cuadro de herramientas se habrá incorporado el componente presentando el aspecto: Colocamos el componente en el formulario del proyecto al que habremos dado el nombre frm_visorMTB, al componente añadido le ponemos el nombre MTBvisor. Hacemos doble-clic en el fondo del formulario, elegimos el evento Resize y colocamos el código siguiente para que el visor se adapte al cambio de tamaño del formulario. Private Sub frm_MTBvisor_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize MTBvisor.Width = Me.Width - 15 'Igualamos el ancho del visor al ancho del formulario MTBvisor.Height = Me.Height - 50 'Igualamos el alto End Sub Se podría reemplazar la barra de Herramientas del componente por una propia, e ir programando el código para cada botón y/o para cada opción del menú. Escuela Politécnica Superior de Ávila Universidad de Salamanca 35 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Probamos a abrir el archivo Cuadros.dwg proporcionado, y practicamos con el zoom, etc. Para facilitar la distribución posterior de esta aplicación que utiliza componentes externos nos aseguramos de activar la copia local del mismo. En el menú Proyecto/Propiedades de MTBPrueba, seleccionamos la referencia a MTBCadViewer y nos aseguramos que en las propiedades Aislada esté a False y Copia Local a True. Generamos el ejecutable en Generar/GenerarPruebaMTB. Este proyecto se podría completar con menús y barras de herramientas propias ayudándonos de las indicaciones del componente en el archivo ‘Manual MTBCadViewer.pdf’. Cerramos el Proyecto. 7.2 Vector DRAW. Esta empresa proporciona varios componentes para desarrollar aplicaciones CAD con .NET. La versión de evaluación del componente que usaremos dura 90 días. También pone un mensaje molesto en el fondo del visor, y un diálogo indicativo de los días de uso que llevamos. Nos hemos decidido por el por sus grandes posibilidades, porque está accesible a todos, a pesar de las limitaciones de la versión de pruebas. La web de la empresa creadora es: http://www.vdraw.com/ Tenemos varios componentes disponibles, nosotros probamos a descargar VectorDraw Developers Framework Trial en la ruta http://www.vdraw.com/eval/vdf_eval.zip En esta ruta el manual. http://www.vdraw.com/vdframed.pdf Además descargaremos e instalaremos la aplicación VectorDraw File Converter Lite 3.0 que utilizaremos para convertir los archivos creados desde alguno de los programas que vayamos desarrollando. Aquí el enlace. http://www.vdraw.com/converter/fc_lite.zip Tras la instalación vamos a crear un Proyecto VDFPrueba para añadir los componentes. Seguimos los pasos del caso anterior y en el botón derecho sobre la ficha Controles CAD que creamos antes, en Elegir componentes, ahora en la ficha de Componentes de .Net Framework, pulsamos Examinar. Localizamos vdFramedControl.dll normalmente estará en la ruta C:\Archivos de programa\VectorDraw\Common\6014 o 6XXX para versiones posteriores. Al pulsar Aceptar, nos aparece el componente en la lista, lo marcamos y pulsamos de nuevo Aceptar. Tendremos el componente en la ficha Controles CAD. Esta sería la ventana. Escuela Politécnica Superior de Ávila Universidad de Salamanca 36 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Y aquí marcamos el control. La ficha de controles aparecería: Escuela Politécnica Superior de Ávila Universidad de Salamanca 37 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Como en el caso anterior, nos aseguramos de copiar el componente a la carpeta local del programa o si deseamos quitarlo para no duplicar componentes lo haríamos en Proyecto/Propiedades en el apartado Referencias. Probamos las opciones incorporadas. Guardamos el proyecto. 8 Cargar y dibujar puntos de datos terrestres. Creamos otro proyecto nuevo para dibujar los puntos con nombre “DibujarTerrestre”. Cambiamos el nombre al formulario y le llamamos frm_visor. En el incorporamos un menú como el siguiente: que comentábamos Vamos a incorporar el componente anteriormente. Le vamos a cambiar el nombre a vdf_visor. Queremos que el espacio de dibujo que nos proporciona el control utilizado se redimensione ajustándose al tamaño que le demos al formulario, para ellos vamos a asociar el código siguiente al evento Resize del formulario. Private Sub frm_visor_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize VdF_visor.Width = Me.Width - 15 'Igualamos el ancho del visor al ancho del formulario VdF_visor.Height = Me.Height - 65 'Igualamos el alto End Sub Preparamos ahora el código necesario para cargar y dibujar los puntos: Private Sub AbrirToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AbrirToolStripMenuItem.Click OpenFileDialog1.Filter = "Archivos Ascii(*.asc)|*.asc|Archivos de Texto(*.txt)|*.txt|Todos los Archivos|*.*" 'Le indicamos los filtros que aparecerán al seleccionar los archivos. asc, txt, o todos. OpenFileDialog1.ShowDialog() 'Mostramos diálogo de Abrir Dim leer As New StreamReader(New FileStream(OpenFileDialog1.FileName, FileMode.Open)) 'Creamos la variable de tipo StreamReader que nos permitirá manejar el fichero 'la variable se crea a partir otra de tipo FileStream asociada al archivo seleccionado y 'Abiendo el archivo Escuela Politécnica Superior de Ávila Universidad de Salamanca 38 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Dim linea As String Dim vdf_punto As New VectorDraw.Geometry.gPoint 'Variable de la clase punto que proporciona vector Draw. 'Es la misma idea que la clase punto3D que nos creamos nosotros en la biblioteca de clases de la introducción VdF_visor.BaseControl.ActiveDocument.[New]() ' Creamos un documento nuevo Dim punto(2) As String 'Vector de tres cadenas para guardar la X,Y,Z de cada punto Do linea = leer.ReadLine 'Leemos una linea del fichero If Not linea Is Nothing Then 'Si la linea no está vacia punto = Split(linea, vbTab, 3) 'Separamos con la función Split la linea por la posición del separador "tabulador" 'Limitamos el número de trozos a 3 para no desbordar el vector If punto.Length = 3 Then 'Si no hay tres coordenadas descartamos el dato vdf_punto.x = CDbl(punto(0)) 'Ponemos en la coordenada x del punto de vector Draw el valor leido vdf_punto.y = CDbl(punto(1)) 'Igual en la y vdf_punto.z = CDbl(punto(2)) 'Igual en la Z 'VdF_visor.BaseControl.ActiveDocument.ActivePenColor.SystemColor = Color.Yellow 'Forma de indicar el color con colores del sistema VdF_visor.BaseControl.ActiveDocument.ActivePenColor.TrueColor = RGB(0, 255, 255) 'Indicamos el color en RGB VdF_visor.BaseControl.ActiveDocument.CommandAction.CmdPoint(vdf_punt o) 'Dibujamos el punto End If End If Loop Until linea Is Nothing 'Repetimos hasta que linea sea vacia que se habrá terminado el fichero leer.Close() 'Cerramos el fichero leer = Nothing VdF_visor.BaseControl.ActiveDocument.CommandAction.Zoom("e", Nothing, Nothing) 'Hacemos zoom Extension End Sub Podemos entender el funcionamiento del código a partir de los comentarios en el mismo. Podemos utilizar las herramientas del menú inferior para cambiar de vista, etc. Vamos a escribir el código para guardar el documento creado. En la versión de evaluación solo nos permite guardarlo en formato “vdml”, pero podemos utilizar la aplicación Vector Draw File converter para convertir a DWG, DGN o DXF entre otros. El código sería: Escuela Politécnica Superior de Ávila Universidad de Salamanca 39 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura Private Sub GuardarToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GuardarToolStripMenuItem.Click Dim ver As String = "" Dim nombre As String = VdF_visor.BaseControl.ActiveDocument.GetSaveFileNameDlg(VdF_visor.Ba seControl.ActiveDocument.FileName, ver) 'Tomamos el nombre del dialogo de guardar que nos proporciona vector Draw If Not (nombre Is Nothing) Then VdF_visor.BaseControl.ActiveDocument.SaveAs(nombre) 'Guardamos el documento creado End If End Sub Guardamos y cerramos el proyecto. 9 Cargar y dibujar puntos con información de color. Vamos a crear otro proyecto casi igual al anterior, pero ahora los ficheros a parte de la X,Y,Z tendrán también información de color en RGB. Creamos otro proyecto nuevo para dibujar los puntos con nombre “DibujarColor”. Cambiamos el nombre al formulario y le llamamos frm_visor. En el incorporamos un menú como el siguiente: Vamos a incorporar el componente el nombre a vdf_visor. El código a asociar al menú Abrir y dibujar es: . Le vamos a cambiar Private Sub AbrirToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AbrirToolStripMenuItem.Click OpenFileDialog1.Filter = "Archivos Ascii(*.asc)|*.asc|Archivos de Texto(*.txt)|*.txt|Todos los Archivos|*.*" 'Le indicamos los filtros que aparecerán al seleccionar los archivos. asc, txt, o todos. OpenFileDialog1.ShowDialog() 'Mostramos diálogo de Abrir Dim leer As New StreamReader(New FileStream(OpenFileDialog1.FileName, FileMode.Open)) 'Creamos la variable de tipo StreamReader que nos permitirá manejar el fichero 'la variable se crea a partir otra de tipo FileStream asociada al archivo seleccionado y 'Abiendo el archivo Dim linea As String Dim vdf_punto As New VectorDraw.Geometry.gPoint 'Variable de la clase punto que proporciona vector Draw. 'Es la misma idea que la clase punto3D que nos creamos nosotros en la biblioteca de clases de la introducción 'Forma de indicar el color con colores del sistema Escuela Politécnica Superior de Ávila Universidad de Salamanca 40 Herram. Inf. para el Geoprocesado. Procesamiento y Gestión de datos Láser y Rádar Geotecnologías Cartográficas en Ingeniería y Arquitectura 'Es la misma idea que la clase punto3D que nos creamos nosotros en la biblioteca de clases de la introducción VdF_visor.BaseControl.ActiveDocument.[New]() ' Creamos un documento nuevo Dim punto(5) As String 'Vector de tres cadenas para guardar la X,Y,Z de cada punto Dim rojo, verde, azul As Integer Do linea = leer.ReadLine 'Leemos una linea del fichero If Not linea Is Nothing Then 'Si la linea no está vacia punto = Split(linea, vbTab, 6) 'Separamos con la función Split la linea por la posición del separador "tabulador" 'Limitamos el número de trozos a 3 para no desbordar el vector If punto.Length = 6 Then 'Si no hay tres coordenadas y 3 colores descartamos el dato vdf_punto.x = CDbl(punto(0)) 'Ponemos en la coordenada x del punto de vector Draw el valor leido vdf_punto.y = CDbl(punto(1)) 'Igual en la y vdf_punto.z = CDbl(punto(2)) 'Igual en la Z rojo = CInt(punto(3)) verde = CInt(punto(4)) azul = CInt(punto(5)) 'VdF_visor.BaseControl.ActiveDocument.ActivePenColor.SystemColor = Color.Yellow 'Forma de indicar el color con colores del sistema VdF_visor.BaseControl.ActiveDocument.ActivePenColor.TrueColor = RGB(rojo, verde, azul) 'Indicamos el color en RGB VdF_visor.BaseControl.ActiveDocument.CommandAction.CmdPoint(vdf_punt o) 'Dibujamos el punto End If End If Loop Until linea Is Nothing 'Repetimos hasta que linea sea vacia que se habrá terminado el fichero leer.Close() 'Cerramos el fichero leer = Nothing VdF_visor.BaseControl.ActiveDocument.CommandAction.Zoom("e", Nothing, Nothing) 'Hacemos zoom Extension End Sub Probamos a Cargar el archivo Catedral_RGBmini.asc Catedral_RGB_Parte.asc para comprobar su funcionamiento. y el archivo En la opción de guardar le ponemos el mismo código que en el ejemplo anterior. Escuela Politécnica Superior de Ávila Universidad de Salamanca 41