Format DXF : expérimentations

Cette page regroupe des informations sur tout ce qui touche au format DXF dans QElectroTech. Pour le moment, cela se cantonne aux expérimentations en vue de l'implémentation de l'export DXF.

  • Comment lire un DXF sous GNU/Linux ? Le plus simple est d'utiliser QCad
  • Quelle bibliothèque sera utilisée pour manipuler ce format ?
    • Bien que la libqcad contienne sans doute déjà de quoi interfacer une QGraphicsScene et un fichier DXF, le projet QET ne souhaite pas dépendre de cette bibliothèque
    • 20/03/2011 : bemol : la dxflib va bientôt être packagée à part : http://ftp-master.debian.org/new/dxflib_2.2.0.0-1.html
    • la libdime, bibliothèque C++ portable centrée sur le DXF, paraît plus adaptée
    • GNU LibreDWG est une librairie logicielle écrite en C pour la lecture et l'écriture de fichiers au format DWG, avec l'objectif à terme de remplacer les bibliothèques du groupe Open Design Alliance. http://www.gnu.org/software/libredwg/

Bibliothèque dime : Programme de test

#include <iostream>
 
#include <dime/Model.h>
#include <dime/Layer.h>
#include <dime/Output.h>
#include <dime/sections/EntitiesSection.h>
#include <dime/sections/TablesSection.h>
#include <dime/tables/Table.h>
#include <dime/tables/TableEntry.h>
#include <dime/tables/LayerTable.h>
#include <dime/entities/Circle.h>
 
/**
	Ce programme de test genere un fichier test.dxf comportant un cercle sur un
	calque.
	Paquets necessaires : libdime, libdime-dev
	Compile avec :
	gcc testdxf0.cpp -o testdxf0 -lstdc++ -ldime
*/
 
using namespace std;
namespace TestDXF {
	void testColor(int);
}
 
int main(int /*argc*/, char **/*argv*/) {
 
	const string dxf_file = "dxftest.dxf";
 
	cout << "generation d'un fichier DXF" << endl;
	// modele
	dimeModel dxf_model;
	dxf_model.init();
 
	// section TABLES
	dimeLayerTable *circle_layer_table_entry = new dimeLayerTable();
	circle_layer_table_entry -> setLayerName("circle", NULL);
	circle_layer_table_entry -> setColorNumber(125);
 
	dimeTable *layer_tables = new dimeTable(NULL);
	layer_tables -> insertTableEntry(circle_layer_table_entry);
 
	dimeTablesSection *tables_section = new dimeTablesSection();
	tables_section -> insertTable(layer_tables);
	dxf_model.insertSection(tables_section);
 
	// cercle
	dimeCircle *dxf_circle = new dimeCircle();
	dxf_circle -> setCenter(dimeVec3f(0.0, 0.0, 0.0));
	dxf_circle -> setRadius(1.0);
	dxf_circle -> setThickness(0.1);
 
	const dimeLayer *circle_layer_ptr = dxf_model.addLayer("circle");
	if (circle_layer_ptr != NULL) {
		dxf_circle -> setLayer(circle_layer_ptr);
	} else {
		cout << "layer circle non cree" << endl;
	}
 
	// section ENTITIES
	dimeEntitiesSection *entities_section = new dimeEntitiesSection();
	dxf_model.insertSection(entities_section);
	entities_section -> insertEntity(dxf_circle);
 
	// objet dimeOutput pour l'export vers un fichier
	dimeOutput dxf_output;
	dxf_output.setFilename(dxf_file.c_str());
 
	// ecriture du fichier
	dxf_model.write(&dxf_output);
 
	//TestDXF::testColor(125);
 
	return(0);
}
 
void TestDXF::testColor(int test_color) {
	dxfdouble r = 0.0, g = 0.0, b = 0.0;
	dimeLayer::colorToRGB(test_color, r, g, b);
	r *= 255, g *= 255, b *= 255;
	cout << test_color << " => (" << (int)r << ", " <<  (int)g << ", " <<  (int)b << ")" << endl;
}

Questions et remarques :

  • Ce format semble utiliser des couleurs sur 16 bits ; la bibliothèque Dime fournit une fonction statique dimeLayer::colorToRGB pour passer d'un entier 16 bits à 3 flottants RVB ; la fonction TestDXF::testColor du programme ci-dessus utilise dimeLayer::colorToRGB pour afficher les valeurs RVB d'un entier. Comment obtenir cet entier à partir des trois valeurs RVB ?
  • La documentation de certaines classes de la bibliothèque Dime stipule qu'elles ne doivent jamais être allouées sur la pile, sous-entendant que d'autres classes les supprime après usage ⇒ bien étudier cette gestion des objets, le programme ci-dessus comporte peut-être des fuites mémoires.
  • Il faudra s'assurer que la libdime est packagée sous Mandriva et Slackware. Il s'agit très clairement d'une dépendance supplémentaire pour QET.

Bibliothèque Qt : rendre une QGraphicsScene en DXF

D'après la documentation Qt, pour ajouter la possibilité de faire un rendu DXF à l'instar du support SVG, il faut ajouter deux classes :

  • une classe dérivant de QPaintDevice dont il faudra implémenter au moins la méthode
    virtual QPaintEngine * paintEngine () const = 0
  • une classe dérivant de QPaintEngine, qui fera le rendu DXF à partir de primitives :
    • drawEllipse
    • drawImage
    • drawLines
    • drawPath
    • drawPixmap
    • drawPoints
    • drawPolygon
    • drawRects
    • drawTextItem
    • drawTiledPixmap

Avantage : très propre : les primitives utilisées pour les éléments sont dessinées exclusivement via QPainter, sans se soucier de la cible : écran (QGraphicsView), imprimante (physique/PDF/PS), image vectorielle (SVG/DXF), image bitmap (BMP/PNG/JPEG/…), … Inconvénient : assez compliqué car exhaustif. Il n'est toutefois pas exclu de n'implémenter que les primitives qui nous intéressent.

import dxf to elmt

inkscape -E intermediate.eps infile.svg
pstoedit -dt -f dxf:-polyaslines intermediate.eps outfile.dxf
./convert_dxf_elmt.py

export dxf

Il est possible de convertir des exports de Qet format svg en dxf sois avec

  • autotrace
  • inkscape

autotrace = le fichier est bien converti au format DXF mais le résultât n'est pas convaincant au vu des premiers essais

autotrace fichier Qet.png -output-file output.dxf

inkscape s'en sort mieux et le resultat est presque exploitable

Imprimer/exporter