Daily 2018-12-12
TIL
c++ 사각형 그리기
#include "pch.h"
#include <iostream>
#include <math.h>
typedef struct _Point {
int posX;
int posY;
} Point;
class MyRect {
private:
Point myPoints[4];
bool validateRect(Point* points);
int rectType;
double getDistance(Point pointA, Point pointB);
double getPowOfDistance(Point pointA, Point pointB);
public:
enum {
RECT_TYPE_NORMAL = 1,
RECT_TYPE_TILTED = 2
};
MyRect(Point* points);
double CalRectArea();
};
// swift에서는 filter를 사용해서 자체 반복문으로 구할 수 있지만.
// c++의 경우 filter가 없음으로 하나하나 for문을 돌려야함.
bool MyRect::validateRect(Point * points)
{
Point sortedPoints[4];
Point swpPoint;
for (int i = 0; i < 4; i++) {
sortedPoints[i] = points[i];
}
// 사각형 네 점을 기준으로 X값 순으로 정렬하고
// X값이 같을경우 다시 Y로 정렬
// 즉, sortedPoints[0]에는 X,Y좌표가 가장 작은 좌표가 들어있고.
// sortedPoints[3]에는 X,Y좌표가 가장 큰 좌표가 들어있음.
for (int i = 0; i < 3; i++) {
for (int j = 0; j<3-i; j++) {
if (sortedPoints[j].posX > sortedPoints[j + 1].posX) {
swpPoint = sortedPoints[j];
sortedPoints[j] = sortedPoints[j + 1];
sortedPoints[j + 1] = swpPoint;
}
else if (sortedPoints[j].posX == sortedPoints[j + 1].posX) {
if (sortedPoints[j].posY > sortedPoints[j + 1].posY) {
swpPoint = sortedPoints[j];
sortedPoints[j] = sortedPoints[j + 1];
sortedPoints[j + 1] = swpPoint;
}
}
}
}
//for (int i = 0; i < 4; i++) {
// printf("x : %d, y : %d\n", sortedPoints[i].posX, sortedPoints[i].posY);
//}
// 직사각형 조건.
// 대각선 2개의 길이가 같고 사각형 4개의 각이 전부 직각(90도)여야 함.
// 대각선 2개는 길이 구해서 비교하면 됨. sortedPoints[0]부터 sortedPoints[3]의 거리와
// sortedPoints[1]부터 sortedPoints[2]까지의 거리를 비교.
// 사각형의 4개의 각은 서로 마주보고 있는 부분의 각도가
// 둘다 직각(90도)이면 사각형안의 모든 각은 전부 직각
// 각이 직간인지 확인하는 방법은 피타고라스 정리를 이용합니다. 각이 직각이면 A^2 = B^2 + C^2이니까
// 반대로 말하면 A^2 = B^2 + C^2 식을 만족하면 각이 직각
// 조건이 참이 아니면 일반적으로 들어오는 사각형 좌표 체크를 위해 다음 블럭 진행.
// 좌표를 그림으로 그리면.
// myPoints[1] myPoints[3]
//
// myPoints[0] myPoints[2]
// 대각선 2개의 길이 비교.
double diagonalA = getDistance(sortedPoints[0], sortedPoints[3]);
double diagonalB = getDistance(sortedPoints[1], sortedPoints[2]);
// lineA = sortedPoints[0]과 sortedPoints[1]의 거리
double powOfLineA = getPowOfDistance(sortedPoints[0], sortedPoints[1]);
// lineB = sortedPoints[0]과 sortedPoints[2]의 거리
double powOfLineB = getPowOfDistance(sortedPoints[0], sortedPoints[2]);
// lineC = sortedPoints[3]과 sortedPoints[1]의 거리
double powOfLineC = getPowOfDistance(sortedPoints[3], sortedPoints[1]);
// lineD = sortedPoints[3]과 sortedPoints[2]의 거리
double powOfLineD = getPowOfDistance(sortedPoints[3], sortedPoints[2]);
double sumOfLineAB = powOfLineA + powOfLineB;
double sumOfLineCD = powOfLineC + powOfLineD;
double powOfDiagonalB = getPowOfDistance(sortedPoints[1], sortedPoints[2]);
// 두 대각선이 일치하고 sumOfLineAB와 sumOfLineCD가 각각 powOfDiagonalB와 일치하면 내 각이 직각
// 결과가 참이면 클래스 내부 변수에 값 저장.
if ((diagonalA == diagonalB) && (sumOfLineAB == powOfDiagonalB) && (sumOfLineCD == powOfDiagonalB)) {
for (int i = 0; i < 4; i++) {
myPoints[i] = sortedPoints[i];
}
}
return false;
}
// getDistance랑 getPowOfDistance를 2개로 나눈 이유는
// getPowDistance는 각 lineA의 제곱과 lineB의 제곱을 합친 값인데 이를 sqrt를 사용하면 값이 소수단위로 들어감.
// 근데 사각형 판별 식에서 사용할때에는 sqrt하지 않은 값이 필요함. sart한 값을 다시 pow하면 값의 소수점이 미묘하게 다르기 때문에
// 별도로 함수를 구현하여서 사용하여 비교.
double MyRect::getDistance(Point pointA, Point pointB)
{
return sqrt(getPowOfDistance(pointA, pointB));
}
double MyRect::getPowOfDistance(Point pointA, Point pointB)
{
int lineA = 0;
int lineB = 0;
lineA = abs(pointB.posX - pointA.posX);
lineB = abs(pointB.posY - pointA.posY);
return pow(lineA, 2) + pow(lineB, 2);
}
MyRect::MyRect(Point * points)
{
memset(myPoints, 0x00, sizeof(myPoints));
this->rectType = validateRect(points);
}
double MyRect::CalRectArea()
{
double lineA = getDistance(myPoints[0], myPoints[1]);
double lineB = getDistance(myPoints[0], myPoints[2]);
return lineA * lineB;
}
int main()
{
Point points[4];
points[0].posX = 2;
points[0].posY = 0;
points[1].posX = 0;
points[1].posY = 2;
points[2].posX = 3;
points[2].posY = 5;
points[3].posX = 5;
points[3].posY = 3;
//points[0].posX = 10;
//points[0].posY = 10;
//points[1].posX = 22;
//points[1].posY = 10;
//points[2].posX = 22;
//points[2].posY = 18;
//points[3].posX = 10;
//points[3].posY = 18;
MyRect myRect(points);
int rectArea = myRect.CalRectArea();
printf("area = %d\n", rectArea);
}
Written on December 12, 2018