Obsah
1. Vektorový grafický formát HPGL prakticky
2. Specifika ovladače plotteru Hewlett-Packard HP 7475
3. Demonstrační výkresy převedené do formátu HPGL
4. Rozpoznání jednotlivých příkazů uložených v souboru HPGL
5. Vykreslení načteného výkresu na základě uložených příkazů
6. Popis demonstračního příkladu
7. Možné další rozšíření demonstračního příkladu
8. Odkazy na další informační zdroje
9. Obsah dalšího pokračování tohoto seriálu
1. Vektorový grafický formát HPGL prakticky
V předchozí části tohoto seriálu jsme si popsali jazyk HPGL (Hewlett-Packard Graphics Language) používaný pro popis vektorových výkresů. Tento jazyk je použitý buď přímo při komunikaci s tiskárnou či plotterem (většinou přímo přes sériový či paralelní port, nověji také přes spooler) nebo při zápisu vektorové podoby výkresu do souborů s koncovkou .PLT, .HGL či .HPG. Také jsme si řekli, že pro každé kreslicí zařízení se generuje poněkud odlišný soubor podle toho, jak je které zařízení „inteligentní“. Některé plottery například nedokáží provádět vyplňování uzavřených obrazců, tisknout řetězce znaků, vykreslovat oblouky apod. Při komunikaci s těmito plottery je tedy zapotřebí všechny složitější grafické entity nechat rozložit na jednotlivé úsečky a teprve ty vykreslovat, popř. ukládat do souboru.
Na první pohled může podpora mnoha plotterů vypadat velmi složitě a nepřehledně, v některých případech si však situaci můžeme naopak podstatným způsobem zjednodušit – pokud například v daném grafickém programu (tím může být CAD/CAM, vektorový grafický editor apod.) nastavíme tisk na „málo inteligentní“ plotter, program sám či ovladač plotteru provede potřebné rozložení složitých grafických entit na entity jednodušší a ty je možné snadněji zpracovat. Tímto způsobem je možné mezi různými programy přenášet i výkresy obsahující složité prvky typu řetězce znaků či křivky, musíme se však smířit s tím, že jsou tyto prvky rozloženy na úsečky a jejich opětovné složení je velmi složité (křivky) či nemožné (texty).
V dalších kapitolách si ukážeme, jakým způsobem je možné načítat a zobrazovat soubory určené pro plotter HP 7475 a celou řadu kompatibilních tiskových zařízení.
2. Specifika ovladače plotteru Hewlett-Packard HP 7475
Typ plotteru Hewlett-Packard HP 7475 je velmi starý a tak se s tímto zařízením pravděpodobně již nesetkáte (i když výrobky HP z té doby jsou proslulé svou výdrží a technickou kvalitou – viz například „nezničitelná“ LaserJet 4). To, že tento plotter již morálně zastaral, však nevadí, celá řada plotterů HP 74.. byla velmi oblíbená a výrazným způsobem přispěla k rozšíření i akceptaci jazyka HPGL. Na tuto řadu navázali i další výrobci, proto je možné vektorové výkresy určené pro tisk na HP 7475 zpracovat i na dalších typech plotterů, včetně jejich moderních variant, které už nepoužívají klasická rýsovací pera nebo inkoustové fixy, ale rastrovou tiskovou technologii (v podstatě nejde o nic jiného, než o velkoformátové inkoustové nebo laserové tiskárny s přidanými pomůckami, například pro ořez papíru).
Plotter HP 7475 akceptuje pouze omezenou skupinu příkazů jazyka HPGL. To může být výhodné, protože při výběru tohoto typu plotteru, například v programech typu CAD, můžeme generovat soubory, které jsou kompatibilní s dalšími modernějšími plottery. Tyto soubory je možné díky své jednoduchosti i snadněji načítat a posléze zobrazovat, což si ukážeme na dnešním demonstračním příkladu. Abych byl konkrétní, uvedu v následující tabulce seznam příkazů, které plotter HP 7475 akceptuje:
Příkaz | Význam | Parametry | Popis |
---|---|---|---|
IN | Initialize | inicializace plotteru | |
SC | Scaling | x, y, x, y | nastavení měřítka pomocí obdélníku nebo inicializace měřítka |
SP | Select Pen | n | výběr kreslicího pera číslo n |
LT | Line Type | číslo, délka | nastavení typu vykreslované úsečky |
VS | Velocity Select | v | nastavení rychlosti kreslení |
PA | Plot Absolute | x, y, … | nastavení absolutních souřadnic (může kreslit) |
PU | Pen Up | x, y, … | zdvižení pera na souřadnice x, y; bývá bez souřadnic |
PD | Pen Down | x, y, … | spuštění pera na souřadnice x, y; bývá bez souřadnic |
3. Demonstrační výkresy převedené do formátu HPGL
Pro ukázku zpracování výkresů uložených v souborech typu HPGL/PLT jsem vybral trojici výkresů vytvořenou v programu AutoCAD:
- Na prvním výkresu se nachází několik kružnic o různém poloměru. Touto kresbou je předvedeno, jakým způsobem AutoCAD provedl rozklad kružnic na řetězec na sebe navazujících úseček. Celý výkres může být vykreslen jedním kreslicím perem, tj. jednobarevně. První výkres si můžete stáhnout zde.
- Na druhém výkresu je vytvořen raketoplán vykreslený v několika barvách. Opět se jedná o obrázek, ve kterém musely být původně zaoblené tvary převedeny na řetězec úseček. Současně je možné otestovat funkce změny kreslicího pera a tím pádem i barvy či tloušťky kreslených čar. Konkrétní typ pera (barva, tloušťka) původně závisel na uživateli, protože pera bylo možné v zásobníku prohazovat. Soubor s druhým výkreslem si můžete stáhnout zde.
- Na třetím výkresu je vyobrazen pohled na původně trojrozměrný model. V souborech typu HPGL/PLT se však samozřejmě nachází pouze dvourozměrná varianta, tj. průmět 3D scény do promítací roviny. Původní výkres neobsahoval žádné oblouky ani křivky, proto zde nemuselo docházet k rozkladu těchto tvarů na úsečky. Soubor se třetím výkresem se nachází pod tímto odkazem.
4. Rozpoznání jednotlivých příkazů uložených v souboru HPGL
Vzhledem k tomu, že soubory generované pro plotter HP 7475 obsahují pouze několik příkazů, může být parsovací funkce poměrně jednoduchá. Jedinou výraznější komplikací je fakt, že některé ovladače (konkrétně například ovladač v AutoCADu 2006) spojují příkazy PU a PA, popř. PD a PA do jednoho slova PUPA popř. PDPA. To samozřejmě neodporuje pravidlům stanoveným pro jazyk HPGL, ale přebytečně načtený znak je nutné vrátit zpět do bufferu načítaného souboru (nebo použít složitější programovou logiku, například KA). Po načtení příkazů, které provádí nastavení barvy pera nebo přímo vykreslují, se parametry těchto příkazů uloží do lineárního seznamu, který posléze slouží pro vykreslení celého výkresu na obrazovku. V lineárním seznamu je uložena identifikace příkazu, nové souřadnice pera (pro kreslení úseček) a popř. i nově nastavená barva pera:
// typ prikazu
typedef enum {
PEN_UP, // zvednuti kresliciho pera
PEN_DOWN, // spusteni kresliciho pera
MOVE_TO, // presun kresliciho pera
SELECT_PEN // vyber kresliciho pera ~ vyber barvy
} Command;
// jeden zaznam ziskany ze souboru HPGL
typedef struct Item {
Command cmd; // prikaz - (PEN_UP, PEN_DOWN, MOVE_TO, SELECT_PEN)
double x; // souradnice
double y;
int pen; // barva pera
struct Item *next; // vazba v linearnim seznamu
} Item;
Funkce pro načtení všech relevantních příkazů ze souboru typu HPGL/PLT může vypadat následovně (všimněte si, že nevýznamné příkazy jako IN apod. jsou přeskakovány, stejně jako několik úvodních bytů na začátku souboru, které slouží k inicializaci plotteru):
//-----------------------------------------------------------------------------
// Precteni HPGL souboru urceneho pro HP7475
//-----------------------------------------------------------------------------
int readItems(char *fileName)
{
FILE *fin=fopen(fileName, "rt");
int c;
char s[100];
if (!fin) return 0;
// smycka, ve ktere se zanalyzuje cely soubor HPGL
do {
int i;
// nacteni jednoho prikazu (oddelovacem je vetsinou strednik)
for (i=0; (c=fgetc(fin))!=';' && c!=EOF; i++) {
// tato podminka je nutna pro ovladace,
// ktere generuji kod ve stylu 'PUPA10,10'
// misto 'PU;PA10,10
if (i==2 && isalpha(c)) {
ungetc(c, fin);
break;
}
// prevod znaku na velka pismena (pro jistotu)
s[i]=(c>='a' && c<='z') ? c-'a'+'A':c;
}
s[i]=0; // ukonceni retezce
if (!strcmp(s, "PU")) {
addItem(PEN_UP, 0, 0, 0);
}
if (!strcmp(s, "PD")) {
addItem(PEN_DOWN, 0, 0, 0);
}
if (!strncmp(s, "SP", 2)) { // prikaz SP
int pen=strtol(s+2, NULL, 10); // = nacteme barvu pera
addItem(SELECT_PEN, 0, 0, pen);
}
if (!strncmp(s, "PA", 2)) { // prikaz PA
double x, y; // = musime nacist obe souradnice
for (i=0; s[i]!='-' && s[i]!='+' && !isdigit(s[i]); i++)
;
x=strtod(s+i, NULL);
i++;
for (; s[i]!='-' && s[i]!='+' && s[i]!=','; i++)
;
i++;
y=strtod(s+i, NULL);
addItem(MOVE_TO, x, y, 0);
}
} while (c!=EOF); // cteni az do konce souboru
fclose(fin);
return 1;
}
//-----------------------------------------------------------------------------
5. Vykreslení načteného výkresu na základě uložených příkazů
Vykreslení všech částí načteného výkresu je poměrně jednoduché, protože plotter HP 7475 vlastně vykresluje pouze jednotlivé úsečky nebo lomené čáry, které se opět skládají z úseček. Použitá grafická knihovna OpenGL vykreslování úseček samozřejmě podporuje, proto je převod „pohybu kreslicího pera“ na úsečky poměrně přímočarý (vzhledem k tomu, že příkazy PU a PD nejsou párovány, je další zjednodušování prakticky nemožné a musíme používat pomocné proměnné x1, y1, x2, y2). V demonstračním příkladu je možné výkresem posouvat a měnit jeho velikost (zvětšení, zmenšení), proto se před vlastním vykreslováním musí vhodně nastavit transformační matice ModelView. Výběr barvy pera je řešen přes barvovou paletu; změnou hodnot v této paletě je možné výkres jednoduše přebarvit (přesné mapování čísla pera na barvu není stanoveno).
//-----------------------------------------------------------------------------
// Prekresleni vektorove kresby
//-----------------------------------------------------------------------------
void redrawDrawing(double scale, // meritko obrazce
double xpos, // posun obrazce
double ypos)
{
Item *item=p_first;
double x1=0, y1=0, x2=0, y2=0; // souradnice pro vypocet usecek
float r=1.0, g=1.0, b=1.0; // barva kresliciho pera
float scale2=mouse.ztran0/100.0+1.0; // zmena meritka zadana mysi
Command pen=PEN_DOWN;
// posun a zmena meritka kresby
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(xpos, ypos, 0); // posun zadany klavesnici
glTranslatef(mouse.xtran0, -mouse.ytran0, 0); // posun zadany mysi
// posunuti pocatku (pro zmenu meritka vuci stredu okna
// je nutna mala programova uprava)
glTranslatef(window.width/2, window.height/2, 0);
glScalef(scale, scale, scale); // zmena meritka zadana klavesnici
glScalef(scale2, scale2, scale2); // zmena meritka zadana mysi
glScalef(0.1, 0.1, 0.1);
glTranslatef(-window.width/2, -window.height/2, 0);
// projit celym seznamem a aplikovat v nem ulozene prikazy
while (item!=NULL) {
Command cmd=item->cmd; // nacist prikaz
double x=item->x; // nacist souradnice
double y=item->y;
int pencolor=item->pen; // nacist barvu pera
item=item->next; // prechod na dalsi polozku
switch (cmd) {
case PEN_UP: // zvednuti kresliciho pera
pen=PEN_UP;
break;
case PEN_DOWN: // polozeni kresliciho pera
pen=PEN_DOWN;
break;
case MOVE_TO: // zmena pozice kresliciho pera
if (pen==PEN_UP) { // PEN_UP - presun bez kresleni
x1=x;
y1=y;
}
else { // PEN_DOWN - kreslime
x2=x;
y2=y;
glColor3f(r, g, b); // nastavit barvu
glBegin(GL_LINES); // a vykreslit usecku
glVertex2d(x1, y1);
glVertex2d(x2, y2);
glEnd();
x1=x; // zapamatovat si pozici
y1=y; // pro dalsi MOVE_TO
}
break;
case SELECT_PEN: // zmena barvy pera
{
static float palette[][3]={ // static=alokace 1x za behu
{0.0, 0.0, 1.0},
{0.0, 1.0, 0.0},
{0.0, 1.0, 1.0},
{1.0, 0.0, 0.0},
{1.0, 0.0, 1.0},
{1.0, 1.0, 0.0},
{1.0, 1.0, 1.0},
{0.5, 0.5, 0.5},
};
if (pencolor>=0 && pencolor<=7) { // HP7475 ma osm per
r=palette[pencolor][0];
g=palette[pencolor][1];
b=palette[pencolor][2];
}
else { // kazdy jiny index=bila barva
r=1.0;
g=1.0;
b=1.0;
}
}
break;
default: // ostatni prikazy ignorujeme
break;
}
}
}
//-----------------------------------------------------------------------------
6. Popis demonstračního příkladu
Céčkovské funkce redrawDrawing() a readItems() jsou použity i v dnešním demonstračním příkladu, jehož zdrojový soubor je možné získat pod tímto odkazem, k dispozici je i HTML varianta zdrojového textu se zvýrazněnou syntaxí. Při spouštění demonstračního příkladu je nutné jako první argument zadat jméno souboru uloženého ve formátu HPGL/PLT. Program se posléze pokusí z tohoto souboru načíst všechny příkazy PU, PD, PA a SP spolu s jejich parametry a uloží je do lineárního seznamu. Potom je obsah tohoto seznamu interpretován a převeden na příkazy OpenGL.
Zobrazeným výkresem je možné posouvat pomocí kurzorových kláves nebo pohybem myši se stlačeným levým tlačítkem. Také je možné výkres zvětšit či zmenšit klávesami [PageUp] a [PageDown], popřípadě i pohybem myši se stlačeným pravým tlačítkem. Při posunu a změně měřítka je použit double-buffering, takže nedochází k žádnému viditelnému poblikávání. Klávesou [Q] a [Esc] se běh programu ukončí.
7. Možné další rozšíření demonstračního příkladu
Výše uvedený demonstrační příklad je samozřejmě možné dále rozšiřovat, například se pokusit načítat i složitější příkazy než uvedenou čtveřici PU, PD, PA a SP. Pro některé modernější plottery se generují příkazy pro kresbu kružnic (CI, WG, EW), kruhových oblouků (AA, AR), textů (LB, CS, SS, CN, SI, SR…), vyplňovaných polygonů (RA, RR) apod. Kromě textů, pro jejichž korektní vykreslení je zapotřebí mít k dispozici stejné vektorové fonty (soubory typu SHX převedené do vektorů apod.), je tvar ostatních grafických entit známý i bez dalších informací a je možné provádět jejich vykreslování.
8. Odkazy na další informační zdroje
- Heslo HPGL na Wikipedii:
http://en.wikipedia.org/wiki/HPGL - Hewlett Packard Graphics Language Commands:
http://www.sxlist.com/techref/language/hpgl/commands.htm - HP-GL Graphics Language:
http://cstep.luberth.com/HPGL.pdf - EscapeE:
http://www.pclviewer.com/
(komerční software pro prohlížení a konverzi vektorových formátů, existuje trial verze pro Win32) - HPGL Viewer (AutoVue):
http://www.cimmetry.com/hpgl_viewer.html
poměrně známý prohlížeč vektorových formátů, dostupná je i evaluation verze - What is HPGL?
http://www.swiftview.com/pclcorner/pclcorner1.htm#HPGL - A Comparison of File Formats:
http://www.swiftview.com/pclcorner/compareformat.htm
porovnání PDF vs. HPGL vs. další formáty z hlediska několika požadavků (HPGL kupodivu vychází ze srovnání poměrně dobře)
9. Obsah dalšího pokračování tohoto seriálu
V následujícím pokračování tohoto seriálu si popíšeme další poměrně jednoduchý a přitom velmi rozšířený a často používaný vektorový formát. Bude se jednat o formát DXF (Drawing Interchange File), který navrhla firma AutoDesk pro svůj známý CAD systém AutoCAD. Tento formát se posléze tak rozšířil (zejména na počítačích PC), že se stal prakticky standardem při přenášení výkresů mezi jednotlivými CAD systémy, ať už dvourozměrnými či trojrozměrnými.