Вывести на экран изображение поверхности z=f(x,y) с удалением невидимых линий с использованием алгоритма плавающего горизонта
Добавил: | DMT |
Дата создания: | 4 декабря 2007, 3:15 |
Дата обновления: | 4 декабря 2007, 3:15 |
Просмотров: | 5984 последний 24 ноября, 23:37 |
Комментариев: | 0 |
Удаление невидимых линий осуществляется с использованием алгоритма плавающего горизонта. Рассматривается параллельная проекция. Поверхность задается одной формулой: Z=x*y/(x^2+y^2+1).
Исходный текст программы на языке C Builder: //--------------------------------------------------------------------------- #include <vcl.h>#include <math.h>#pragma hdrstop#include "Unit1.h"//--------------------------------------------------------------------------- #pragma package(smart_init)#pragma resource "*.dfm"TForm1 *Form1; #define nx 60#define ny 60float xmax = 3, xmin = -3, ymax = 3, ymin = -3, zmax = 3, zmin = -2;float xv = 5, yv = 3.5 , zv = 3 ; // положение наблюдателяfloat d = 10 ; // расстояние до плоскости проекцииfloat cosa, sina ; // меридиана точки наблюденияfloat exmax, exmin, eymax, eymin ;int gmex, gmey ;int fimin[640], fimax[640] ;float cvals[ny+1], cval ;void sline( int X0, int Y0, int X1, int Y1 ){ int i, n;float x, y, dx=0, dy=0;n = abs(X1-X0); if (n< abs(Y1-Y0) ) n = abs(Y1-Y0);if (n>0) {dx=(0.+X1-X0)/n; dy=(0.+Y1-Y0)/n;}x=X0; y=Y0; if (dx>0) x+=0.5; else if (dx<0) x-=0.5;if (dy>0) y+=0.5; else if (dy<0) y-=0.5;for (i=0;i<=n;i++){ if (y>fimax[(int)x]) fimax[(int)x]=y; // Изменяем верхний горизонт if (y<fimin[(int)x]) fimin[(int)x]=y; // Изменяем нижний горизонтx+=dx; y+=dy; } } // Вывод видимой части отрезка void vectsec( int X0, int Y0, int X1, int Y1 ){ int begx, begy, endx, endy, i;sline(X0, Y0, X1, Y1); begx=X0; begy=Y0; endx=X1; endy=Y1; if (begx>X1) {begx=X1; begy=Y1; endx=X0; endy=Y0;}Form1->Canvas->MoveTo( begx, gmey-fimax[begx]); for (i=begx;i<endx;i++) Form1->Canvas->LineTo(i, gmey-fimax[i]);Form1->Canvas->MoveTo(begx, gmey-fimin[begx]); for (i=begx;i<endx;i++) Form1->Canvas->LineTo(i, gmey-fimin[i]);} /* x'=-d(r-r0) u1 / ((r-r0) u - d); y'=-d(r-r0) u2 / ((r-r0) u - d); z'=- =d/((r-r0) u - d). float fz(float x, float y) {return (x*y/(x*x+y*y+1));} // Центральная проекция // x координата на плоскости проекциии float ex(float x, float y, float z) {return (-d*(-(x-xv)*sina+(y-yv)*cosa))/((x-xv)*cosa+(y-yv)*sina);} // y координата на плоскости проекции float ey(float x, float y, float z ) {return (-d*(z-zv))/((x-xv)*cosa+(y-yv)*sina);} */ float fz(float x, float y) {return (x*y/(x*x+y*y+1));}// Центральная проекция // x координата на плоскости проекциии float ex(float x, float y, float z){ return (-d*(-(x-xv)*sina+(y-yv)*cosa))/((x-xv)*cosa+(y-yv)*sina);}// y координата на плоскости проекции float ey(float x, float y, float z ){ return (-d*(z-zv))/((x-xv)*cosa+(y-yv)*sina);}// Вычисление экранных координат void vectfi(float x0, float y0, float z0, float x1, float y1, float z1,int mm){ float ex0, ex1, ey0, ey1; int ix0, ix1, iy0, iy1;ex0=ex(x0,y0,z0); ix0=(ex0-exmin)*gmex/(exmax-exmin); ey0=ey(x0,y0,z0); iy0=(ey0-eymin)*gmey/(eymax-eymin); ex1=ex(x1,y1,z1); ix1=(ex1-exmin)*gmex/(exmax-exmin); ey1=ey(x1,y1,z1); iy1=(ey1-eymin)*gmey/(eymax-eymin); // Если mm не равно нулю, то выводим // изображение с удалением невидимых линий, // иначе - без удаления невидимых линий if (mm) vectsec(ix0,iy0,ix1,iy1); else {Form1->Canvas->MoveTo(ix0,gmey-iy0); Form1->Canvas->LineTo(ix1,gmey-iy1); } }
//--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::FormClick(TObject *Sender){ int i, j;float x,y,hx,hy;Form1->Canvas->Pen->Color=clWhite; Form1->Canvas->Brush->Color=clWhite; Form1->Canvas->Rectangle(0,0,Form1->ClientWidth,Form1->ClientHeight); Form1->Canvas->Pen->Color=clBlack; hy=(ymax-ymin)/ny; hx=(xmax-xmin)/nx; gmex=Form1->ClientWidth; gmey=Form1->ClientHeight; cosa=xv/sqrt(xv*xv+yv*yv); sina=yv/sqrt(xv*xv+yv*yv ); for (i=0;i<gmex;i++) {fimax[i]=0; fimin[i]=gmey;}exmax=ex(xmin, ymax, zmax); exmin=ex(xmax, ymin, zmin); eymax=ey(xmin, ymin, zmax); eymin=ey(xmax, ymax, zmin); // Заполнение первой строки cval=fz(xmax, ymax); for (i=ny-1;i>=0;i--){ cvals[i+1]=cval; y=ymin+hy*i; cval=fz(xmax, y); vectfi(xmax, y+hy, cvals[i+1], xmax, y, cval, 1); } cvals[0] = cval ; // Заполнение остальных строк for (j=nx-1;j>=0;j--){ x=xmin+hx*j; cval=fz(x, ymax); vectfi(x+hx, ymax, cvals[ny], x,ymax,cval, 1); for(i=ny-1;i>=0;i--){ cvals[i+1]=cval; y=ymin+hy*i; cval=fz(x, y); vectfi(x, y+hy, cvals[i+1], x, y, cval, 1); vectfi(x+hx, y, cvals[i], x, y, cval, 1); } cvals[0] = cval ; } // Изображение объемлющего параллелепипеда vectfi(xmax, ymax, zmax, xmin, ymax, zmax, 0); vectfi(xmax, ymax, zmax, xmax, ymax, zmin, 0); vectfi(xmax, ymax, zmax, xmax, ymin, zmax, 0); vectfi(xmin, ymax, zmin, xmin, ymax, zmax, 0); vectfi(xmin, ymax, zmin, xmax, ymax, zmin, 0); vectfi(xmax, ymin, zmin, xmax, ymin, zmax, 0); vectfi(xmax, ymin, zmin, xmax, ymax, zmin, 0); vectfi(xmin, ymin, zmin, xmin, ymin, zmax, 1); vectfi(xmin, ymin, zmin, xmax, ymin, zmin, 1); vectfi(xmin, ymin, zmin, xmin, ymax, zmin, 1); vectfi(xmax, ymin, zmax, xmin, ymin, zmax, 1); vectfi(xmin, ymax, zmax, xmin, ymin, zmax, 1); } //--------------------------------------------------------------------------- |
