У комп'ютерній графіці, алгоритм Ляна — Барського це алгоритм відсікання відрізків. Цей алгоритм використовує параметричне рівняння прямої і нерівності, що описують вікно відсікання для визначення перетинів між відрізком і вікном відсікання. За цими перетинами визначається, яку частину відрізка потрібно малювати. Алгоритм можна узагальнити до тривимірного випадку. Цей алгоритм значно ефективніший від алгоритму Коена — Сазерленда.
Розробили [en] і [en] 1984 року і вдосконалили 1992 року.
Опис
Ідеєю відсікання Ляна — Барського є якомога повніша перевірка перед обчисленням перетину відрізків. Спочатку розглянемо звичайне параметричне рівняння відрізка:
Точка перебуває у вікні відсікання, якщо
і
- ,
що можна виразити чотирма нерівностями
- ,
де
- — ліворуч
- — праворуч
- — знизу
- — згори
- Якщо — відрізок паралельний до однієї з площин відсікання
- — зовні, відкинути
- — всередині
- Якщо — ззовні всередину
- Перетин у:
- Якщо — зсередини назовні
- Перетин у:
- Для — точка ззовні всередину
- Для — точка зсередини назовні
- Якщо повністю зовні, відкинути
- Інакше, опрацьовуваний відрізок пролягає у межах
Реалізація мовою C++
Нижче наведено реалізацію алгоритму мовою C++ з використанням бібліотеки winbgim:
// Алгоритм Ляна - Барського відсікання відрізка #include<iostream> #include<math.h> #include<graphics.h> using namespace std; // Функція, що повертає максимум у масиві float maxi(const float arr[], int n) { float m = 0; for (int i = 0; i < n; ++i) if (m < arr[i]) m = arr[i]; return m; } // Функція, що повертає мінімум у масиві float mini(const float arr[], int n) { float m = 1; for (int i = 0; i < n; ++i) if (m > arr[i]) m = arr[i]; return m; } void liang_barsky_clipper(float xmin, float ymin, float xmax, float ymax, float x1, float y1, float x2, float y2) { // Оголошення зімнних float p1 = -(x2 - x1); float p2 = -p1; float p3 = -(y2 - y1); float p4 = -p3; float q1 = x1 - xmin; float q2 = xmax - x1; float q3 = y1 - ymin; float q4 = ymax - y1; float posarr[5], negarr[5]; int posind = 1, negind = 1; posarr[0] = 1; negarr[0] = 0; rectangle(int(round(xmin)), int(round(467 - ymin)), int(round(xmax)), int(round(467 - ymax))); // Малювання відсікального вікна if ((p1 == 0 && q1 < 0) || (p3 == 0 && q3 < 0)) { outtextxy(80, 80, "Line is parallel to clipping window!"); return; } if (p1 != 0) { float r1 = q1 / p1; float r2 = q2 / p2; if (p1 < 0) { negarr[negind++] = r1; // При від'ємному p1, додаємо r1 до від'ємного масиву posarr[posind++] = r2; // і додаємо r2 до додатного масиву } else { negarr[negind++] = r2; posarr[posind++] = r1; } } if (p3 != 0) { float r3 = q3 / p3; float r4 = q4 / p4; if (p3 < 0) { negarr[negind++] = r3; posarr[posind++] = r4; } else { negarr[negind++] = r4; posarr[posind++] = r3; } } float xn1, yn1, xn2, yn2; float rn1, rn2; rn1 = maxi(negarr, negind); // Максимум від'ємного масиву rn2 = mini(posarr, posind); // Мінімум додатного масиву if (rn1 > rn2) { // Відхиляємо outtextxy(80, 80, "Line is outside the clipping window!"); return; } xn1 = x1 + p2 * rn1; yn1 = y1 + p4 * rn1; // Обчислюємо нові точки xn2 = x1 + p2 * rn2; yn2 = y1 + p4 * rn2; setcolor(CYAN); line(int(round(xn1)), int(round(467 - yn1)), int(round(xn2)), int(round(467 - yn2))); // Рисование новой линии setlinestyle(1, 1, 0); line(int(round(x1)), int(round(467 - y1)), int(round(xn1)), int(round(467 - yn1))); line(int(round(x2)), int(round(467 - y2)), int(round(xn2)), int(round(467 - yn2))); } int main() { cout << "\nLiang-Barsky line clipping"; cout << "\nThe system window outlay is: (0,0) at bottom left and (631, 467) at top right"; cout << "\nEnter the co-ordinates of the window(wxmin, wxmax, wymin, wymax):"; float xmin, xmax, ymin, ymax; cin >> xmin >> ymin >> xmax >> ymax; cout << "\nEnter the end points of the line (x1, y1) and (x2, y2):"; float x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; int gd = DETECT, gm; // Ініціалізація графічного режиму initgraph(&gd, &gm, ""); liang_barsky_clipper(xmin, ymin, xmax, ymax, x1, y1, x2, y2); getch(); closegraph(); }
Примітки
- Liang, Y. D., and Barsky, B., «A New Concept and Method for Line Clipping», ACM Transactions on Graphics, 3(1):1-22, January 1984
- Liang, YD, BA, Barsky, and M. Slater, Some Improvements to a Parametric Line Clipping Algorithm, CSD-92-688, Computer Science Division, University of California, Berkeley, 1992.
Посилання
- Графіка і Мультимедіа: Обтинання [ 22 листопада 2015 у Wayback Machine.]
- Опис алгоритму із кодом на C++ [ 21 листопада 2016 у Wayback Machine.] (англ.)
- The Liang-Barsky algorithm for line-rectangle collisions [ 12 березня 2017 у Wayback Machine.] (англ.)
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
U komp yuternij grafici algoritm Lyana Barskogo ce algoritm vidsikannya vidrizkiv Cej algoritm vikoristovuye parametrichne rivnyannya pryamoyi i nerivnosti sho opisuyut vikno vidsikannya dlya viznachennya peretiniv mizh vidrizkom i viknom vidsikannya Za cimi peretinami viznachayetsya yaku chastinu vidrizka potribno malyuvati Algoritm mozhna uzagalniti do trivimirnogo vipadku Cej algoritm znachno efektivnishij vid algoritmu Koena Sazerlenda Rozrobili en i en 1984 roku i vdoskonalili 1992 roku OpisIdeyeyu vidsikannya Lyana Barskogo ye yakomoga povnisha perevirka pered obchislennyam peretinu vidrizkiv Spochatku rozglyanemo zvichajne parametrichne rivnyannya vidrizka x x 0 u x 1 x 0 x 0 u D x displaystyle x x 0 u x 1 x 0 x 0 u Delta x y y 0 u y 1 y 0 y 0 u D y displaystyle y y 0 u y 1 y 0 y 0 u Delta y u 0 1 displaystyle u in 0 1 Tochka perebuvaye u vikni vidsikannya yaksho x min x 0 u D x x max displaystyle x text min leq x 0 u Delta x leq x text max i y min y 0 u D y y max displaystyle y text min leq y 0 u Delta y leq y text max sho mozhna viraziti chotirma nerivnostyami u p k q k k 1 2 3 4 displaystyle up k leq q k quad k 1 2 3 4 de p 1 D x q 1 x 0 x min displaystyle p 1 Delta x q 1 x 0 x text min livoruch p 2 D x q 2 x max x 0 displaystyle p 2 Delta x q 2 x text max x 0 pravoruch p 3 D y q 3 y 0 y min displaystyle p 3 Delta y q 3 y 0 y text min znizu p 4 D y q 4 y max y 0 displaystyle p 4 Delta y q 4 y text max y 0 zgori Yaksho p k 0 displaystyle p k 0 vidrizok paralelnij do odniyeyi z ploshin vidsikannya q k lt 0 displaystyle q k lt 0 zovni vidkinuti q k 0 displaystyle q k geq 0 vseredini Yaksho p k lt 0 displaystyle p k lt 0 zzovni vseredinu Peretin u u q k p k displaystyle u q k p k Yaksho p k gt 0 displaystyle p k gt 0 zseredini nazovni Peretin u u q k p k displaystyle u q k p k Dlya p k lt 0 displaystyle p k lt 0 tochka zzovni vseredinu r k q k p k displaystyle r k q k p k u 1 m a x r k 0 displaystyle u 1 max r k 0 Dlya p k gt 0 displaystyle p k gt 0 tochka zseredini nazovni r k q k p k displaystyle r k q k p k u 2 m i n r k 1 displaystyle u 2 min r k 1 Yaksho u 1 gt u 2 displaystyle u 1 gt u 2 povnistyu zovni vidkinuti Inakshe opracovuvanij vidrizok prolyagaye u mezhah u 1 u 2 displaystyle u 1 u 2 Realizaciya movoyu C Nizhche navedeno realizaciyu algoritmu movoyu C z vikoristannyam biblioteki winbgim Algoritm Lyana Barskogo vidsikannya vidrizka include lt iostream gt include lt math h gt include lt graphics h gt using namespace std Funkciya sho povertaye maksimum u masivi float maxi const float arr int n float m 0 for int i 0 i lt n i if m lt arr i m arr i return m Funkciya sho povertaye minimum u masivi float mini const float arr int n float m 1 for int i 0 i lt n i if m gt arr i m arr i return m void liang barsky clipper float xmin float ymin float xmax float ymax float x1 float y1 float x2 float y2 Ogoloshennya zimnnih float p1 x2 x1 float p2 p1 float p3 y2 y1 float p4 p3 float q1 x1 xmin float q2 xmax x1 float q3 y1 ymin float q4 ymax y1 float posarr 5 negarr 5 int posind 1 negind 1 posarr 0 1 negarr 0 0 rectangle int round xmin int round 467 ymin int round xmax int round 467 ymax Malyuvannya vidsikalnogo vikna if p1 0 amp amp q1 lt 0 p3 0 amp amp q3 lt 0 outtextxy 80 80 Line is parallel to clipping window return if p1 0 float r1 q1 p1 float r2 q2 p2 if p1 lt 0 negarr negind r1 Pri vid yemnomu p1 dodayemo r1 do vid yemnogo masivu posarr posind r2 i dodayemo r2 do dodatnogo masivu else negarr negind r2 posarr posind r1 if p3 0 float r3 q3 p3 float r4 q4 p4 if p3 lt 0 negarr negind r3 posarr posind r4 else negarr negind r4 posarr posind r3 float xn1 yn1 xn2 yn2 float rn1 rn2 rn1 maxi negarr negind Maksimum vid yemnogo masivu rn2 mini posarr posind Minimum dodatnogo masivu if rn1 gt rn2 Vidhilyayemo outtextxy 80 80 Line is outside the clipping window return xn1 x1 p2 rn1 yn1 y1 p4 rn1 Obchislyuyemo novi tochki xn2 x1 p2 rn2 yn2 y1 p4 rn2 setcolor CYAN line int round xn1 int round 467 yn1 int round xn2 int round 467 yn2 Risovanie novoj linii setlinestyle 1 1 0 line int round x1 int round 467 y1 int round xn1 int round 467 yn1 line int round x2 int round 467 y2 int round xn2 int round 467 yn2 int main cout lt lt n Liang Barsky line clipping cout lt lt n The system window outlay is 0 0 at bottom left and 631 467 at top right cout lt lt n Enter the co ordinates of the window wxmin wxmax wymin wymax float xmin xmax ymin ymax cin gt gt xmin gt gt ymin gt gt xmax gt gt ymax cout lt lt n Enter the end points of the line x1 y1 and x2 y2 float x1 y1 x2 y2 cin gt gt x1 gt gt y1 gt gt x2 gt gt y2 int gd DETECT gm Inicializaciya grafichnogo rezhimu initgraph amp gd amp gm liang barsky clipper xmin ymin xmax ymax x1 y1 x2 y2 getch closegraph PrimitkiLiang Y D and Barsky B A New Concept and Method for Line Clipping ACM Transactions on Graphics 3 1 1 22 January 1984 Liang YD BA Barsky and M Slater Some Improvements to a Parametric Line Clipping Algorithm CSD 92 688 Computer Science Division University of California Berkeley 1992 PosilannyaGrafika i Multimedia Obtinannya 22 listopada 2015 u Wayback Machine Opis algoritmu iz kodom na C 21 listopada 2016 u Wayback Machine angl The Liang Barsky algorithm for line rectangle collisions 12 bereznya 2017 u Wayback Machine angl