Обрезка линии | Набор 1 (алгоритм Коэна – Сазерленда)
Опубликовано: 20 Января, 2022
Учитывая набор линий и прямоугольную область интереса, задача состоит в том, чтобы удалить линии, которые находятся за пределами области интереса, и обрезать линии, которые частично находятся внутри области.
Входные данные: прямоугольная область интереса (определяется ниже четырех значений, которые являются координатами внизу слева и вверху справа) x_min = 4, y_min = 4, x_max = 10, y_max = 8 Набор линий (определяется двумя угловыми координатами) строка 1: x1 = 5, y1 = 5, x2 = 7, y2 = 7 Строка 2: x1 = 7, y1 = 9, x2 = 11, y2 = 4 Строка 2: x1 = 1, y1 = 5, x2 = 4, y2 = 1 Вывод: Строка 1: Принимается с (5, 5) по (7, 7) Строка 2: Принято с (7.8, 8) до (10, 5.25) Строка 3: отклонено
Алгоритм Коэна-Сазерленда делит двумерное пространство на 9 областей, а затем эффективно определяет линии и части линий, которые находятся внутри данной прямоугольной области.
Алгоритм можно изложить следующим образом: -
Создаются девять регионов, восемь «внешних» регионов и один «внутренний» регион. Для данной крайней точки линии (x, y) мы можем быстро найти четырехбитный код своего региона. Четырехбитный код может вычисляться путем сравнения x и y с четырьмя значениями (x_min, x_max, y_min и y_max). Если x меньше x_min, то устанавливается бит номер 1. Если x больше x_max, то устанавливается бит номер 2. Если y меньше y_min, то устанавливается бит номер 3. Если y больше y_max, то устанавливается бит номер 4.
Для любой данной строки есть три возможных случая.
- Полностью внутри данного прямоугольника: Побитовое ИЛИ области двух конечных точек линии равно 0 (Обе точки находятся внутри прямоугольника)
- Полностью за пределами данного прямоугольника: обе конечные точки имеют как минимум одну внешнюю область, что означает, что линия не пересекает видимую область. (побитовое И конечных точек! = 0).
- Частично внутри окна: обе конечные точки находятся в разных регионах. В этом случае алгоритм находит одну из двух точек, находящихся за пределами прямоугольной области. Пересечение линии от внешней точки и прямоугольного окна становится новой угловой точкой, и алгоритм повторяется.
Псевдокод:
Шаг 1: Назначьте код региона для двух конечных точек данной линии. Шаг 2. Если обе конечные точки имеют код региона 0000 тогда данная линия полностью внутри. Шаг 3: В противном случае выполните операцию логического И для обоих кодов регионов. Шаг 3.1: Если результат не 0000, то данная строка полностью заполнена. вне. Шаг 3.2: Остальная линия частично внутри. Шаг 3.2.1: Выберите конечную точку линии что находится за пределами данного прямоугольника. Шаг 3.2.2: Найдите точку пересечения прямоугольная граница (на основе кода региона). Шаг 3.2.3: Замените конечную точку точкой пересечения и обновите код региона. Шаг 3.2.4: Повторяйте шаг 2, пока не найдем обрезанную линию. банально принимается или банально отвергается. Шаг 4. Повторите шаг 1 для других строк.
Below is implementation of above steps.
C++
// C++ program to implement Cohen Sutherland algorithm // for line clipping. #include <iostream> using namespace std; // Defining region codes const int INSIDE = 0; // 0000 const int LEFT = 1; // 0001 const int RIGHT = 2; // 0010 const int BOTTOM = 4; // 0100 const int TOP = 8; // 1000 // Defining x_max, y_max and x_min, y_min for // clipping rectangle. Since diagonal points are // enough to define a rectangle const int x_max = 10; const int y_max = 8; const int x_min = 4; const int y_min = 4; // Function to compute region code for a point(x, y) int computeCode( double x, double y) { // initialized as being inside int code = INSIDE; if (x < x_min) // to the left of rectangle code |= LEFT; else if (x > x_max) // to the right of rectangle code |= RIGHT; if (y < y_min) // below the rectangle code |= BOTTOM; else if (y > y_max) // above the rectangle code |= TOP; return code; } // Implementing Cohen-Sutherland algorithm // Clipping a line from P1 = (x2, y2) to P2 = (x2, y2) void cohenSutherlandClip( double x1, double y1, double x2, double y2) { // Compute region codes for P1, P2 int code1 = computeCode(x1, y1); int code2 = computeCode(x2, y2); // Initialize line as outside the rectangular window bool accept = false ; while ( true ) { if ((code1 == 0) && (code2 == 0)) { // If both endpoints lie within rectangle accept = true ; break ; } else if (code1 & code2) { // If both endpoints are outside rectangle, // in same region break ; } else { // Some segment of line lies within the // rectangle int code_out; double x, y; // At least one endpoint is outside the // rectangle, pick it. if (code1 != 0) code_out = code1; else code_out = code2; // Find intersection point; // using formulas y = y1 + slope * (x - x1), // x = x1 + (1 / slope) * (y - y1) if (code_out & TOP) { // point is above the clip rectangle x = x1 + (x2 - x1) * (y_max - y1) / (y2 - y1); y = y_max; } else if (code_out & BOTTOM) { // point is below the rectangle x = x1 + (x2 - x1) * (y_min - y1) / (y2 - y1); y = y_min; } else if (code_out & RIGHT) { // point is to the right of rectangle y = y1 + (y2 - y1) * (x_max - x1) / (x2 - x1); x = x_max; } else if (code_out & LEFT) { // point is to the left of rectangle y = y1 + (y2 - y1) * (x_min - x1) / (x2 - x1); x = x_min; } // Now intersection point x, y is found // We replace point outside rectangle // by intersection point if (code_out == code1) { x1 = x; y1 = y; code1 = computeCode(x1, y1); } else { x2 = x; y2 = y; code2 = computeCode(x2, y2); } } } if (accept) { cout << "Line accepted from " << x1 << ", " << y1 << " to " << x2 << ", " << y2 << endl; // Here the user can add code to display the rectangle // along with the accepted (portion of) lines } else cout << "Line rejected" << endl; } // Driver code int main() { // First Line segment // P11 = (5, 5), P12 = (7, 7) cohenSutherlandClip(5, 5, 7, 7); // Second Line segment // P21 = (7, 9), P22 = (11, 4) cohenSutherlandClip(7, 9, 11, 4); // Third Line segment // P31 = (1, 5), P32 = (4, 1) cohenSutherlandClip(1, 5, 4, 1); return 0; } |
Python
# Python program to implement Cohen Sutherland algorithm # for line clipping. # Defining region codes INSIDE = 0 # 0000 LEFT = 1 # 0001 RIGHT = 2 # 0010 BOTTOM = 4 # 0100 TOP = 8 # 1000 # Defining x_max, y_max and x_min, y_min for rectangle # Since diagonal points are enough to define a rectangle x_max = 10.0 y_max = 8.0 x_min = 4.0 y_min = 4.0 # Function to compute region code for a point(x, y) def computeCode(x, y): code = INSIDE if x < x_min: # to the left of rectangle code | = LEFT elif x > x_max: # to the right of rectangle code | = RIGHT if y < y_min: # below the rectangle code | = BOTTOM elif y > y_max: # above the rectangle code | = TOP return code # Implementing Cohen-Sutherland algorithm # Clipping a line from P1 = (x1, y1) to P2 = (x2, y2) def cohenSutherlandClip(x1, y1, x2, y2): # Compute region codes for P1, P2 code1 = computeCode(x1, y1) code2 = computeCode(x2, y2) accept = False while True : # If both endpoints lie within rectangle if code1 = = 0 and code2 = = 0 : accept = True break # If both endpoints are outside rectangle elif (code1 & code2) ! = 0 : break # Some segment lies within the rectangle else : # Line Needs clipping # At least one of the points is outside, # select it x = 1.0 y = 1.0 if code1 ! = 0 : code_out = code1 else : code_out = code2 # Find intersection point # using formulas y = y1 + slope * (x - x1), # x = x1 + (1 / slope) * (y - y1) if code_out & TOP: # point is above the clip rectangle x = x1 + (x2 - x1) *
(y_max - y1) / (y2 - y1) y = y_max elif code_out & BOTTOM: # point is below the clip rectangle x = x1 + (x2 - x1) *
(y_min - y1) / (y2 - y1) y = y_min elif code_out & RIGHT: # point is to the right of the clip rectangle y = y1 + (y2 - y1) *
(x_max - x1) / (x2 - x1) x = x_max elif code_out & LEFT: # point is to the left of the clip rectangle y = y1 + (y2 - y1) *
(x_min - x1) / (x2 - x1) x = x_min # Now intersection point x, y is found # We replace point outside clipping rectangle # by intersection point if code_out = = code1: x1 = x y1 = y code1 = computeCode(x1, y1) else : x2 = x y2 = y code2 = computeCode(x2, y2) if accept: print ( "Line accepted from %.2f, %.2f to %.2f, %.2f" % (x1, y1, x2, y2)) # Here the user can add code to display the rectangle # along with the accepted (portion of) lines else : print ( "Line rejected" ) # Driver Script # First Line segment # P11 = (5, 5), P12 = (7, 7) cohenSutherlandClip( 5 , 5 , 7 , 7 ) # Second Line segment # P21 = (7, 9), P22 = (11, 4) cohenSutherlandClip( 7 , 9 , 11 , 4 ) # Third Line segment # P31 = (1, 5), P32 = (4, 1) cohenSutherlandClip( 1 , 5 , 4 , 1 ) |
Выход:
Линия принимается с 5.00, 5.00 до 7.00, 7.00 Линия принимается с 7.80, 8.00 до 10.00, 5.25 Линия отклонена
Below is C++ code with Graphics using graphics.h
C++
// C++ program to implement Cohen Sutherland algorithm // for line clipping. // including libraries #include <bits/stdc++.h> #include <graphics.h> using namespace std; // Global Variables int xmin, xmax, ymin, ymax; // Lines where co-ordinates are (x1, y1) and (x2, y2) struct lines { int x1, y1, x2, y2; }; // This will return the sign required. int sign( int x) { if (x > 0) return 1; else return 0; } // CohenSutherLand LineClipping Algorith As Described in theory. // This will clip the lines as per window boundaries. void clip( struct lines mylines) { // arrays will store bits // Here bits implies initial Point whereas bite implies end points int bits[4], bite[4], i, var; // setting color of graphics to be RED setcolor(RED); // Finding Bits bits[0] = sign(xmin - mylines.x1); bite[0] = sign(xmin - mylines.x2); bits[1] = sign(mylines.x1 - xmax); bite[1] = sign(mylines.x2 - xmax); bits[2] = sign(ymin - mylines.y1); bite[2] = sign(ymin - mylines.y2); bits[3] = sign(mylines.y1 - ymax); bite[3] = sign(mylines.y2 - ymax); // initial will used for initial coordinates and end for final string initial = "" , end = "" , temp = "" ; // convert bits to string for (i = 0; i < 4; i++) { if (bits[i] == 0) initial += "0" ; else initial += "1" ; } for (i = 0; i < 4; i++) { if (bite[i] == 0) end += "0" ; else РЕКОМЕНДУЕМЫЕ СТАТЬИ |