Uso de formatos de archivo AutoCAD con bibliotecas de código abierto

Lectura de formatos de archivo DWG y DXF

Muchos expertos utilizan AutoCAD en ingeniería, diseño, arquitectura, geografía, y otros campos relacionados.A menudo es útil combinar los datos que produce AutoCAD con los datos de SIG, tales como shapefiles para localizaciones en los mapas o para su uso dentro de Google Earth o Google Maps.Aprenda sobre dos bibliotecas de código abierto — LibreDWG y dxflib— que hacen que los formatos de archivo AutoCAD DXF y DWG sean más accesibles.Además usted creará una herramienta de traductor que escribe en formatos KML y shapefile y utiliza la biblioteca GDAL para facilitar el trabajo con los formatos GML y shapefile.

Christopher Michaelis, Developer, Consultant

Christopher Michaelis photoMichaelis Christopher es un desarrollador especializado en hosting web y aplicaciones web.Asistió a la Universidad de Utah State y a la Universidad de Idaho State, en las que estudió ciencias de la computación y ciencias de la información geográfica.Su experiencia abarca una amplia gama de desarrollo, que incluyen las aplicaciones para el modelado del entorno, la educación, el análisis de datos de la diabetes, herramientas de administración de sistemas, hosting web, integración de plataformas y servicios basados en la localización.



05-03-2012

Introducción

Muchos desarrolladores y profesionales del sistema de información geográfica (SIG) han sido incapaces de utilizar un archivo Drawing Interchange Format (DXF) o "drawing" (DWG).Estos formatos de AutoCAD por lo general requieren la instalación de Windows® y una copia de AutoCAD para abrirlos.A través de algunas bibliotecas prácticas de código abierto, se puede conseguir que sus aplicaciones sean capaces de leer de forma nativa archivos DXF y DWG en cualquier sistema operativo sin ningún costo.En este artículo, se compila un convertidor para traducir estos formatos de archivo a los formatos más abiertos ESRI shapefile o Keyhole Markup Language (KML). El software comercial y el de código abierto utilizan ESRI Shapefiles, mientras que Google Earth y Google Maps usan principalmente KML.


AutoCAD DWG y LibreDWG

El formato de AutoCAD más común es el formato "drawing", con una extensión de archivo que termina en .dwg. Solamente algunas aplicaciones de software pueden leer este formato, el cual es predeterminado cuando se guardan archivos en AutoCAD.Sin embargo, se puede utilizar la biblioteca de código abierto LibreDWG (ver Recursos) para leer estos archivos.El formato del archivo se compone de un bloque de control, que contiene bloques adicionales que representan las formas en el archivo, y bloques en el espacio de modelo y en el espacio de papel, que representan desplazamientos de las coordenadas que se encuentran dentro del documento.

Usted utiliza la biblioteca al abrir el documento y leer el archivo, seguido de un bucle a través de cada bloque en el bloque de control principal, como se muestra en El Listado 1.

Listado 1. Apertura de un archivo DWG y ciclado a través del bloque de control principal
Dwg_Data dwg = new Dwg_Data();
int errno = dwg_read_file((char *)inputFilename, dwg);
if (errno) {
  fprintf(stderr, "Could not open DWG. Returned error code: $d\n", errno);
  delete dwg;
}

Dwg_Object_BLOCK_CONTROL * ctrl = dwg->object[0].tio.object->tio.BLOCK_CONTROL;
dumpBlock(ctrl->model_space);
dumpBlock(ctrl->paper_space);	

for (int i = 0; i < ctrl->num_entries; i++) {
  dumpBlock(ctrl->block_headers[i]);
}	
dwg_free(dwg);

Cada bloque puede representar cualquiera de los diversos tipos de geometría: una línea, un círculo, un arco, un texto anclado a una ubicación o una inserción (se aplicará un desplazamiento a los bloques posteriores).Cada uno se manipula accediendo a las propiedades en los objetos de bloque que se devuelven get_first_owned_object y get_next_owned_object , como se muestra en El Listado 2.

Listado 2. Lectura de objetos con get_first_owned_object and get_next_owned_object
void InputFormatDWG::dumpBlock(Dwg_Object_Ref * block) {
  if (!block) return;
  if (!block->obj) return;
  if (!block->obj->tio.object) return;

  Dwg_Object_BLOCK_HEADER * header = block->obj->tio.object->tio.BLOCK_HEADER;
  Dwg_Object * obj = get_first_owned_object(block->obj, header);
  while (obj) {
    if (obj->type == DWG_TYPE_LINE) {
      Dwg_Entity_LINE * line = obj->tio.entity->tio.LINE;
      printf("Line starting at (%f, %f, %f) ending at (%f, %f, %f)\n", line->start.x, 
              line->start.y, 0, line->end.x, line->end.y, 0);
      // Don't delete "line" - dwg_free will do this
    }

    obj = get_next_owned_object(block->obj, obj, header);
  }
}

De este modo, la lectura de un archivo DWG con LibreDWG es un flujo secuencial de principio a fin. Al implementar LibreDWG en C++, es importante incluir dwg.h dentro de un bloque externo "C" para evitar encontrarse errores posteriores de enlazador. Ver el ejemplo a continuación:

extern "C" {
	#include <dwg.h>
}

Los requisitos previos de esta biblioteca son los paquetes autoconf, swig, texinfo y python-dev así como el compilador de paquetes (build-essential si se utilizan Debian o Ubuntu).Usted puede compilar la biblioteca descargándola o introduciendo la siguiente línea de comandos:

git clone git://git.sv.gnu.org/libredwg.git

. . . seguido por:

./autogen.sh && ./configure && make && sudo make install

AutoCAD DXF y dxflib

El formato DXF es una opción de exportación dentro de AutoCAD.Como tal, es compatible con más aplicaciones que DWG, y se publica la especificación de formato de archivo especificación (ver Recursos para un enlace a la especificación completa de DXF).Sin embargo se pueden leer estos archivos utilizando la biblioteca de código abierto dxflib .A diferencia de LibreDWG, la lectura de un archivo DXF se controla menos a través de su propia codificación secuencial.De hecho, el utilizar dxflib es parecido a escribir un código controlador de eventos.

Se abre el archivo llamando a la función in del objeto DL_Dxf y pasa un puntero a una clase que hereda de la clase abstracta DL_CreationAdapter. A medida que se ejecuta la función in llama a varias funciones en la clase que se la pasa.Existen docenas de funciones como esa (ver el enlace de la Guía de programación DXFLib en Recursos pero usted sólo se preocupa de unas cuantas en la mayoría de los casos), </mdash> típicamente, addPoint, addLine, addCircle y addVertex. Sólo es necesario implementar esas funciones, el resto se pueden omitir.El Listado 3 muestra un sencillo ejemplo de subida de un archivo DXF y lectura de líneas solamente del mismo.

Listado 3. Subida de un archivo DXF y lectura de líneas solamente
LineReader.h:
#ifndef LINEREADER_H
#define LINEREADER_H

#include "dxflib/src/dl_dxf.h"
#include "dxflib/src/dl_creationadapter.h"
#include <stdio.h>

class LineReader: public DL_CreationAdapter {
	public:
		// Our functions:
		void readLines(const char * filename);

		// Overloading from parent DL_CreationAdapter:
		void addLine(const DL_LineData& data);


};
#endif

LineReader.cpp:
void LineReader::readLines(const char * filename) {
  DL_Dxf * getData = new DL_Dxf();
  if (!getData->in(filename, this)) {
    fprintf(stderr, "Could not retrieve data from input file.\n");
    delete getData;
    exit(1);
  }  
  delete getData;
}

void LineReader::addLine(const DL_LineData& data) {
  printf("Line starting at (%f, %f, %f) ending at (%f, %f, %f)\n", 
          data.x1, data.y1, data.z1, data.x2, data.y2, data.z2);
}

Como DWG, el formato DXF puede contener inserciones, que representan los desplazamientos que se aplican a los dispositivos geométricos encontrados después de la inserción. Estas inserciones se deben almacenar internamente y aplicar a las coordenadas a medida que se encuentran.De igual manera, el añadir polylines (líneas con múltiples vértices) requiere el almacenamiento de algunos datos.La biblioteca primero llama a addPolyline, indicando que la línea está llegando; entonces llama una vez a addVertex una vez con cada vértice de la línea.Por último, la línea termina cuando se llama a endEntity o endBlock momento en el que usted tiene la línea completa y puede representarla, exportarla a un nuevo formato, o tomar otras acciones.

Usted puede compilar e instalar la biblioteca DXF con sólo introducir lo siguiente en la línea de comandos:

./configure && make && sudo make install

Puede que reciba mensajes de error sobre strcasecmp así como sobre strlen sin que sean declarados.La biblioteca fue compilada dxflib para utilizarse con GCC/G++ 4.2, y en la versión 4.3, se llevo a cabo algún tipo de reorganización de los archivos de cabecera.Para arreglar este error se tienen que añadir algunas inclusiones en src/dl_writer.h y src/dl_writer_ascii.h así como en #include <cstring> y #include <cstdlib> cerca de las otras inclusiones.

Nota: Ya se realizaron estos cambios en la copia de dxflib incluida con el convertidor de código fuente disponible en Descargas, por lo que este cambio solamente se aplica si usted descarga dxflib directamente desde la web site dxflib .


KML y textos planos/Xerces-C++

El formato KML que utilizan Google Earth y Google Maps es un formulario especializado de XML; como tal se pueden utilizar bibliotecas como Xerces-C++ XML Parser (ver Recursos para un enlace) para trabajar con archivos KML. Al leer estos formatos, se advierte a las bibliotecas Xerces-C++ que manipulen estructuras más complejas que puedan aparecer.Cuando se escribe, normalmente es suficiente utilizar una simple funcionalidad de lenguaje integrada para escribir archivos de texto, y después generar el texto correspondiente tú mismo.

Un archivo KML básico consiste en una sección del Documento que contiene un nombre y una descripción. El archivo también puede contener una o más carpetas (utilizadas para organizar formas lógicamente), y dentro de cada carpeta están las marcas de posición.Las marcas de posición son la forma real, la cual se puede definir como Serie lineal, Punto, Polígono, u otros tipos.El escribir un archivo KML requiere escribir textos formateados adecuadamente que representan las formas, como se muestra en el Listado 4.

Listado 4. Un simple archivo KML
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
  <name>test</name>
  <open>1</open>
  <description>Converted from AutoCAD DXF or DWG</description>
  <Folder>
    <name>test</name>
    <Placemark>
      <LineString>
        <tessellate>0</tessellate>
        <coordinates>27.54998,82.27393,0.00000 39.72346,9.25601,0.00000</coordinates>
      </LineString>
    </Placemark>
  </Folder>
</Document>
</kml>

También se pueden encontrar archivos KMZ, que son archivos KML comprimidos con compresión ZIP.Consulte Recursos para un enlace a un tutorial de principiante de KML y documentación completa de KLM.


ESRI Shapefile y GDAL/OGR

El formato shapefile es un formato comercial de datos binarios (pero abierto) publicado por ESRI (ver Recursos para un enlace a una completa descripción técnica). Se puede utilizar el código abierto OGR Simple Feature Library— que forma parte del Geospatial Data Abstraction Layer (GDAL)— para acceder a estos archivos fácilmente.En el convertidor de ejemplo, usted sólo necesita una salida, pero esta biblioteca también simplifica la lectura de los datos de forma. La escritura de datos requiere la apertura de un origen de datos de salida y la creación de una capa de datos dentro de el.Usted puede crear campos para almacenar datos nonspatial para cada forma.Una vez creado el origen de datos de salida, se pueden añadir múltiples formas (llamadas dispositivos) al origen de datos.La Creación de un dispositivo requiere además la creación de una geometría, como un punto o una línea, y asociarla al dispositivo.El dispositivo actúa como un contenedor para todos datos de campo/nonspatial y geométricos.

El Listado 5 muestra el código para la creación de un nuevo origen de datos y un punto único shapefile dentro del conjunto de datos.Ver el tutorial leer/escribir OGR C++ y la jerarquía de clase OGR y enlaces de documentación en Recursos Para obtener más información sobre el uso de OGR y para un enlace de descarga a la misma biblioteca. La mayoría de repositorios de distribución Linux® incluyen los archivos de cabecera y la biblioteca GDAL como libgdal1-1.7.0 y libgdal1-dev (la versión puede variar).

Listado 5. Creación de un shapefile con un punto único dentro de el
OGRRegisterAll();
OGRSFDriver drv = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("ESRI Shapefile");
if (drv == NULL) {
  fprintf(stderr, "Could not open Shapefile OGR driver.\n");
  return;
}  

OGRDataSource ds = drv->CreateDataSource(filename, NULL);
if (ds == NULL) {
  fprintf(stderr, "Could not create output file.\n");
  return;
}

OGRLayer lyr = ds->CreateLayer("Layer", NULL, wkbPoint, NULL);
if (lyr == NULL) {
  fprintf(stderr, "Could not create layer.\n");
  return;
}

// Add an ID field
OGRFieldDefn newField("id", OFTInteger);
newField.SetWidth(32);
lyr->CreateField(&newField);

if (!lyr) {
  fprintf(stderr, "No output layer is available.");
  return;
}
  
OGRFeature * newFeat = OGRFeature::CreateFeature(lyr->GetLayerDefn());
newFeat->SetField("id", lyr->GetFeatureCount(1));
OGRPoint point;
point.setX(15.653);
point.setY(43.783);
point.setZ(0);
newFeat->SetGeometry(&point);
lyr->CreateFeature(newFeat);
  
// Clean up your memory
OGRFeature::DestroyFeature(newFeat);

if (ds) {
  // Will trigger saving the file and also 
  // clean up any layer references from Create/Get Layer calls
  OGRDataSource::DestroyDataSource(ds);
}

Implementación de bibliotecas de formato de archivo

Existen tres métodos principales para implementar una biblioteca de formato de archivo en software. El primer método, — la implementación nativa en aplicaciones — requiere que se puedan utilizar las bibliotecas directamente desde su código, lo que significa que usted puede tener que escribir el código en un conjunto de lenguajes en particular, dependiendo de la disponibilidad del enlace.También se requiere algún tipo de enlace fuerte, que puede ocasionar errores de menor importancia cuando se actualizan las versiones de la biblioteca.Sin embargo, la implementación directa en su aplicación hace que el uso del formato sea mucho más suave para el usuario.

Otro método consiste en escribir un plug-in o extensión de la aplicación que proporciona soporte a los formatos de archivo deseados. Este método le proporciona un cierto grado de separación entre una biblioteca de formato de archivo y el código de su aplicación.Si su aplicación ya tiene una infraestructura plug-in, esta puede ser una buena opción.Por ejemplo, Quantum GIS, una aplicación común de escritorio de GIS, utiliza una arquitectura plug-in, uno de esos plug-in le permiten utilizar archivos de texto delimitados directamente en la aplicación.

El último y el método más simple de todos ellos, — es crear un convertidor autónomo — para traducir entre dos o más formatos de archivo.Esta técnica tiene la ventaja de que se puede volver a utilizar independientemente de su objetivo final para los datos a costa de añadir otro paso para los usuarios.


Un traductor de línea de comandos para DXF/DWG a KML/Shapefile

En este ejemplo, usted toma la ruta más sencilla y más reutilizable para crear un traductor de formatos de archivo.El objetivo es crear un convertidor que sea fácil de ampliar para manipular formatos adicionales y eso mantiene la lógica de cualquier formato de entrada o salida en particular lo más separados posible. Estos objetivos llevan a la definición de dos clases abstractas: InputFormat y OutputFormat (vea El Listado 6).

Listado 6. Definiciones de clase abstracta de InputFormat y OutputFormat
OutputFormat.h:
#ifndef OUTPUTFORMAT_H
#define OUTPUTFORMAT_H

#include "OutputFormatTypes.h"
#include <vector>

class OutputFormat {
  public:
    OutputFormat() {};
    ~OutputFormat() {};

    // Standard feature types:
    virtual void addPoint(OutputFeaturePoint newPoint) = 0;
    virtual void addLine(OutputFeatureLine newLine) = 0;
    virtual void addPolyLine(std::vector<OutputFeaturePoint *> newPoints) = 0;
    virtual void addPolygon(std::vector<OutputFeaturePoint *> newPoints) = 0;

    // For approximating text on DXF/DWG with a separate point layer with
    // a label attribute:
    virtual void addText(OutputFeaturePoint location, const char * text) = 0;

    // The cleanup function
    virtual void finalizeOutput() = 0;
};
#endif

InputFormat.h:
#ifndef INPUTFORMAT_H
#define INPUTFORMAT_H

#include "OutputFormat.h"

class InputFormat {
  public:
    InputFormat() {};
    ~InputFormat() {};
    virtual void readFeaturesInto(OutputFormat * outputHandler) = 0; 
};
#endif

Cualquier formato que se implemente debe heredar de una de estas clases.De esta manera, la función principal y el punto de entrada del programa pueden acordar en exclusiva con determinación de qué clase se crea una instancia.Una vez definidos un archivo de entrada y un archivo de salida, la conversión se llevará a cabo con una única línea de código:

input->readFeaturesInto(output);

El rol de la función principal (ver Listado 7), se convierte entonces únicamente creando la instancia adecuada de formatos de entrada y salida, que culmina con la llamada a la función readFeaturesInto .

Listado 7. La función principal() del convertidor AutoCAD
void usage(char * me) {
  printf("Usage: %s inputfile outputfile [point|line|polygon]\n", me);
  printf("Input formats supported:\n");
  printf("\tAutoCAD DXF (*.dxf)\n");
  printf("\tAutoCAD DWG (*.dwg)\n");
  printf("Output formats supported:\n");
  printf("\tText (*.txt)\n");
  printf("\tESRI Shapefile (*.shp)\n");
  printf("\tKeyhold Markup Language (*.kml)\n");
  printf("\nInput format and output format are determined automatically by file extension.
		  \n");
  printf("If you use a shapefile as the output format, please additionally specify\n");
  printf("point, line, or polygon output shapefile type.\n");
}

int main(int argc, char * argv[]) {
  if (argc < 3) {
    usage(argv[0]);
    return 1;
  }

  OutputFormat * output = NULL;  
  InputFormat * input = NULL;
  struct stat fileExists;

  // Set up output format first...
  std::string outFile = argv[2];
  if (outFile.rfind('.') == std::string::npos) {
    printf("I couldn't make sense of your output filename's extension: %s. Please use 
            filename.shp, filename.kml, or filename.txt.\n", argv[2]);
    return 1;
  }
  if (outFile.substr(outFile.rfind('.')+1) == "txt") {
    printf("Setting up output file %s...\n", argv[2]);
    output = new OutputFormatText(argv[2]);
  }
  else if (outFile.substr(outFile.rfind('.')+1) == "shp") {
    if (argc < 4) {
      printf("When specifying shapefile output, please also specify 'point', 'line', or 
              'polygon'. See usage.\n");
      return 1;
    }
    std::string textAttributeFile = outFile.substr(0, outFile.rfind('.')) + "_text.shp";
    OGRwkbGeometryType type;
    if (strcmp(argv[3], "line") == 0) {
      type = wkbLineString;
    }
    else if (strcmp(argv[3], "point") == 0) {
      type = wkbPoint;
    }
    else if (strcmp(argv[3], "polygon") == 0) {
      type = wkbPolygon;
    }
    else {
      printf("I didn't understand %s. Please use point, line, or polygon.\n", argv[3]);
      return 1;
    }
    printf("Setting up output file %s...\n", argv[2]);
    output = new OutputFormatSHP(argv[2], textAttributeFile.c_str(), outFile.substr(0, 
                 outFile.rfind('.')).c_str(), type);
  }
  else if (outFile.substr(outFile.rfind('.')+1) == "kml") {
    printf("Setting up output file %s...\n", argv[2]);
    output = new OutputFormatKML(argv[2], outFile.substr(0, outFile.rfind('.')).c_str());
  }

  // Next grab the input file
  std::string inFile = argv[1];
  if (inFile.rfind('.') == std::string::npos) {
    printf("I couldn't make sense of your input filename's extension: %s. Please use 
            filename.dxf or filename.dwg.\n", argv[1]);
    delete output;
    return 1;
  }
  if (stat(argv[1], &fileExists) != 0) {
    printf("The specified input file does not exist or is not accessible: %s\n", argv[1]);
    return 1;
  }
  if (inFile.substr(inFile.rfind('.')+1) == "dxf") {
    input = new InputFormatDXF(argv[1]);
    printf("Setting up input file %s...\n", argv[1]);
  }
  else if (inFile.substr(inFile.rfind('.')+1) == "dwg") {
    input = new InputFormatDWG(argv[1]);
    printf("Setting up input file %s...\n", argv[1]);
  }

  if (!input) {
    printf("The input file was not recognized or could not be opened.\n");
    return 1;
  }
  if (!output) {
    printf("The output file was not recognized or could not be opened.\n");
    return 1;
  }

  printf("Converting file...\n");
  input->readFeaturesInto(output);
  output->finalizeOutput();
  printf("Done!\n");

  delete input;
  delete output;
  return 0;
}

La única función requerida en la clase InputFormat es readFeaturesInto, que la deja abierta al formato de entrada individual de como realmente se quiere proporcionar los dispositivos (formas) a la clase de salida suministrada.La clase OutputFormat tiene unas cuantas funciones necesarias más, sin embargo — funciona para añadir varios tipos de formas geométricas.Usted define sus propias clases de punto y línea para que pueda proporcionar todos los argumentos como valores dobles en lugar de números enteros y así poder suministrar una z-axis.

El formato ESRI Shapefile tiene una limitación importante, sólo puede almacenar formas de un sólo tipo (por ejemplo, sólo líneas, solo puntos, o sólo polígonos).No se hace mención a ningún otro formato en este artículo — DXF, DWG, y KML — tienen esta restricción. En la clase OutputFormatSHP usted comprueba que puede ver qué tipo shapefile se está creando, si no es el tipo correcto, se manipula de la mejor manera.Mientras se crea un shapefile de puntos, cuando se le pide que añada una forma polilínea, añada cada vértice como un punto individual. Mientras crea un shapefile de líneas, en caso de que se solicite que añada un punto, se escribe una advertencia en el error estándar indicando que la forma fue ignorada.Los formatos de archivo DXF y DWG también soportan arcos y círculos, los cuales se pueden aproximar en sus formatos de salida mediante la creación de múltiples segmentos de línea pequeña de aproximadamente el círculo o el arco.

Al compilar la aplicación de ejemplo, puede que reciba mensajes de error en relación con dwg.h. Las bibliotecas dxflib y LibreDWG definen la definición global de THICKNESS, por lo tanto edite el archivo dwg.h en la ubicación instalada (por ejemplo, /usr/local/include/dwg.h) y cambie el nombre de la constante THICKNESS o añada un subrayado (_) al final.(Esto no se utiliza realmente en este código de ejemplo.)

Nota: Consulte la sección del tema Descargas para el código de origen completo en este ejemplo de traductor de formato de archivo.


Recortar el traductor en una web site

Llegados a este punto, usted tiene un completo traductor funcional de línea de comandos para formatos de archivo.Sin embargo, la mayoría de los usuarios que normalmente preguntan cómo leer estos archivos no son ni expertos en líneas de comandos ni capaces de compilar el convertidor desde el origen por ellos mismos. Por lo tanto tiene sentido el proporcionar una sencilla gateway basada en la web a esta herramienta, por lo que la gente que necesite una rápida conversión de uno o dos archivos puede hacerla fácilmente.Al mismo tiempo, se puede crear un sistema en el que los archivos se convierten automáticamente cuando se añaden a un directorio en particular en el disco. — Útil para la interacción de FTP o para el acceso a través de un intercambio de archivos CIFS.

En primer lugar, crear un grupo de directorios para los diversos tipos de formato de salida shapefile:

  • uploads_KML t uploads_Text para KML y formatos de salida de texto
  • uploads_Point, uploads_Polyline, y uploads_Polygon para las diversos tipos de formatos de salida de shapefile

La convención será que cualquier archivo DXF o DWG subido a alguna de estas ubicaciones se convertirá en el formato que implica el nombre del directorio. Se deben ubicar las salidas en otro directorio, llamado outputs.

Dada tal configuración, se puede construir un simple script BASH shell (ver Listado 8) para comprobar si los archivos DWG y DXF en esta ubicación y desencadenar el convertidor con los argumentos de línea de comandos correspondientes. Para ayudar en depuraciones futuras, este script también puede guardar todas las entradas subidas junto con las salidas generadas en un archivo. zip con indicación de fecha y hora para su uso administrativo.Se puede configurar este script para que se ejecute periódicamente como un trabajo cron o para el uso de FTP y CIFS (intercambio de archivos de Windows) como un convertidor automático.

Listado 8. Script BASH para verificar si existen conversiones pendientes de archivos y pasarlas al convertidor
#!/bin/bash -u

# Polyline Shapefile queue
cd /var/www/acadconverter.chrismichaelis.com/uploads_Polyline
for file in /var/www/acadconverter.chrismichaelis.com/uploads_Polyline/*.d*; do
  [[ "$file" =~ .dxf$ || "$file" =~ dwg$ ]] && {
    base=$(basename "$file")
    base=${base%.dwg}
    base=${base%.dxf}
    /var/www/acadconverter.chrismichaelis.com/bin/AutoCADConverter \
                "$file" "$base.shp" line
    [ -e "../outputs/$base.zip" ] && rm -f "../outputs/$base.zip"
    zip "../outputs/$base.zip" "$base.shx" "$base.shp" "$base.dbf" \
                "${base}_text.shp" "${base}_text.shx" "${base}_text.dbf"
    zip "../uploads_done/$(date +%s)_$base.zip" "$base.shx" "$base.shp" "$base.dbf" \ 
                "${base}_text.shp" "${base}_text.shx" "${base}_text.dbf" "$file"
    rm -f "$file" "$base.shx" "$base.shp" "$base.dbf" "${base}_text.shp" \ 
                "${base}_text.shx" "${base}_text.dbf"
  }
done

# Polygon Shapefile queue
cd /var/www/acadconverter.chrismichaelis.com/uploads_Polygon
for file in /var/www/acadconverter.chrismichaelis.com/uploads_Polygon/*.d*; do
  [[ "$file" =~ .dxf$ || "$file" =~ dwg$ ]] && {
    base=$(basename "$file")
    base=${base%.dwg}
    base=${base%.dxf}
    /var/www/acadconverter.chrismichaelis.com/bin/AutoCADConverter "$file" \ 
                "$base.shp" polygon 
    [ -e "../outputs/$base.zip" ] && rm -f "../outputs/$base.zip"
    zip "../outputs/$base.zip" "$base.shx" "$base.shp" "$base.dbf" \ 
                "${base}_text.shp" "${base}_text.shx" "${base}_text.dbf"
    zip "../uploads_done/$(date +%s)_$base.zip" "$base.shx" "$base.shp" "$base.dbf" \ 
                "${base}_text.shp" "${base}_text.shx" "${base}_text.dbf" "$file"
    rm -f "$file" "$base.shx" "$base.shp" "$base.dbf" "${base}_text.shp" \ 
                "${base}_text.shx" "${base}_text.dbf"
  }
done

# Point Shapefile queue
cd /var/www/acadconverter.chrismichaelis.com/uploads_Point
for file in /var/www/acadconverter.chrismichaelis.com/uploads_Point/*.d*; do
  [[ "$file" =~ .dxf$ || "$file" =~ dwg$ ]] && {
    base=$(basename "$file")
    base=${base%.dwg}
    base=${base%.dxf}
    /var/www/acadconverter.chrismichaelis.com/bin/AutoCADConverter "$file" \
                "$base.shp" point
    [ -e "../outputs/$base.zip" ] && rm -f "../outputs/$base.zip"
    zip "../outputs/$base.zip" "$base.shx" "$base.shp" "$base.dbf" \  
                "${base}_text.shp" "${base}_text.shx" "${base}_text.dbf"
    zip "../uploads_done/$(date +%s)_$base.zip" "$base.shx" "$base.shp" "$base.dbf" \ 
                "${base}_text.shp" "${base}_text.shx" "${base}_text.dbf" "$file"
    rm -f "$file" "$base.shx" "$base.shp" "$base.dbf" "${base}_text.shp" \  
                "${base}_text.shx" "${base}_text.dbf"
  }
done

# KML queue
cd /var/www/acadconverter.chrismichaelis.com/uploads_KML
for file in /var/www/acadconverter.chrismichaelis.com/uploads_KML/*.d*; do
  [[ "$file" =~ .dxf$ || "$file" =~ dwg$ ]] && {
    base=$(basename "$file")
    base=${base%.dwg}
    base=${base%.dxf}
    /var/www/acadconverter.chrismichaelis.com/bin/AutoCADConverter "$file" "$base.kml" 
    [ -e "../outputs/$base.zip" ] && rm -f "../outputs/$base.zip"
    zip "../outputs/$base.zip" "$base.kml"
    zip "../uploads_done/$(date +%s)_$base.zip" "$base.kml" "$file"
    rm -f "$file" "$base.kml"
  }
done

# Text queue
cd /var/www/acadconverter.chrismichaelis.com/uploads_Text
for file in /var/www/acadconverter.chrismichaelis.com/uploads_Text/*.d*; do
  [[ "$file" =~ .dxf$ || "$file" =~ dwg$ ]] && {
    base=$(basename "$file")
    base=${base%.dwg}
    base=${base%.dxf}
    /var/www/acadconverter.chrismichaelis.com/bin/AutoCADConverter "$file" "$base.txt" 
    [ -e "../outputs/$base.zip" ] && rm -f "../outputs/$base.zip"
    zip "../outputs/$base.zip" "$base.txt"
    zip "../uploads_done/$(date +%s)_$base.zip" "$base.txt" "$file"
    rm -f "$file" "$base.txt"
  }
done

La misma web site puede ser una simple página de subida de archivo. En este caso, el incluir una barra de progreso de subida sería una buena mejora.Una herramienta de código abierto llamada Ajax Upload (vea Recursos para un enlace) utiliza XMLHttpRequest para ayudar a producir una más fluida interfaz de subida. En la página HTML, utilice la función jQuery ready para crear el cargador de archivos una vez haya subido la página y pasar el formato de salida seleccionado junto con el archivo subido (ver Listado 9.). Utilizar el script de subida de stock en PHP que se suministra con la herramienta Ajax Upload, y al final de ese script, altere el comando handleUpload para guardar el archivo subido al directorio correcto para el tipo de salida deseada. En lugar de esperar a que se lleve a cabo el trabajo planificado cron , utilizar la función exec PHP para iniciar el script y convertir el archivo.La página HTML espera un momento hasta que finalice la conversión, y luego dirige al visitante al archivo .zip generado que contiene los archivos de salida generados.

Listado 9. Función jQuery ready() para instalar el cargador de archivos
$(document).ready(function() {
  var uploader = new qq.FileUploader({
    'element': $('#inputFile')[0],
    'action': 'fileuploader.php',
    'params': { 'outputFormat': $('#outputFormat option:selected').attr('value') },
    'onComplete': function(id, file, response) {
      if (!response.success) return;
      // Please Wait
      $('#postLoader').hide()
      $('#postLoader').html('<img src="clock.png" height="210" width="210"><br />
                             Please Wait...');
      $('#postLoader').slideDown();

      // for IE compatibility, don't use anonymous function in setTimeout
      setTimeout("showDownload('" + file.replace(".dwg", "").replace(".dxf", "") + "');",
                 5000);
      return true;
    }
  });

  $('#outputFormat').change(function() {
    uploader.setParams({
      'outputFormat': $('#outputFormat option:selected').attr('value')
    });
  });
});

function showDownload(file) {
  $('#postLoader').slideUp('slow', function() { $('#postLoader').html('<img 
        src="download.png" height="48" width="48" align="absmiddle"> 
        <a href="outputs/' + file + '.zip">Download Ouptut</a>').slideDown(); });
}

Este código simplifica considerablemente el convertidor, logrando el objetivo de hacerlo de fácil acceso para cualquier persona que necesite un archivo convertido.Consulte Recursos para un enlace a la completa interfaz de web del convertidor o ver la sección Descargas para un completo código de origen del convertidor de la página web.


Conclusión

En este ejemplo se puede ampliar el convertidor de formatos de archivos simple para manipular más formatos de archivo de datos geométricos y geográficos.Usted puede utilizar las bibliotecas demostradas aquí para ampliar cualquier herramienta de software para una manipulación nativa de estos formatos de archivo.Los enlaces para estas bibliotecas se encuentran disponibles en diferentes lenguajes más allá del uso y la sintaxis de C++ que aquí se demuestra.


Descargas

DescripciónNombretamaño
AutoCAD file format converter source codeAutoCADConverter-SourceCode.zip1.6MB
Converter website source codeConverterWebsite-SourceCode.zip0.36MB

Recursos

Aprender

Obtener los productos y tecnologías

  • El área web site de la bibliotecadxflib incluye descargas y documentación del código de origen.
  • Web site GNU LibreDWG : Encuentre el código de origen así como documentación.
  • Xerces-C++ XML Parser: Utilice esta excelente y segura forma de analizar complejos documentos XML (incluidos los derivados como GML y KML).
  • Página de descarga de GDAL : Obtenga el código de origen de OGR — una parte de GDAL —.
  • Ajax Upload: Consiga esta herramientas que utiliza XmlHTTPRequest para mostrar agradables barras de progreso de subida de archivos HTTP.
  • Desarrollo C/C++ : puede que esté interesado en la optimización que se puede conseguir con XL C/C++ de IBM para AIX y Linux.

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=Linux
ArticleID=799363
ArticleTitle=Uso de formatos de archivo AutoCAD con bibliotecas de código abierto
publish-date=03052012