Skip to content

Instantly share code, notes, and snippets.

@Novakov
Created March 8, 2013 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Novakov/5116655 to your computer and use it in GitHub Desktop.
Save Novakov/5116655 to your computer and use it in GitHub Desktop.
#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