Đăng ký Đăng nhập
Trang chủ Tìm hiểu lập trình python và pyopengl...

Tài liệu Tìm hiểu lập trình python và pyopengl

.DOCX
29
1
111

Mô tả:

ĐẠI HỌC QUỐC GIA TP.HỒ CHÍ MINH TRƯỜNG ĐẠI HỌC BÁCH KHOA KHOA ĐIỆN – ĐIỆN TỬ BỘ MÔN ĐIỆN TỬ ---------------o0o--------------- BÁO CÁO THỰC TẬP TỐT NGHIỆP Đề Tài: Tìm Hiểu Lập Trình Python Và PyOpenGl GVHD: Th.S Hồ Trung Mỹ TP. HỒ CHÍ MINH, THÁNG 09 NĂM 2020 LỜI CẢM ƠN GVHD: Th.S Hồ Trung Mỹ LỜI CẢM ƠN Chúng em xin cảm ơn chân thành tới các thầy cô Khoa Điện- Điện Tử Trường ĐH Bách Khoa- Đại Học Quốc Gia TP.HCM, đặc biệt là thầy Hồ Trung Mỹ đã tận tình hướng dẫn, hỗ trợ chúng em trong suốt thời gian thực tập và trong quá trình làm báo cáo thực tập tốt nghiệp. Trong thời gian thực tập chúng em đã được truyền đạt những kinh nghiệm quý báu để giúp chúng em trong công việc sau này, chúng em cũng được học thêm những kiến thức cũng như kinh nghiệm thực tế và có điều kiện phát huy những kiến thức chuyên môn đã được học trong trường do các thầy cô tận tình giảng dạy. Với kiến thức còn hạn chế nên bản báo cáo TTTN không thể tránh khỏi những thiếu xót rất mong được sự thông cảm của quý thầy cô. Chúng em xin chân thành cảm ơn! Tp. Hồ Chí Minh, ngày 08 tháng 09 năm 2020. Sinh viên i MỤC LỤC LỜI MỞ ĐẦU....................................................................................................................................... 3 1. TỔNG QUAN VỀ NGÔN NGỮ PYTHON.................................................................................. 4 1.1 1.1.1. Đặc điểm......................................................................................................................... 4 1.1.2. Ưu điểm.......................................................................................................................... 4 1.1.3. Nhược điểm.................................................................................................................... 5 1.2 Cú pháp ngôn ngữ.................................................................................................................. 5 1.2.1. Biếến sốế và toán tử........................................................................................................... 5 1.2.2. Kiểu dữ liệu..................................................................................................................... 6 1.2.3. Cấếu trúc lặp và rẽẽ nhánh................................................................................................. 7 1.2.4. Hàm và Class................................................................................................................... 7 1.3 Phân chia module................................................................................................................... 9 1.3.1. Các loại modulẽ............................................................................................................... 9 1.3.2. Cách sử dụng modulẽ..................................................................................................... 9 1.4 2. Giới thiệu Python................................................................................................................... 4 Xử lý tập tin.......................................................................................................................... 10 1.4.1. Mở filẽ........................................................................................................................... 10 1.4.2. Đọc filẽ.......................................................................................................................... 11 1.4.3. Ghi vào filẽ.................................................................................................................... 11 1.4.4. Đóng filẽ........................................................................................................................ 11 1.4.5. Đổi tến/ xóa filẽ............................................................................................................ 11 GIỚI THIỆU VỀ PYOPENGL.................................................................................................... 12 2.1 Tìm hiểu về OpenGl............................................................................................................. 12 2.2 Cấu trúc tập lệnh................................................................................................................... 13 2.3 Ứng dụng của OpenGL......................................................................................................... 14 2.3.1. Vẽẽ các đốếi tượng hình học............................................................................................ 14 3. 2.3.2. Thao tác trến ModẽlViẽw.............................................................................................. 16 2.3.3. Thao tác trến Projẽcton................................................................................................ 17 2.3.4. Thao tác trến Viẽwport................................................................................................. 18 2.3.5. Thiếết lập mố hình shading............................................................................................. 19 2.3.6. Tương tác với người dùng............................................................................................. 20 MỘT SỐ DEMO CƠ BẢN.......................................................................................................... 23 3.1 Vẽ khối lập phương xoay...................................................................................................... 23 3.2 Tương tác với chuột và bàn phím......................................................................................... 24 3.3 Thao tác với Model View và thư viện Random.................................................................... 25 3.4 Tạo một khối cầu mặt lưới từ hai mặt phẳng cắt...................................................................26 3.5 Xây dựng mô hình Trái Đất quay xung quanh Mặt Trời.......................................................26 3.6 Thiết lập mô hình Smooth-Shading cho một tam giác..........................................................26 4. ĐỀ XUẤT CÁC ĐỀ TÀI LIÊN QUAN...................................................................................... 26 5. TÀI LIỆU THAM KHẢO........................................................................................................... 26 6. PHỤ LỤC.................................................................................................................................... 26 LỜI MỞ ĐẦU Thật rõ ràng để nhận thấy rằng nếu chỉ hiển thị thông tin chỉ với các ký hiệu, chữ cái, chữ số thì sẽ không thể hấp dẫn và dễ hiểu như khi có thêm biểu diễn bằng Kỹ thuật đồ hoạ. Đây cũng là công cụ không thể thiếu trong các ngành khoa học kỹ thuật, giáo dục, nghệ thuật, giải trí, quảng cáo…(để diễn đạt máy móc thiết bị, kiến trúc, cấu trúc cơ thể, thông tin thiên văn địa lý, hình ảnh minh hoạ..). Cùng với sự phát triển của tin học, kỹ thuật đồ họa trên máy vi tính, ngày càng trở nên tinh xảo. Giao diện các phần mềm ngày nay trở nên thân thiện, đẹp mắt nhờ các thể hiện đồ họa. Sự hỗ trợ của tin học cho các ngành khác trở nên đắc lực hơn nhờ khả năng đồ họa vi tính. Ngôn ngữ lập trình (Programming language) là dạng ngôn ngữ máy tính sử dụng để phát triển các chương trình phần mềm, tập lệnh hoặc các chuẩn hóa theo một hệ thống các quy tắc riêng để máy tính thực thi. Hiện nay có rất nhiều ngôn ngữ lập trình đang được sử dụng như JavaScript, Java, C/C++,Python,…Python có cú pháp khá đơn giản, tốc độ xử lý nhanh, mượt, không quá kén người sử dụng, nhất là phù hợp với những người học lập trình game và ứng dụng. Một điều đáng kinh ngạc đối với Python là tốc độ phát triển nhanh nhất hiện nay. Trong thành công của kỹ thuật đồ họa ngày nay không thể không nói đến sự phát triển vượt bậc của tốc độ phần cứng lẫn hệ điều hành. Nhưng bản thân kỹ thuật đồ họa thì có bước tiến nhảy vọt từ những phép tính toán học phức tạp đến những thư viện đồ họa được tạo sẳn. Các thư viện này cho phép giảm nhẹ thời gian và công sức của người lập trình; Bởi với chúng, để có được một “tác phẩm”đồ họa không đòi hỏi phải có một kiến thức hùng hậu về đường cong Bezier, B-spline, về hình học, tạo bóng…, mà chỉ ứng dụng các hàm tạo sẵn. Một trong những thư viện đó là OpenGL, được xem là tiêu chuẩn thiết kế công nghiệp cho đồ họa ba chiều. Mục tiêu của bài tiểu luận này làtìm hiểu thư viện đồ họa của OpenGL trong đồ họa ba chiều, đồng thời cũng cố gắng đưa ra một ứng dụng của OpenGL trong việc minh họa các giải thuật đồ họa ba chiều một cách đơn giản và dễ tiếp cận. 1. TỔNG QUAN VỀ NGÔN NGỮ PYTHON 1.1 Giới thiệu Python 1.1.1. Đặc điểm Python là một ngôn ngữ lập trình bậc cao cho các mục đích lập trình đa năng, do Guido van Rossum tạo ra và lần đầu ra mắt vào năm 1991 tại Viện toán-tin ở Hà Lan. Python kế thừa từ nhiều ngôn ngữ như ABC, Module-3, C, C++, Unix Shell,… Đến nay thì cộng đồng người sử dụng ngôn ngữ này rất đông, nếu so sánh từ bảng xếp hạng các ngôn ngữ năm 2016 thì Python đứng thứ 3 trong top 10 ngôn ngữ lập trình phổ biến nhất. Có thể thấy rất nhiều ví dụ từ những trò chơi điện tử đơn giản, cho đến những thuật toán tìm kiếm phức tạp, Python đã trở thành sự lựa chọn hoàn hảo cho mọi lập trình viên. Đặc biệt là với sự bùng nổ về công nghệ AI – trí tuệ nhân tạo trong những năm gần đây, cái tên Python liên tục được nhắc đến như là một công cụ hữu ích trong lĩnh vực công nghệ thông tin. 1.1.2. Ưu điểm - Python là một ngôn ngữ bậc cao rất dễ dàng sử dụng. Python có một số lượng từ khóa ít hơn, cấu trúc của Python đơn giản hơn và cú pháp của Python được định nghĩa khá rõ ràng. Tất cả các điều này là Python thực sự trở thành một ngôn ngữ thân thiện với lập trình viên. - Phần code của Python được định nghĩa khá rõ ràng và rành mạch. - Python có một thư viện chuẩn khá rộng lớn. Thư viện này dễ dàng tương thích và tích hợp với UNIX, Windows, và Macintosh. - Python là một ngôn ngữ thông dịch. Trình thông dịch thực thi code theo từng dòng, điều này giúp cho quá trình debug trở nên dễ dàng hơn và đây cũng là yếu tố khá quan trọng giúp Python thu hút được nhiều người học và trở nên khá phổ biến. - Python cũng là một ngôn ngữ lập trình hướng đối tượng. Ngoài ra, Python còn hỗ trợ các phương thức lập trình theo hàm và theo cấu trúc. - Ngoài các đặc điểm trên, Python còn khá nhiều đặc điểm khác như hỗ trợ lập trình GUI, mã nguồn mở, có thể tích hợp với các ngôn ngữ lập trình khác, … 1.1.3. Nhược điểm - Tốc độ chậm hơn so với các ngôn ngữ C/C++ hay Java. - Không phải là ngôn ngữ tốt dành cho nền tảng mobile. - Python không phải lựa chọn tốt cho các bài toán cần tối ưu bộ nhớ. - Python có nhiều giới hạn khi làm việc với cơ sở dữ liệu phức tạp. 1.2 Cú pháp ngôn ngữ 1.2.1. Biến số và toán tử Ta khai báo một biến bằng cách gán giá trị cụ thể cho nó. Biến sẽ tự động được giải phóng khi ra khỏi phạm vi của chương trình sử dụng nó. Một biến có thể được gán nhiều loại giá trị như số, chuỗi, ký tự. >>>a = 1 >>>a = 'Hello World' >>>a = [1, 2, 3] >>>a = [1.2, 'Hello', 'W', 2] Cũng có thể khai báo nhiều giá trị cho nhiều biến trên cùng một dòng hoặc chuyển đổi giữa hai giá trị rất dễ dàng: >>> a , b = 45, 54 >>> a, b = b , a >>> a 54 >>> b 45 1.2.2. Kiểu dữ liệu Kiểu số 1234585396326 (số nguyên dài vô hạn) -86.12 7.84E-04 3+ 8j (số phức) Kiểu chuỗi (string): Đặt trong cặp dấu ‘ hoặc “ "Hello" "It's me" '"OK"-he replied' Kiểu bộ (tuple): là cấu trúc mảng và một tuple đã được khai báo rồi thì không thay đổi được giá trị (immutable) mytuple = ('x' , 'y' , 'z') (1, 2.0, 3) (1,) ("Hello",1,()) Kiểu danh sách (list): là cấu trúc mảng và các phần tử có index có thứ tự numbers = [1, 2, 3, 4, 5] names = ['Marry' , 'Peter'] Kiểu từ điển (dictionary):là một cấu trúc mảng, nhưng các phần tử bao gồm key và value {"Vietnam":"Hanoi", "Netherlands":"Amsterdam","France":"Paris"} Chú thích: giúp cho lập trình viên dễ dàng cải tiến mã nguồn, ghi chú các chức năng của đoạn code thực hiện # dòng chú thích 1.2.3. Cấu trúc lặp và rẽ nhánh a) If…elif…else if : elif : elif elif : else: b) For…in…else for in : else: c) While...else while : else: 1.2.4. Hàm và Class Trong lập trình chúng ta sẽ có lúc sử dụng một đoạn code lặp đi lặp lại nhiều lần trong chương trình. Hàm sẽ giúp chúng ta thực hiện điều này. Chúng ta có thể viết tất cả những gì chúng ta muốn thực hiện trong hàm sau đó chỉ cần gọi khi sử dụng. Khai báo hàm theo cú pháp sau: def (, ,..): Hàm nếu không trả dữ liệu thì mặc định sẽ trả về giá trị Một ví dụ về khai báo và gọi hàm tìm phần tử lớn nhất trong mảng: def max(a): max = a[0] for x in a: if x > max: max = x return max data = [1, 5, 1, 12,3, 4, 6] print “Data:”, data Kết quả: Data: [1, 5, 1, 12,3, 4, 6] Maximum: 12 Khai báo một Class theo cú pháp sau: class ([parentclass]): def (self): init def : def : 1.3 Phân chia module 1.3.1. Các loại module Có 3 loại module thường thấy là: 1. Viết bằng Python: có phần mở rộng là .py 2. Các thư viện liên kết động: có phần mở rộng là .dll , .pyd , .so , .sl ,… 3. C-Module liên kết với trình phiên dịch 1.3.2. Cách sử dụng module Modules trong Python là các tập tin chưa các hàm được định nghĩa sẵn, biến cái mà chúng ta có thể sử dụng lại, nó cũng có đuôi mở rộng là .py. Python đã cung cấp sẵn một số module mặc định. Chúng ta có thể sử dụng chúng. Để sử dụng chúng ta cần dùng lệnh import import Khi gặp câu lệnh trên thì trình biên dịch sẽ tiến hành tìmkiếm file module tương ứng theo thứ tự thư mục sau: 1. Thư mục hiện hành mà script đang gọi 2. Các thư mục trong PYTHONPATH (nếu có set) 3. Các thư mục cài đặt chuẩn trên Linux/Unix.. Giả sử ta tạo một file python mymath.py có nội dung như sau: def cong(a, b): return a + b def tru(a, b): return a - b def nhan(a, b): return a * b Sau đó, tạo một file có tên myexample.py , trong cùng thư mục với file mymath.py vừa tạo ở trên, có nội dung như sau: import mymath num1 =1 num2 = 2 Sau khi thực hiện sẽ hiển thị lên màn hình là: Tong hai so la: 3 1.4 Xử lý tập tin Một tập tin chứa thông tin hoặc dữ liệu được lưu trữ trên thiết bị lưu trữ của máy tính. Python sẽ cung cấp cách để điều khiển các tập tin như âm nhạc, video, và tập tin văn bản. Chúng ta sẽ tập trung vào hai loại: tập tin văn bản và binary. 1.4.1. Mở file Trước khi muốn đọc hoặc ghi file, cần có thao tác mở file theo cú pháp: fh = open(filepath, mode) Với hàm này sẽ có hai tham số được truyền vào đó là đường dẫn và chế độ mở. Các chế độ như sau:  r : mở để đọc nội dung (mặc định)  w : mở để ghi nội dung  a : mở để ghi thêm nội dung vào cuối file.  r+ : mở để đọc và ghi. Con trỏ nằm ở đầu file.  w+ : mở để đọc và ghi. Ghi đè nếu file đã tồn tại, nếu chưa tồn tại thì tạo file mới để ghi.  a+ : mở để đọc và thêm vào cuối file. Con trỏ nằm ởcuối file. Nếu file chưa tồn tại thì tạo file mới để ghi. Mặc định là mở file text, nếu muốn mở file nhị phân(binary) thì thêm b , ví dụ: rb , wb , ab , rb+ , wb+ , ab+ . 1.4.2. Đọc file Sau khi file đã mở ở chế độ đọc thì gọi phương thức read([count]) để trả về toàn bộ nội dung của file. Ví dụ: f1 = open('test.txt', 'r') data = f1.read(); Hàm read() có nhận một tham số là số lượng byte muốn đọc. Nếu không truyền vào thì sẽ đọc hết nội dung của file. 1.4.3. Ghi vào file Nếu file được mở ở chế độ có thể ghi thì có thể dùng phương thức write() để ghi một nội dung vào file. Ví dụ: f2 = open('access_log','a+') f2.write('Attack detected') 1.4.4. Đóng file Cuối chương trình chúng ta sử dụng hàm close() để thực hiện đóng tập tin khi không còn thao tác với nó nữa.Ví dụ: f1.close() f2.close() 1.4.5. Đổi tên/ xóa file Sử dụng phương thức os.rename(old, new) để đổi tênmột file. Ví dụ: import os os.rename('test.txt','test_new.txt') Sử dụng phương thức os.remove(file) để xóa một filekhỏi hệ thống. Ví dụ: import os os.remove('test.txt') 2. GIỚI THIỆU VỀ PYOPENGL 2.1 Tìm hiểu về OpenGl OpenGL (Open Graphics Library) là một tiêu chuẩn kỹ thuật đồ họa có mục đích định ra một giao diện lập trình ứng dụng (API) đồ họa 3 chiều. OpenGL cũng có thể được dùng trong các ứng dụng đồ họa 2 chiều. Giao diện lập trình này chứa khoảng 150 hàm để vẽ các cảnh phức tạp từ những hàm đơn giản Silicon Graphics, nhà sản xuất máy trạm đồ họa tiên tiến thế giới, là đơn vị đi tiên phong trong việc phát triển OpenGL. Nó được dùng rộng rãi trong các trò chơi điện tử. Ngoài ra OpenGL còn dùng trong các ứng dụng CAD, thực tế ảo, mô phỏng khoa học, mô phỏng thông tin, phát triển trò chơi…. OpenGL hỗ trợ các hàm đồ họa làm các việc như sau:  Xây dựng các đối tượng phức tạp từ các thành phần hình học cơ bản (điểm, đoạn, đa giác, ảnh, bitmap)  Sắp xếp đối tượng trong đồ họa 3D và chọn điểm thuận lợi để quan sát  Tính toán màu sắc của các đối tượng (màu sắc của đối tượng được quy định bởi điều kiện chiếu sáng, texture của đối tượng, mô hình được xây dựng hoặc là kết hợp của cả 3 yếu tố đó)  Biến đổi những mô tả toán học của đối tượng và thông tin màu sắc thành các pixel trên màn hình (quá trình này được gọi là resterization). 2.2 Cấu trúc tập lệnh OpenGL sử dụng tiền tố gl và tiếp theo đó là những từ được viết hoa ở chữ cái đầu để tạo nên tên của một lệnh theo hình thức gl{tên hàm}[{số tham số}{loại tham số}] Ví dụ: glClearColor(), glColor3f() Tương tự, OpenGL đặt tên các hằng số bắt đầu bằng GL_ và các từ tiếp sau đều được viết hoa và cách nhau bởi dấu ‘_’ Ví dụ: GL_COLOR_BUFFER_BIT. Bên cạnh đó, với một số lệnh, để ám chỉ số lượng cũng như kiểu tham số được truyền, một số hậu tố được sử dụng như trong bảng sau: Ví dụ: glVertex2i(1,3) tương ứng với xác định một điểm (x,y) với x, y nguyên (integer) Tuy nhiên có những thứ mà OpenGL không hỗ trợ sẵn như  Bản thân OpenGL không có sẵn các hàm nhập xuất hay thao tác trên window  OpenGL không có sẵn các hàm cấp cao để xây dựng các mô hình đối tượng, thay vào đó,người dùng phải tự xây dựng từ các thành phần hình học cơ bản. Để khắc phục nhược điểm của OpenGL, GLUT được tạo ra với với nhiều hàm hỗ trợ  Quản lý window  Display callback  Nhập xuất (bàn phím, chuột,...)  Vẽ một số đối tượng 3D phức tạp (mặt cầu, khối hộp,...) Tên các hàm của GLUT đều có tiền tố là glut. 2.3 Ứng dụng của OpenGL 2.3.1. Vẽ các đối tượng hình học Trong OpenGL có 2 loại buffer phổ biến nhất, mỗi lần vẽ, chúng ta nên xóa buffer glClearColor(0.0, 0.0, 0.0, 0.0); /* xác định màu để xóa color buffer (màu đen) */ glClearDepth(1.0); /* xác định giá trị để xóa depth buffer */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* xóa color buffer và depth buffer */  Color buffer: buffer chứa màu của các pixel cần được thể hiện  Depth buffer (hay còn gọi là z-buffer): buffer chứa chiều sâu của pixel, được đo bằng khoảng cách đến mắt. Mục đích chính của buffer này là loại bỏ phần đối tượng nằm sau đối tượng khác. Khi vẽ một đối tượng, OpenGL sẽ tự động sử dụng màu đã được xác định trước đó. Do đó, để vẽ đối tượng với màu sắc theo ý mình, cần phải thiết lập lại màu vẽ như sau: glColor3f(0.0, 0.0, 0.0); // black glColor3f(1.0, 0.0, 0.0); // red glColor3f(0.0, 1.0, 0.0); // green glColor3f(1.0, 1.0, 0.0); // yellow glColor3f(0.0, 0.0, 1.0); // blue glColor3f(1.0, 0.0, 1.0); // magenta glColor3f(0.0, 1.0, 1.0); // cyan glColor3f(1.0, 1.0, 1.0); // white OpenGL không có sẵn các hàm để xây dựng các đối tượng hình học phức tạp, người dùng phải tự xây dựng chúng từ các đối tượng hình học cơ bản mà OpenGL hỗ trợ: điểm, đoạn thẳng, đa giác. Khi khai báo một điểm ta dùng hàm glVertexXY với X là số chiều (2, 3, hoặc 4), Y là kiểu dữ liệu. Việc xây dựng các đối tượng hình học khác đều có thể được thực hiện như sau glBegin(mode); /* xác định tọa độ và màu sắc của các điểm của hình */ glEnd(); mode có thể là một trong những giá trị sau: Một số tính chất của điểm và đoạn cần quan tâm có thể được thiết lập qua các hàm:  Kích thước của một điểm: void glPointSize(GLfloat size)  Độ rộng của đoạn thẳng: void glLineWidth(GLfloat width)  Kiểu vẽ 2.3.2. Thao tác trên ModelView Trước khi thực hiện các thao tác trên ModelView, chúng ta cần gọi hàm glMatrixMode(GL_MODELVIEW); OpenGL hỗ trợ sẵn các hàm biến đổi affine cơ bản như sau  Tịnh tiến: void glTranslate{fd}(TYPEx, TYPE y, TYPEz);  Quay quanh trục nối gốc tọa độ với điểm (x,y,z) void glRotate{fd}(TYPE angle, TYPE x, TYPE y, TYPE z);  Tỉ lệ (tâm tỉ lệ tại gốc tọa độ) void glScale{fd}(TYPEx, TYPE y, TYPEz); Ví dụ: chúng ta thực hiện phép quay quanh trục z một góc α và tịnh tiến đi một đoạn theo vector(trx, try, trz), các bước thực hiện sẽ là: Giống như chụp hình, thiết lập view là thiết lập vị trí cũng như góc, hướng của camera. GLUT cómột hàm giúp thiết lập view một cách nhanh chóng void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, Gldoublecenterx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdoubleupy, GLdouble upz) trong đó  (eyex, eyey, eyez) là vị trí đặt của view,  (centerx, centery, centerz) là điểm nằm trên đường thẳng xuất phát từ tâm view hướng rangoài,  (upx, upy, upz) là vector chỉ hướng lên trên của view 2.3.3. Thao tác trên Projection Trước khi thực hiện các thao tác chiếu, chúng ta gọi 2 hàm glMatrixMode(GL_PROJECTION); glLoadIdentity(); Chiếu phối cảnh (Perspective Projection) Đặc điểm của phép chiếu này là đối tượng càng lùi ra xa thì trông càng nhỏ Để thiết lập phép chiếu này, OpenGL có hàm void glFrustum(GLdouble left, GLdouble right, GLdouble bottom,GLdoubletop, GLdouble near, GLdouble far); Chiếu trực giao (Orthogonal Projection) Trong phép chiếu này, khoảng cách của vật tới camera không ảnh hưởng tới độ lớn của vật đó khi hiển thị. Để thiết lập phép chiếu này, OpenGL có hàm void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdoubletop, GLdouble near, GLdouble far);
- Xem thêm -

Tài liệu liên quan