PDA

View Full Version : Vẽ mặt cong bậc 2 trong Pascal



darkknight144
14-12-2007, 09:31
Mình cần vẽ mặt cong bậc 2 cụ thể la paraboloic va hyperpoloic trong pascal mà chưa tìm ra tài liệu. Bạn nao bít vẽ thì giúp mình với.Nếu đc hãy liên lạc wa email với mình darkknight14487@yahoo.fr

bete
14-12-2007, 10:38
Bạn ơi,

Đây là bài tập của bạn hay sao ?

-thân

Long_Phung
14-12-2007, 11:07
Bạn tìm cuốn "Cấu trúc dữ liệu và giải thuật" Trong đó có vẽ đồ thị. Lâu rồi không làm mình quên mất code rồi..

mr_invincible
14-12-2007, 21:30
Có lẽ cách duy nhất là nếu bạn muốn vẽ đồ thị các hàm số y=f(x) thì cho x chạy lần lượt các giá trị (trong màn hình) rồi tính y, rồi nối các điểm y lại với nhau

darkknight144
14-12-2007, 23:37
Có lẽ cách duy nhất là nếu bạn muốn vẽ đồ thị các hàm số y=f(x) thì cho x chạy lần lượt các giá trị (trong màn hình) rồi tính y, rồi nối các điểm y lại với nhau

Nếu chỉ vẽ đg thì đơn giản wá rồi.Code thì khó lắm , mình chỉ hỏi coi có ai thấy tài liệu hướng dẫn thì chỉ mình.

jiSh@n
14-12-2007, 23:46
Vẽ đồ thị hàm số f(x,y,z) trong ko gian không đơn giản như y=f(x) trong mặt phẳng. Phải tính được cái giá trị của x,y,z rồi chuyển tọa độ (x,y,z) từ không gian 3 chiều sang hệ tọa độ phẳng (X,Y) của màn hình nữa.

bete
15-12-2007, 06:23
Vẽ đồ thị hàm số f(x,y,z) trong ko gian không đơn giản như y=f(x) trong mặt phẳng. Phải tính được cái giá trị của x,y,z rồi chuyển tọa độ (x,y,z) từ không gian 3 chiều sang hệ tọa độ phẳng (X,Y) của màn hình nữa
=> và để cho dễ nhìn thì mình có thể phải che khuất đi 1 số các mảnh con nữa

Tui nhớ không lầm thì bạn whitepenguin đã có thử qua (và chắc chắn có nhiều bạn khác đã thử qua rồi)
Nếu bạn whitepenguine không trả lời kịp cho bạn thì tui sẽ thử viết xuống 1 vài thứ cần thiết (để đổi tọa độ và che khuất các mảnh con)

(hiểu biết nông cạn; có gì sai sót mong được góp ý; xin cám ơn)

-thân

darkknight144
16-12-2007, 00:54
nếu đc thì viết nhanh giúp mình nha

jiSh@n
16-12-2007, 00:58
Đồ họa 3D ko đơn giản như 2D, tính toán phức tạp hơn và đòi hỏi bạn phải có kiến thức vững về lĩnh vực này.

bete
16-12-2007, 05:39
Nếu bạn đã học qua hình giải tích rồi thì sẽ dễ hiểu các công thức hơn
Tui có 1 đoạn code cũ:

Giả sử:

- hệ tọa độ thực cho vật:
++ trục x: hướng từ xa lại gần
++ trục y: hướng từ trái qua phải:
++ trục z: hướng từ dưới lên trên

- vị trí của mắt:
++ đặt ở (xEye, yEye, zEye)
++ khoảng cách từ mắt tới gốc của tọa độ thực: eDist
++ mắt tạo với mặt phẳng (x,y) 1 góc là alpha: sin(alpha) = sinHoriz; cos(alpha) = cosHoriz
++ mắt tạo với mặt phẳng (z,y) 1 góc là beta: sin(beta) = sinVert; cos(alpha) = cosVert

Khởi tạo:
eDist = ....
cosHoriz = .....
sinHoriz = .....
cosVert = .....
sinVert = .....
xTran := getmaxx div 2;
yTran := getmaxy div 2;
xScale := getmaxx div round(maxX-minX);
yScale := getmaxy div round(maxY-minY);

Khi đó: 1 điểm (x3D,y3D,z3D) trong không gian 3D sẽ ứng với 1 điểm (x2D,y2D) trên màn hình:

intermidX := x3D*cosHoriz + y3D*sinHoriz;
finalX := intermidX*cosVert + z3D*sinVert;
fact := eDist/(eDist-finalX);
x2D := round((-x3D*sinHoriz + y3D*cosHoriz)*fact*xScale + xTran);
y2D := round((intermidX*sinVert - z3D*cosVert)*fact*yScale + yTran);

(bạn có thể thử vẽ 1 hình hộp vuông có các đỉnh ở (-1,-1,-1), (-1,-1,1),...,(1,1,1); chọn eDist = 10 hay 20 gì đó; alpha = beta = 45 độ;

Nếu bạn vẽ hết 12 cạnh của hình hộp thì sẽ hơi khó nhìn
=> cần vẽ chỉ 3 mặt và che khuất 3 mặt còn lại

Cách che khuất dễ nhứt (nhưng chậm) là bạn:
- vẽ 1 mặt bằng cách tô màu
- vẽ các mặt theo thứ tự:
++ nếu xEye là dương thì vẽ theo tọa độ x tăng dần; ngược lại thì vẽ theo tọa độ x giảm dần
++ nếu yEye là dương thì vẽ theo tọa độ y tăng dần; ngược lại thì vẽ theo tọa độ y giảm dần
++ nếu zEye là dương thì vẽ theo tọa độ z tăng dần; ngược lại thì vẽ theo tọa độ z giảm dần
)

(hiểu biết nông cạn; có gì sai sót mong được góp ý; xin cám ơn)

-thân

whitepenguin
18-12-2007, 05:19
Anh muốn biểu diễn mặt trong 3D cần 2 chuyện
-Dữ liệu về mặt cần được sản sinh ;dó là các tọa độ (X,Y,Z)
-Dùng Các phương pháp chuyển đổi để XEM dữ liệu này

Nhắc lại về công thức mặt Parabolic

X^2/a+Y^2/b=2*z; (Công thức 1)

:D Cần đọc lại các kiến thức về đường CONIC là 1 và cái PARABOLIC này là 2

Em nói sơ này ,Cái mà em sấp vẽ ra nó là 1 PARABOLIC mà nhận 0,0,0 làm đáy, mở rộng theo chiều dương của z. Vì anh yêu cầu vẽ Parabolic anh phải tìm hiểu rõ về nó thì anh mới đặt câu hỏi lên diễn đàn làm sao để vẽ nó 3D. Em không phân tích sâu vào Parabolic nó có gì và thành phần gì tính chất ra làm sao ,em chĩ hướng dẫn anh cách sản sinh dữ liệu và vẽ 3D thôi ,đó là Yêu cầu Topic Anh đặt ra :D .

Thứ nhất ta sảnh sinh dự liệu cho tọa độ Z
Việc đầu tiên cần là xem xem ta cần vẽ Parabolic cao tới đâu , em thì em cho 120.0 . Máy tính không nên làm cái việc là lặp từ 0--> 120 bằng số nguyên rồi gán cho tọa độ Z--> ta có 120 tọa độ Z :D
Không làm như vậy ! Em chĩ cần 12 độ Z nằm trong 0-> 120.0 thôi
Ta lấy 120.0/Slice với slice =12 ta có 1 khúc là 10.0
Cho Z=0 lặp 12 lần để láy 12 tọa độ từ 0->120
Eg. Z=0 ,Z=10.0 Z=20.0 Z=30.0 .....

Mỗi 1 tọa độ Z ta sẽ dùng nó làm thông số để sản sinh tọa độ X và Y
Biểu Diễn Ellipse khi có Z;
X^2/a+Y^2/b=2*Z ---> X^2/(a*2*Z)+Y^2/(b*2*Z)=1 ---> Công thức Ellipse này là dành cho người xài thôi :D ,còn máy tính thì mình Convert nó qua phương trình tham số

Gọi A và B lần lượt là bán kính của truc x và trục Y trong mặt X0Y
Trong máy tính ta biểu diễn công thức Ellipse như sau
X=A*Cos(t);
Y=B*Sin(t);
Công thức này do ta suy ra khi ta học tọa độ Polar :D

bay giờ cái Crucial Part nằm chỗ này nè t là giá trị Radian
Mình phải quay t từ 0--> 2PI; tương tự mình phải chặt nó ra lam khúc
2PI/Slice ,với Slice là 12 luôn đi cho nó tiện :D
1 khúc là 360/12=30 độ = 2PI/12=PI/6;
Cho vòng lặp 12 lần mỗi 1 lần sinh ra 1 t
Có t ta đem nó vô công thức "Dành cho máy tính" :D và suy ra X Và Y ,với công thức parabolic(1) như trên thì X,Y tạo thành Ellipse luôn có tâm là 0,0

Vậy ta cần 13*13 điểm trong 3D để thể hiện cái Parabolic này
12 lần chặt theo chiều cao ,12 lần chặt theo kiểu xoay tròn ,giống như là chia bánh --> 13*13 điểm;
Khi 13*13 điểm này được vẽ ra thì nó sẽ tạo thành 1 cái Parabolic
Em thể hiện trong C/C++ tại vì trong PASCAL lâu quá rồi em lười xem lại lắm
C cũng hơi giống trong PASCAL ,nếu anh không biết thì nhờ ai đó Convert lại cho anh


struct Point
{
float x,y,z;
};

Point Data[13*13] ; // dữ liệu kiểu Point gồm 13*13 Points


**************************************************
Việc thứ 2 là Vẽ 3D , Cái này cần kiến thức chuyên môn nè :D
Các tọa độ trên là tọa độ Real World , mình cần phải chuyển nó thành tọa độ của mắt (EYES Coordinate)

Cần thành lập 1 Camera để xem trong 3D. Camera có tọa độ (x,y,z) và hướng nhìn. Giống như là anh cầm Camera lên thì anh đã xác định là nó ở vị trí nào ,Còn việc anh quay cái gì thì nó là hướng .VD nhấc camera lên ,muốn quay cái TV thì phải quay camera về hướng cái TV thì mới tháy nó .
Việc chuyễn đổi này anh cần xem lại về toán Đại Số Tuyến tính

[CODE]

struct Vector
{
float x,y,z;
};

struct Camera
{
Point Pos; // Vị trí
Vector Up,Right,View; //Hướng
};

Em dùng tọa độ bàn tay trái Cho Camera ( Left Handed Coord), vì nhiều người thích xài tay trái lắm vì nó tính vector View không có ngược.( của mấy ông DirectX đấy :D) ,em thương dùng tay phải hơn . Anh yên tâm là Demo của em viết cho nền DOS nên anh không cần lo tới mấy cái DirectX hay OpenGL gì hết.

Thành lập Camera:
Ví dụ Em Cho camera đứng ở vị trí 200,200,100
Camera sẽ Dòm vào điểm 0,0,0 chằng hạn
Point Pos=0-200,0-200,0-100;
Vector View là 0-200,0-200,0-100;
Vector Up em cho là 0,0,1;
Vector Right sẽ là View(x)Up ; (x) là tích có hướng
Chỉnh lại Vector Up --> Up=Right(x)View;
Sau đó mình sẽ lấy Vector đơn vị cho những cái Vector này



Camera của ta sẽ có 3 vector Vuông góc với nhau tạo thành 1 hệ Basis



Muốn cho Real World Point thành View Point chỉ việc lấy Point + cho Vector Pos sau đó nhân Điểm vừa tìm với các Vector của camera, nó y chang tích vô hướng thôi ,Xv,Yv,Zv là điểm sau khi đã + với vector View

Xv=X*Right.x+Y*Right.y+Z*Right.z;
Yv=X*Up.x+Y*Up.y+Z*Up.z;
Zv=X*View.x+Y*View.y+Z*View.z;

Sau khi có Các điểm trong tọa độ View rồi ta dùng chiếu phối cảnh
Tâm chiếu em cho nó nằm ở 0,0,0 mặt phằng chiếu z=2 chằng hạn

==> Tọa độ X Và Y nằm trên màn hình chiếu cũa ta là

X=Xv*2/Zv;
Y=Yv*2/Zv;

Vấn đề tiếp theo là chưa đặt lên màn hình đưỡc, cần phải Xén nó
Thường thì người ta Xén nó theo kiểu chuyễn Volume Camera thành Volume chuẩn cắt nó rồi đưa về tọa độ trên màn hình.

Nhưng để đơn giản em không cắt xén gì hết . Nếu mà em còn Viết cái phần cắt này thì chắc là làm luôn cái 3D lib luôn quá :D
Cho nên Em sẽ biến cái sản phẩm cuối cùng thành sản phẩm trên màn hình luon dùng Viewport .

THôi không giải thíhc nữa mệt quá tự coi Code rồi tìm sách mà học :D, em mệt quá rồi


************************************************** ******************
Phần này là quy ước về trình biên dịch và Đồ họa

Thường thì em thấy ở VN các bạn hay xài Compiler Cũ lắm ,nhất là 16 bit , như vậy để phù hợp với nhu cầu cũng như giới hạn ,nên em cũng cố code lại cho 16 bit Program .

-Quy ước thứ 2 , về việc vẽ hình .Anh có thể xài Graphics.h cho DOS . Chỉ cần 1 hàm vẽ line đơn giản là ta có thể làm chương trình được rồi.

Em sẽ Upload File Lib.cpp gồm các thủ tục cho việc chuyển đổi hình học và parabolic.cpp là file chính. File này có 1 thủ tục là tạo Surface cho Parabolic sau đó áp dụng các phép tính toán trong Lib.cpp để đưa lên màn hình
* Thư viện này không hoàn chỉnh vì không bao gồm thủ tục Clip Volume và các thủ tục Shading khác .Do đó Việc đặt Camera phải được chọn 1 cách khéo léo ,để cho toàn bộ hình ảnh có thể được map vào View .

* Các hàm vẽ đường thằng cơ bản (Raster Line)sẽ không được implement trong Lib.cpp vì lí do anh có thể xài trong Window dùng Line của GDI chẳng hạn. Nếu em Add vô việc Convert thành program cho windows sẽ rất khó .

*************Còn tiếp Xem phần Upload*******************

whitepenguin
18-12-2007, 06:39
File đính kèm gồm 1 demo exe giúp anh làm quen với Camera và hiều cách làm việc của camera , try at Risk ,vì lý do không hoàn chỉnh nên nhiều khi đặt camera không khéo sẽ làm cho màn hình bị vẽ lung tung , hoặc tệ nhất là FPU báo lỗi Divison error :D

Nhớ là khi nhập các sồ liên tiếp nhai thì cách nó ra bằng khoảng trống ví du:
Nhập Vector Up :---> 0 0 1 ( 0,0,1 dấu phẩy là sai cách làm )