Created
March 8, 2013 14:09
-
-
Save Novakov/5116655 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "GK lab2.h" | |
#include <vector> | |
typedef Gdiplus::Point Point; | |
typedef std::pair<Point, Point> Line; | |
typedef std::vector<std::pair<Point, Point>> Lines; | |
enum FlagEnum {kNon = 0, kLeft = 1, kRight = 2, kDown = 4, kUp = 8}; | |
Lines initial_line_set; // randomly generated lines | |
Lines lines_in_frame; // clipping output, draw red | |
Lines lines_out_frame; // clipping output, draw green | |
Lines windowing_line_set; // windowing output, draw blue | |
Point frame_corners[2]; // left-up, right-up, left-down, right-down | |
Point port_corners[2]; | |
unsigned short initial_line_number = 8; // defines how many initial lines will be created | |
#define has(byte, flag) ((byte & flag) == flag) | |
#define point_pair(x1, y1, x2, y2) (std::make_pair(Point(x1, y1), Point(x2,y2))) | |
//////////////////////////////////////////////////////////////////////////////// | |
// function declarations | |
void SetFrameCorners(const unsigned short& client_area_width, | |
const unsigned short& client_area_height, | |
Point frame_corners[2]); | |
void GenerateLineSet(const unsigned short& x_min, const unsigned short& y_min, | |
const unsigned short& x_max, const unsigned short& y_max, | |
const unsigned short& number_of_lines, | |
Lines& line_set); | |
void Code(const int& x, const int& y, Point frame_corners[2], unsigned char& bit_flag); | |
void Clipping(const Lines& set, Point frame_corners[2], Lines& in, Lines& out); | |
void Windowing(Point window[2], Point port[2], const Lines& in, Lines& out); | |
//////////////////////////////////////////////////////////////////////////////// | |
// | |
void SetFrameCorners(const unsigned short& client_area_width, | |
const unsigned short& client_area_height, | |
Point frame_corners[2]) | |
{ | |
unsigned short frame_width = client_area_width / 5; | |
unsigned short frame_height = client_area_height / 4; | |
frame_corners[0].X = 2 * frame_width; // left | |
frame_corners[1].X = 3 * frame_width; // right | |
frame_corners[0].Y = frame_height; // up | |
frame_corners[1].Y = 3 * frame_height; // down | |
} | |
// | |
void GenerateLineSet(const unsigned short& x_min, const unsigned short& y_min, | |
const unsigned short& x_max, const unsigned short& y_max, | |
const unsigned short& number_of_lines, | |
Lines& line_set) | |
{ | |
unsigned short delta_x = x_max - x_min; | |
unsigned short delta_y = y_max - y_min; | |
// reset and allocate vector | |
line_set.clear(); | |
line_set.resize(number_of_lines); | |
for (unsigned short i=0; i < number_of_lines; ++i) | |
{ | |
line_set[i].first.X = x_min + rand() % delta_x; | |
line_set[i].first.Y = y_min + rand() % delta_y; | |
line_set[i].second.X = x_min + rand() % delta_x; | |
line_set[i].second.Y = y_min + rand() % delta_y; | |
} | |
// little helper (1) | |
if (line_set.size() >= 1) | |
{ | |
line_set[0].first.X = 147; | |
line_set[0].first.Y = 50; | |
line_set[0].second.X = 253; | |
line_set[0].second.Y = 250; | |
} | |
// little helper (2) | |
if (line_set.size() >= 2) | |
{ | |
line_set[1].first.X = 147; | |
line_set[1].first.Y = 250; | |
line_set[1].second.X = 253; | |
line_set[1].second.Y = 50; | |
} | |
}; | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// | |
// | |
// Function setting bit flags for the given point (point coordinates with respect to the clipping frame) | |
// | |
// IN: x, y - test point coordinates | |
// IN: frame_corners - clipping frame boundary points | |
// OUT: bit_flag - calculated point properties (bit flags) | |
// | |
// | |
// | |
// Funkcja ustawiająca flagi bitowe dla danego punktu (współrzędne punktu względem ramki obcinającej) | |
// | |
// IN: x, y - współrzędne punktu | |
// IN: frame_corners - punkty ograniczające ramkę obcinającą | |
// OUT: bit_flag - wyliczone właściwości punktu (flagi bitowe) | |
// | |
// | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
void Code(const int& x, const int& y, Point frame_corners[2], unsigned char& bit_flag) | |
{ | |
bit_flag = kNon; | |
// | |
// STUDENT'S CODE / KOD STUDENTA | |
// | |
// Useful code snippets / użyteczne fragmenty kodu | |
// | |
// if (x < frame_corners[0].X) | |
// | |
// bit_flag |= kLeft; // kRight / kUp / kDown | |
// | |
// ... // | |
if(x < frame_corners[0].X) | |
{ | |
bit_flag |= kLeft; | |
} | |
else if(x > frame_corners[1].X) | |
{ | |
bit_flag |= kRight; | |
} | |
if(y < frame_corners[0].Y) | |
{ | |
bit_flag |= kUp; | |
} | |
else if(y > frame_corners[1].Y) | |
{ | |
bit_flag |= kDown; | |
} | |
} | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// | |
// | |
// Function performing the actual clipping process | |
// | |
// IN: set - set of segments that will be subdivided to (in)side and (out)side set | |
// IN: frame_corners - clipping frame boundary points | |
// OUT: in - new set of segments, inside the clipping region | |
// OUT: out - new set of segments, outside the clipping region | |
// | |
// | |
// Funkcja wykonująca właściwy proces obcinania | |
// | |
// IN: set - zbiór odcinków do podzielenia na wewnętrzne (in) i zewnętrzne (out) | |
// IN: frame_corners - punkty ograniczające ramkę obcinającą | |
// OUT: in - nowy zestaw odcinków, wewnątrz regionu obcinania | |
// OUT: out - nowy zestaw odcinków, poza regionem obcinania | |
// | |
// | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
void Clipping(const Lines& set, Point frame_corners[2], Lines& in, Lines& out) | |
{ | |
// reset output vectors | |
in.clear(); | |
out.clear(); | |
for(auto z = set.begin(); z != set.end(); ++z) | |
{ | |
std::pair<Point, Point> v = *z; | |
unsigned char c1; | |
unsigned char c2; | |
Code(v.first.X, v.first.Y, frame_corners, c1); | |
Code(v.second.X, v.second.Y, frame_corners, c2); | |
while((c1!= kNon) || (c2 != kNon)) | |
{ | |
if((c1 & c2) != kNon) | |
break; | |
int y; | |
int x; | |
unsigned char c = c1; | |
if(c == kNon) | |
{ | |
c = c2; | |
} | |
if(has(c, kLeft)) | |
{ | |
y = v.first.Y + (v.second.Y - v.first.Y) * (frame_corners[0].X - v.first.X) / (v.second.X - v.first.X); | |
x = frame_corners[0].X; | |
} | |
else if(has(c, kRight)) | |
{ | |
y = v.first.Y + (v.second.Y - v.first.Y) * (frame_corners[1].X - v.first.X) / (v.second.X - v.first.X); | |
x = frame_corners[1].X; | |
} | |
if(has(c, kDown)) | |
{ | |
x = v.first.X + (v.second.X - v.first.X) * (frame_corners[1].Y - v.first.Y) / (v.second.Y - v.first.Y); | |
y = frame_corners[1].Y; | |
} | |
else if(has(c, kUp)) | |
{ | |
x = v.first.X + (v.second.X - v.first.X) * (frame_corners[0].Y - v.first.Y) / (v.second.Y - v.first.Y); | |
y = frame_corners[0].Y; | |
} | |
if(c == c1) | |
{ | |
v = std::make_pair(Point(x, y), v.second); | |
Code(x, y, frame_corners, c1); | |
} | |
else | |
{ | |
v = std::make_pair(v.first, Point(x, y)); | |
Code(x, y, frame_corners, c2); | |
} | |
} | |
if((c1 & c2) == kNon) | |
{ | |
in.push_back(v); | |
out.push_back(point_pair(z->first.X, z->first.Y, v.first.X, v.first.Y)); | |
out.push_back(point_pair(v.second.X, v.second.Y, z->second.X, z->second.Y)); | |
} | |
else | |
{ | |
out.push_back(v); | |
} | |
} | |
// | |
// STUDENT'S CODE / KOD STUDENTA | |
// | |
// Useful code snippets / użyteczne fragmenty kodu | |
// Code(x1, y1, frame_corners, c1); | |
// Code(x2, y2, frame_corners, c2); | |
// in.push_back(Line(Point(x1, y1), Point(x2, y2))); | |
// out.push_back(set[i]); | |
//for (auto iter = set.begin() ; iter != set.end() ; ++iter) | |
//{ | |
// // Współrzędna X (minimum) / X coordinate (minimum) | |
// (*iter).first.X | |
//} | |
// ... // | |
} | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// | |
// | |
// Function converting segment coordinates from selected SOURCE region, to DESTINATION region | |
// (taking some "view" region and rendering it to "port", thus "viewport") | |
// | |
// IN: window - boundary points for the SOURCE region (client area coordinates) | |
// IN: port - boundary points for the DESTINATION region (client area coordinates) | |
// IN: in - set of segments, inside the view region | |
// OUT: out - new set of segments, inside the port region | |
// | |
// | |
// Funkcja konwertująca współrzędne odcinka z regionu źródłowego (view), do regionu docelowego (port) | |
// | |
// IN: window - ppunkty ograniczające ramkę widoku (view) | |
// IN: port - punkty ograniczające ramkę obszaru docelowego (port) | |
// OUT: in - zestaw odcinków, wewnątrz regionu widoku | |
// OUT: out - nowy zestaw odcinków, wewnątrz regionu docelowego | |
// | |
// | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
void Windowing(Point window[2], Point port[2], const Lines& in, Lines& out) | |
{ | |
// reset output vector | |
out.clear(); | |
double a = (port[1].X - port[0].X) / (double)(window[1].X - window[0].X); | |
double b = -a * window[0].X + port[0].X; | |
double c = (port[0].Y - port[1].Y) / (double)(window[0].Y - window[1].Y); | |
double d = -c * window[1].Y + port[1].Y; | |
for(auto v = in.begin(); v != in.end(); ++v) | |
{ | |
out.push_back(point_pair | |
( | |
a * v->first.X + b, | |
c * v->first.Y + d, | |
a * v->second.X + b, | |
c * v->second.Y + d | |
)); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment