Universidad Iberoamericana
Programación Lógica
Primavera 1997
Manuel López Michelone
Víctor Manuel Iniestra Álvarez
Proyecto Final
Visualizador Tridimensional
Descripción:
Este programa es capaz de visualizar una representación bidimensional de un cuerpo o silueta tridimensional. Ésta esta formada por puntos en el espacio y aquellos deberán estar contenidos en un espacio limitado. Se darán tres coordenadas (XYZ) por cada punto, cada una de estas coordenadas podrá variar de 0 a 256 (un Byte). El método para almacenar los datos es el de archivos; los archivos guardarán la información en formato binario y con un punto por cada tres bytes. La visualización se hará en todos los ángulos posibles pudiendo variarlos 1 cada vez. Además del formato de archivos propuesto (simple) se podrán leer y guardar en formato DXF (AutoCad).
Especificaciones Técnicas:
DEBE ESTAR EN MODO VIDEO 800x600
El programa vis.exe (visualizador tridimensional) se desarrolló en:
El primer archivo es vis.dpr:
program vis;
uses
Forms,
visual in 'visual.pas' {Form1},
carga in 'carga.pas' {Form2},
genera in 'genera.pas' {Form3},
guarda in 'guarda.pas' {Form4};
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
Application.CreateForm(TForm3, Form3);
Application.CreateForm(TForm4, Form4);
Application.Run;
end.
Aquí se define el programa y se nombran a las unidades (formas) que lo conforman.
Cada forma necesita dos archivos: unit.dfm y unit.pas. Los archivos .dfm contienen la definición visual de la forma, los archivos .pas contienen los procedimientos y las declaraciones que se le definen.
Visual (Form1):
unit visual;
{Esta unidad define la ventana principal con su área de dibujo y los
procedimientos respectivos para que el dibujo se traze y se guarden los
datos en la memoria.}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, StdCtrls;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
Archivo1: TMenuItem;
Ejes1: TMenuItem;
Abrir: TMenuItem;
Generar: TMenuItem;
xy1: TMenuItem;
xz1: TMenuItem;
xyz1: TMenuItem;
xzy1: TMenuItem;
yxz1: TMenuItem;
yzx1: TMenuItem;
zxy1: TMenuItem;
zyx1: TMenuItem;
Marco1: TMenuItem;
ScrollBar1: TScrollBar;
yz1: TMenuItem;
Herramientas1: TMenuItem;
Escala1: TMenuItem;
X1: TMenuItem;
Y1: TMenuItem;
Z1: TMenuItem;
Ver1: TMenuItem;
Puntos1: TMenuItem;
Lineas1: TMenuItem;
Polgonos1: TMenuItem;
Guardar: TMenuItem;
Salir: TMenuItem;
procedure AbrirClick(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Marco1Click(Sender: TObject);
procedure xy1Click(Sender: TObject);
procedure xz1Click(Sender: TObject);
procedure yz1Click(Sender: TObject);
procedure xyz1Click(Sender: TObject);
procedure xzy1Click(Sender: TObject);
procedure yxz1Click(Sender: TObject);
procedure yzx1Click(Sender: TObject);
procedure zxy1Click(Sender: TObject);
procedure zyx1Click(Sender: TObject);
procedure Escala1Click(Sender: TObject);
procedure X1Click(Sender: TObject);
procedure Y1Click(Sender: TObject);
procedure Z1Click(Sender: TObject);
procedure Puntos1Click(Sender: TObject);
procedure Lineas1Click(Sender: TObject);
procedure Polgonos1Click(Sender: TObject);
procedure SalirClick(Sender: TObject);
procedure GenerarClick(Sender: TObject);
procedure GuardarClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
{Se define un punto como un registro que tiene cordenadas x,y y z
del tipo real y un a puntador a un registro del mismo tipo.}
lis_punto=^punto;
punto = record
x,y,z: real;
Next: lis_punto;
end;
{Definimos a una coord como un registro con valores x, y y z de tipo
real}
coord = record
x,y,z: real;
end;
{Un universo será un registro que contiene una lista de puntos (coord),
y una variable booleana llamada lleno.}
universo = record
coord: lis_punto;
lleno: Boolean;
end;
var
mundo:universo; {Aquí guardaremos el trazo 3D}
vista:Integer; {Con esta variable identificaremos que vista está activa}
Ver:Char; {Para elegir que se quiere ver: puntos, líneas o polígonos}
R: TRect; {Sobre la ventana se dibujará un rectángulo blanco (para tener
coordenadas sobre las cuales trabajar)}
marc:Boolean; {Con esto sabremos si queremos ver el marco o no}
Form1: TForm1;
implementation
uses {Tenemos que hacer referencia a las otras ventanas ya que serán abiertas
desde aquí}
carga, genera, guarda;
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject); {En cuanto sea creada la ventana...}
begin
Ver:='1'; {Deseo ver el dibujo con nube de puntos}
vista:=1; {Con los ejes xyz (ese orden)}
marc:=False; {Sin ver el marco}
mundo.lleno:=False; {Pero como todavía no se ha cargado nada...}
end;
procedure TForm1.Marco1Click(Sender: TObject); {Opción Marco Ejes}
begin
if marc then
marc:=False
else
marc:=True;
Form1.FormPaint(Sender);
end;
procedure TForm1.xy1Click(Sender: TObject); {Opción xy Ejes}
begin
vista:=7;
marc:=False;
Form1.FormPaint(Sender);
end;
procedure TForm1.xz1Click(Sender: TObject); {Opción xz Ejes}
begin
vista:=8;
marc:=False;
Form1.FormPaint(Sender);
end;
procedure TForm1.yz1Click(Sender: TObject); {Opción yz Ejes}
begin
vista:=9;
marc:=False;
Form1.FormPaint(Sender);
end;
procedure TForm1.xyz1Click(Sender: TObject); {Opción xyz Ejes}
begin
vista:=1;
Form1.FormPaint(Sender);
end;
procedure TForm1.xzy1Click(Sender: TObject); {Opción xzy Ejes}
begin
vista:=2;
Form1.FormPaint(Sender);
end;
procedure TForm1.yxz1Click(Sender: TObject); {Opción yxz Ejes}
begin
vista:=3;
Form1.FormPaint(Sender);
end;
procedure TForm1.yzx1Click(Sender: TObject); {Opción yzx Ejes}
begin
vista:=4;
Form1.FormPaint(Sender);
end;
procedure TForm1.zxy1Click(Sender: TObject); {Opción zxy Ejes}
begin
vista:=5;
Form1.FormPaint(Sender);
end;
procedure TForm1.zyx1Click(Sender: TObject); {Opción zyx Ejes}
begin
vista:=6;
Form1.FormPaint(Sender);
end;
procedure TForm1.Puntos1Click(Sender: TObject); {Opción polígonos puntos}
begin
Ver:='1';
Form1.FormPaint(Sender);
end;
procedure TForm1.Lineas1Click(Sender: TObject); {Opción polígonos líneas}
begin
Ver:='2';
Form1.FormPaint(Sender);
end;
procedure TForm1.Polgonos1Click(Sender: TObject); {Opción polígonos ver}
begin
Ver:='3';
Form1.FormPaint(Sender);
end;
procedure intercambia(eje:char); {Este procedimiento "invierte" los datos
en la memoria respecto al eje que sirve de parámetro}
var
temp: real;
data: lis_punto;
begin
New(data);
data:=mundo.coord;
repeat
if eje='x' then
data^.x:=255-data^.x;
if eje='y' then
data^.y:=255-data^.y;
if eje='z' then
data^.z:=255-data^.z;
data:=data^.next;
until (data^.next=nil);
if eje='x' then
data^.x:=255-data^.x;
if eje='y' then
data^.y:=255-data^.y;
if eje='z' then
data^.z:=255-data^.z;
end;
procedure TForm1.X1Click(Sender: TObject); {Opción x Herramientas}
begin
if mundo.lleno then intercambia('x');{Ve si hay algo que invertir
antes de invertir}
Form1.FormPaint(Sender);
end;
procedure TForm1.Y1Click(Sender: TObject); {Opción y Herramientas}
begin
if mundo.lleno then intercambia('y'); {Ve si hay algo que invertir
antes de invertir}
Form1.FormPaint(Sender);
end;
procedure TForm1.Z1Click(Sender: TObject); {Opción z Herramientas}
begin
if mundo.lleno then intercambia('z'); {Ve si hay algo que invertir
antes de invertir}
Form1.FormPaint(Sender);
end;
procedure escala; {Este procedimiento "escala" los valores que se
encuentran en la memoria para que el dibujo pueda ser apreciado en la
pantalla.}
var
xmin,ymin,zmin,xmax,ymax,zmax:real;
data,datos: lis_punto;
begin
New(data);
data:=mundo.coord;
xmin:=0; ymin:=0; zmin:=0;
xmax:=0; ymax:=0; zmax:=0;
repeat
if data^.x<xmin then xmin:=data^.x;
if data^.y<ymin then ymin:=data^.y;
if data^.z<zmin then zmin:=data^.z;
if data^.x>xmax then xmax:=data^.x;
if data^.y>ymax then ymax:=data^.y;
if data^.z>zmax then zmax:=data^.z;
data:=data^.next;
until (data^.next=nil);
if data^.x<xmin then xmin:=data^.x;
if data^.y<ymin then ymin:=data^.y;
if data^.z<zmin then zmin:=data^.z;
if data^.x>xmax then xmax:=data^.x;
if data^.y>ymax then ymax:=data^.y;
if data^.z>zmax then zmax:=data^.z;
New(data);
data:=mundo.coord;
repeat
data^.x:=255*(-xmin+data^.x)/(-xmin+xmax);
data^.y:=255*(-ymin+data^.y)/(-ymin+ymax);
data^.z:=255*(-zmin+data^.z)/(-zmin+zmax);
data:=data^.next;
until (data^.next=nil);
data^.x:=255*(-xmin+data^.x)/(-xmin+xmax);
data^.y:=255*(-ymin+data^.y)/(-ymin+ymax);
data^.z:=255*(-zmin+data^.z)/(-zmin+zmax);
end;
procedure TForm1.Escala1Click(Sender: TObject); {Opción Escala Herramientas}
begin
if mundo.lleno then escala; {Ve si hay algo que escalar
antes de escalar}
Form1.FormPaint(Sender);
end;
procedure TForm1.SalirClick(Sender: TObject); {Opción salir del menú Archivo}
begin
close;
end;
procedure TForm1.AbrirClick(Sender: TObject); {Opción abrir del menú Archivo}
begin
carga.Form2.ShowModal;
end;
procedure TForm1.GenerarClick(Sender: TObject); {Opción generar del menú Archivo}
begin
genera.Form3.ShowModal;
end;
procedure TForm1.GuardarClick(Sender: TObject); {Opción guardar del menú Archivo}
begin
guarda.Form4.ShowModal;
end;
procedure TForm1.FormPaint(Sender: TObject); {Este procedimiento se activa
cada vez que se vuelva a pintar la ventana; ya sea porque la ventana se mueve,
se re-escale o porque se mande llamar desde dentro del programa.}
procedure marco(Anrc,Anrs:Real); {Dibuja el marco en la ventana}
var
X2,Y2,X3,Y3:integer;
begin
X2:=Round(R.Right/(1+Anrc));
Y2:=Round(R.Bottom/(1+Anrs));
X3:=Round(X2*Anrc);
Y3:=Round(Y2*Anrs);
Canvas.Pen.Color := clBlue;
Canvas.PolyLine([Point(X2,0), Point(X2,Y2)]);
Canvas.PolyLine([Point(0,Y2), Point(X2,Y2)]);
Canvas.PolyLine([Point(X2,Y2), Point(R.Right,R.Bottom)]);
Canvas.PolyLine([Point(X3,Y3), Point(R.Right,Y3)]);
Canvas.PolyLine([Point(X3,Y3), Point(X3,R.Bottom)]);
Canvas.PolyLine([Point(0,Y2), Point(X3,R.Bottom)]);
Canvas.PolyLine([Point(0,0), Point(X3,Y3)]);
Canvas.PolyLine([Point(X2,0), Point(R.Right,Y3)]);
Canvas.Pen.Color := clBlack;
end;
procedure pon(Anrc,Anrs,x1,y1,z1,x2,y2,z2,x3,y3,z3:real); {Hace el dibujo
3D en la pantalla, se le pasan 11 datos (un triángulo y el seno y el coseno
de un triángulo).}
var
Xp1,Yp1,Xp2,Yp2,Xp3,Yp3:Integer;
begin
Xp1:=Round(R.Right*((x1/255)+(z1/255)*Anrc)/(1+Anrc));
Yp1:=Round(R.Bottom*((y1/255)+(z1/255)*Anrs)/(1+Anrs));
Xp2:=Round(R.Right*((x2/255)+(z2/255)*Anrc)/(1+Anrc));
Yp2:=Round(R.Bottom*((y2/255)+(z2/255)*Anrs)/(1+Anrs));
Xp3:=Round(R.Right*((x3/255)+(z3/255)*Anrc)/(1+Anrc));
Yp3:=Round(R.Bottom*((y3/255)+(z3/255)*Anrs)/(1+Anrs));
{Esto lo rescala a un cubo de 0 a 255 pixeles y lo "aplana" usando el
seno y el coseno del triángulo.}
case Ver of
'1': begin
Canvas.Pixels[Xp1,Yp1]:=clBlack;
Canvas.Pixels[Xp2,Yp2]:=clBlack;
Canvas.Pixels[Xp3,Yp3]:=clBlack;
end;
'2': Canvas.Polyline([Point(Xp1, Yp1), Point(Xp2, Yp2), Point(Xp3, Yp3), Point(Xp1, Yp1)]);
'3': Canvas.Polygon([Point(Xp1, Yp1), Point(Xp2, Yp2), Point(Xp3, Yp3)]);
{Se hace el trazo ya sea con puntos, líneas o triángulos.}
end;
end;
procedure dib; {Este procedimiento hace el trazo}
var
Anrc,Anrs:Real;
data:lis_punto;
x1,y1,z1,x2,y2,z2,x3,y3,z3:real;
begin
Anrc:=cos(ScrollBar1.Position*3.141592/180); {"Lee" el ángulo de vista}
Anrs:=sin(ScrollBar1.Position*3.141592/180); {del scrollbar}
New(data);
data:=mundo.coord;
repeat
data:=data^.next;
x1:=data^.x;
y1:=data^.y;
z1:=data^.z;
data:=data^.next;
x2:=data^.x;
y2:=data^.y;
z2:=data^.z;
data:=data^.next;
if (data^.next<>nil) then
begin
x3:=data^.x;
y3:=data^.y;
z3:=data^.z;
case vista of
1:pon(Anrc,Anrs,x1,y1,z1,x2,y2,z2,x3,y3,z3);
2:pon(Anrc,Anrs,x1,z1,y1,x2,z2,y2,x3,z3,y3);
3:pon(Anrc,Anrs,y1,x1,z1,y2,x2,z2,y3,x3,z3);
4:pon(Anrc,Anrs,y1,z1,x1,y2,z2,x2,y3,z3,x3);
5:pon(Anrc,Anrs,z1,x1,y1,z2,x2,y2,z3,x3,y3);
6:pon(Anrc,Anrs,z1,y1,x1,z2,y2,x2,z3,y3,x3);
7:pon(0,0,x1,y1,0,x2,y2,0,x3,y3,0);
8:pon(0,0,x1,z1,0,x2,z2,0,x3,z3,0);
9:pon(0,0,y1,z1,0,y2,z2,0,y3,z3,0);
end;
end;
until (data^.next=nil);
x3:=data^.x;
y3:=data^.y;
z3:=data^.z;
case vista of
1:pon(Anrc,Anrs,x1,y1,z1,x2,y2,z2,x3,y3,z3);
2:pon(Anrc,Anrs,x1,z1,y1,x2,z2,y2,x3,z3,y3);
3:pon(Anrc,Anrs,y1,x1,z1,y2,x2,z2,y3,x3,z3);
4:pon(Anrc,Anrs,y1,z1,x1,y2,z2,x2,y3,z3,x3);
5:pon(Anrc,Anrs,z1,x1,y1,z2,x2,y2,z3,x3,y3);
6:pon(Anrc,Anrs,z1,y1,x1,z2,y2,x2,z3,y3,x3);
7:pon(0,0,x1,y1,0,x2,y2,0,x3,y3,0);
8:pon(0,0,x1,z1,0,x2,z2,0,x3,z3,0);
9:pon(0,0,y1,z1,0,y2,z2,0,y3,z3,0);
end;
if marc then marco(Anrc,Anrs); {Si se necesita visualizar el marco,
lo visualiza}
end;
begin
R := GetClientRect; {Obtén las dimensiones de la ventana}
Canvas.Rectangle(R.Left,R.Top,R.Right,R.Bottom); {Haz un rectángulo
que ocupe toda la ventana}
If mundo.lleno Then {Si hay algo en la memoria, dibújalo}
dib;
end;
end.
Carga (Form2):
unit carga; {Esta unidad (y su ventana) sirven para cargar en memoria
un archivo para ser visualizado}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
FileCtrl, StdCtrls;
type
TForm2 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Button2: TButton;
DriveComboBox1: TDriveComboBox;
DirectoryListBox1: TDirectoryListBox;
FilterComboBox1: TFilterComboBox;
FileListBox1: TFileListBox;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
uses
visual; {Se necesita la unidad visual (para tener acceso a las
variables globales)}
{$R *.DFM}
procedure lee_dxf(nombre:String); {Lee el formato DXF de AutoCad, se le
pasa el nombre del archivo a leer}
var
archivo: Text; {Los archivos DXF son de tipo texto}
dato1, dato2, dato3: real;
data: lis_punto;
temp: string;
cont: Integer;
procedure AgregaDat(x,y,z:real); {Este procedimiento anexa un dato a la
lista data}
var
dato: lis_punto;
begin
new(dato);
data^.Next:=dato;
dato^.x:=x;
dato^.y:=y;
dato^.z:=z;
dato^.Next:=nil;
data:=dato;
end;
Function busca(bandera:string):String; {Este procedimiento busca una
"bandera" dentro del archivo DXF y regresa el contenido de la línea
siguiente}
var
temp:string;
begin
While (NOT(EOF(Archivo))AND(Not(temp=bandera))) DO
readln(archivo,temp);
readln(archivo,temp);
busca:=temp;
end;
begin
Assign(archivo,nombre);
Reset(archivo); {Asocia el nombre del archivo y abrelo para lectura}
New(data); {Prepara el listado de puntos}
data^.x:=0;
data^.y:=0;
data^.z:=0;
mundo.coord:=data; {Ancla el principio de la lista}
temp:='';
cont:=-2;
While Not(EOF(archivo)) DO
BEGIN
temp:=busca('3DFACE'); {Principio de definición de un triángulo}
if ((Not(EOF(archivo)))AND(temp<>'EOF')) then
begin
cont:=cont+3;
temp:=busca('10'); {x del 1 punto}
dato1:=StrToFloat(temp);
temp:=busca('20'); {y del 1 punto}
dato2:=StrToFloat(temp);
temp:=busca('30'); {z del 1 punto}
dato3:=StrToFloat(temp);
AgregaDat(dato1,dato2,dato3); {Agrega estos datos a la lista}
temp:=busca('11');
dato1:=StrToFloat(temp);
temp:=busca('21');
dato2:=StrToFloat(temp);
temp:=busca('31');
dato3:=StrToFloat(temp);
AgregaDat(dato1,dato2,dato3);
temp:=busca('12');
dato1:=StrToFloat(temp);
temp:=busca('22');
dato2:=StrToFloat(temp);
temp:=busca('32');
dato3:=StrToFloat(temp);
AgregaDat(dato1,dato2,dato3);
end;
END;
CloseFile(archivo); {Cierra el archivo}
end;
procedure lee_sim(nombre:String);
var
archivo:File of char; {Los archivos "simple" son de caracteres}
dato1, dato2, dato3: char;
data: lis_punto;
cont: Integer;
procedure AgregaDat(x,y,z:char); {Este procedimiento anexa un dato a la
lista data}
var
dato: lis_punto;
begin
new(dato);
data^.Next:=dato;
dato^.x:=ord(x);
dato^.y:=ord(y);
dato^.z:=ord(z);
dato^.Next:=nil;
data:=dato;
end;
begin
Assign(archivo,nombre);
Reset(archivo);
New(data);
data^.x:=0;
data^.y:=0;
data^.z:=0;
mundo.coord:=data;
cont:=-2;
While Not(EOF(archivo)) DO
BEGIN
Read(archivo,dato1);
If Not(EOF(archivo)) THEN
BEGIN
Read(archivo,dato2);
If Not(EOF(archivo)) THEN
Begin
Read(archivo,dato3);
cont:=cont+3;
AgregaDat(dato1,dato2,dato3); {Se leen 3 bytes seguidos,
cada uno de 0 a 255 es una coordenada de un punto}
END
ELSE
MessageDlg('Número de datos Incorrectos', mtInformation,[mbOk], 0);
END
ELSE
MessageDlg('Número de datos Incorrectos', mtInformation,[mbOk], 0);
END;
CloseFile(archivo);
end;
procedure TForm2.Button1Click(Sender: TObject); {Si se oprime el botón OK}
var
FileExt: string[4];
FilePath:string;
begin
FileExt := UpperCase(ExtractFileExt(Edit1.Text)); {Determina la extensión}
FilePath := ExtractFileDir(FileListBox1.Filename); {Lee el Path}
if (FileExt = '') then
BEGIN
lee_sim(FilePath+'\'+Edit1.Text); {Se lee con el formato simple}
mundo.lleno:=True;
END;
if (FileExt = '.DXF') then
BEGIN
lee_dxf(Edit1.Text); {Se lee con el formato DXF}
mundo.lleno:=True;
END;
close;
end;
procedure TForm2.Button2Click(Sender: TObject); {Si se oprime el botón Cancelar}
begin
close;
end;
end.
Genera (Form3):
unit genera; {Este procedimiento "genera" archivos "simples" de prueba}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
FileCtrl, StdCtrls;
type
TForm3 = class(TForm)
Listado: TButton;
arch_nom: TEdit;
Calculado: TButton;
Cancelar: TButton;
Label1: TLabel;
procedure ListadoClick(Sender: TObject);
procedure CalculadoClick(Sender: TObject);
procedure CancelarClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
{$R *.DFM}
procedure crea_lis(nombre:String); {Crea un archivo con los datos listados}
var
archivo: file of char;
c: array [1..29] of char;
cont : Integer;
begin
c[1]:=char(4);
c[2]:=char(0);
c[3]:=char(167);
c[4]:=char(12);
c[5]:=char(0);
c[6]:=char(168);
c[7]:=char(14);
c[8]:=char(0);
c[9]:=char(170);
c[10]:=char(14);
c[11]:=char(0);
c[12]:=char(227);
c[13]:=char(12);
c[14]:=char(0);
c[15]:=char(228);
c[16]:=char(4);
c[17]:=char(0);
c[18]:=char(229);
c[19]:=char(4);
c[20]:=char(0);
c[21]:=char(233);
c[22]:=char(28);
c[23]:=char(0);
c[24]:=char(233);
c[25]:=char(28);
c[26]:=char(0);
c[27]:=char(230);
c[28]:=char(71);
c[29]:=char(67);
Assign(archivo,nombre);
Rewrite(archivo);
for cont:=1 to 29 do
Write(archivo,c[cont]);
CloseFile(archivo);
end;
procedure crea_cal(nombre:String); {Crea un archivo con los datos calculados}
var
archivo: file of char;
x,y,z : Integer;
begin
Assign(archivo,nombre);
Rewrite(archivo);
for x:=1 to 255 do
begin
y:=round(127+127*cos(2*2*3.1415*(1-x/255))); {Círculos...}
z:=round(127+127*sin(4*2*3.1415*(1-x/255))); {+ círculos}
Write(archivo,char(x));
Write(archivo,char(y));
Write(archivo,char(z));
end;
CloseFile(archivo);
end;
procedure TForm3.ListadoClick(Sender: TObject);
begin
crea_lis(arch_nom.Text);
close;
end;
procedure TForm3.CalculadoClick(Sender: TObject);
begin
crea_cal(arch_nom.Text);
close;
end;
procedure TForm3.CancelarClick(Sender: TObject);
begin
close;
end;
end.
Guarda (Form4):
unit guarda; {Este procedimiento guarda los datos en memoria, sólo en
formato simple}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
FileCtrl, StdCtrls;
type
TForm4 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Button2: TButton;
DriveComboBox1: TDriveComboBox;
DirectoryListBox1: TDirectoryListBox;
FilterComboBox1: TFilterComboBox;
FileListBox1: TFileListBox;
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form4: TForm4;
implementation
uses
visual;
{$R *.DFM}
procedure esc_sim(nombre:String);
var
archivo:File of char;
data: lis_punto;
x,y,z: integer;
begin
New(data);
data:=mundo.coord;
Assign(archivo,nombre);
Rewrite(archivo);
repeat
data:=data^.next;
x:=round(data^.x);
y:=round(data^.y);
z:=round(data^.z);
Write(archivo,char(x));
Write(archivo,char(y));
Write(archivo,char(z));
until (data^.next=nil);
CloseFile(archivo);
end;
procedure esc_dxf(nombre:String);
var
archivo:Text; {Los archivos DXF son de tipo texto}
data: lis_punto;
x,y,z: real;
begin
New(data);
data:=mundo.coord;
Assign(archivo,nombre);
Rewrite(archivo);
writeln(archivo,'0');
writeln(archivo,'SECTION');
writeln(archivo,'2');
writeln(archivo,'HEADER');
writeln(archivo,'0');
writeln(archivo,'ENDSEC');
writeln(archivo,'0');
writeln(archivo,'SECTION');
writeln(archivo,'2');
writeln(archivo,'ENTITIES');
repeat
data:=data^.next;
x:=data^.x;
y:=data^.y;
z:=data^.z;
writeln(archivo,'0');
writeln(archivo,'3DFACE');
writeln(archivo,'8');
writeln(archivo,'Default');
writeln(archivo,'62');
writeln(archivo,'254');
writeln(archivo,'10');
Writeln(archivo,x);
writeln(archivo,'20');
Writeln(archivo,y);
writeln(archivo,'30');
Writeln(archivo,z);
data:=data^.next;
x:=data^.x;
y:=data^.y;
z:=data^.z;
writeln(archivo,'11');
Writeln(archivo,x);
writeln(archivo,'21');
Writeln(archivo,y);
writeln(archivo,'31');
Writeln(archivo,z);
data:=data^.next;
x:=data^.x;
y:=data^.y;
z:=data^.z;
writeln(archivo,'12');
Writeln(archivo,x);
writeln(archivo,'22');
Writeln(archivo,y);
writeln(archivo,'32');
Writeln(archivo,z);
writeln(archivo,'13');
Writeln(archivo,x);
writeln(archivo,'23');
Writeln(archivo,y);
writeln(archivo,'33');
Writeln(archivo,z);
until (data^.next=nil);
writeln(archivo,'0');
writeln(archivo,'ENDSEC');
writeln(archivo,'0');
writeln(archivo,'EOF');
CloseFile(archivo);
end;
procedure TForm4.Button2Click(Sender: TObject);
begin
close;
end;
procedure TForm4.Button1Click(Sender: TObject);
var
FileExt: string[4];
FilePath:string;
begin
if mundo.lleno then
begin
FileExt := UpperCase(ExtractFileExt(Edit1.Text));
FilePath := ExtractFileDir(FileListBox1.Filename);
if (FileExt = '') then
esc_sim(FilePath+'\'+Edit1.Text)
else if (FileExt = '.DXF') then
esc_dxf(Edit1.Text)
else showmessage('Formato desconocido.');
end
else
showmessage('No hay nada que guardar');
close;
end;
end.