Daily 2018-12-11
TIL
c++ 언어로 사각형 그리기
#include "pch.h"
#include <iostream>
#include <math.h>
typedef struct _Point {
int posX;
int posY;
} Point;
class MyRect {
private:
Point myPoints[4];
int 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문을 돌려야함.
int MyRect::validateRect(Point * points)
{
// 가장 첫번째로 들어온 데이터를 기준으로 처리.
myPoints[0] = points[0];
//45도 정도 기울어진 형태의 직사각형 or 정사각형 처리.
Point symmPoint;
int symmPointIndex = 0;
bool sameXPos = false;
memset(&symmPoint, 0x00, sizeof(symmPoint));
// symmetry 단어 뜻 대칭, 약자로 symm 사용
// 좌표(45도 기울어지 사각형)는 4개의 점 중에서 2개는 X좌표가 같고 2개는 Y좌표가 같아야함.
// 첫번째로 우선 point0에 대칭되는 점을 찾는다.
// 대칭점이 X좌표가 같은지 Y좌표가 같은지 모르므로 우선 X먼저 비교하여 같은 지점을 찾는다.
for (int i = 1; i < 4; i++) {
if (points[0].posX == points[i].posX) {
symmPointIndex = i;
symmPoint = points[i];
// X좌표가 같은 경우 체크
sameXPos = true;
break;
}
}
// 만약 X좌표가 일치하는 좌표가 없다면 Y좌표를 비교.
if (symmPointIndex == 0) {
for (int i = 1; i < 4; i++) {
if (points[0].posY == points[i].posY) {
symmPointIndex = i;
symmPoint = points[i];
break;
}
}
}
// Y좌표를 비교해서 해당 인덱스가 존재하면 처리하고 아니면
// 일반적으로 들어오는 사각형 좌표 체크를 한다.
if (symmPointIndex != 0) {
int inputIndex = 0;
for (int i = 1; i < 4; i++) {
// 위에서 확인한 대칭하는 좌표는 필요 없음.
if (symmPointIndex == i) {
continue;
}
// 대칭으로 일치하는 것은 0, 1에 들어가있음.
// 일치하는걸 제외한 나머지를 2,3 번에 저장.
this->myPoints[2 + inputIndex] = points[i];
inputIndex++;
myPoints[0] = points[0];
myPoints[1] = symmPoint;
}
// sameXPos가 true라면 0,1번이 X좌표가 같아야하고, 2,3번이 Y좌표가 같아야함.
// false일 경우는 반대로, 0,1번이 Y좌표가 같아야하고, 2,3번이 X좌표가 같아야함.
bool checkPos = false;
if (sameXPos) {
if ((myPoints[0].posX == myPoints[1].posX) && (myPoints[2].posY == myPoints[3].posY)) {
checkPos = true;
}
}
else {
if ((myPoints[0].posY == myPoints[1].posY) && (myPoints[2].posX == myPoints[3].posX)) {
checkPos = true;
}
}
// 위의 조건이 참일 경우,
// 두 대각선의 길이를 비교하여 같으면서 각이 직각이여야 직각사각형으로 판별.
// 각이 직간인지 확인하는 방법은 피타고라스 정리를 이용합니다. 각이 직각이면 A^2 = B^2 + C^2이니까
// 반대로 말하면 A^2 = B^2 + C^2 식을 만족하면 각이 직갑
// 대각선의 양 끝쪽 각(즉 마주보고있는 각)이 둘다 직각(90도)이면 사각형안의 모든 각은 전부 직각
// 체크 후, 조건이 참이라면 RECT_TYPE_TILTED를 반환
// 조건이 참이 아니면 일반적으로 들어오는 사각형 좌표 체크를 위해 다음 블럭 진행.
// 좌표를 그림으로 그리면.
// myPoints[0] myPoints[3]
//
// myPoints[2] myPoints[1]
// 즉 각을 구하기 위해서는 diagnoalA의 제곱의 값과
if (checkPos) {
double diagonalA = getDistance(myPoints[0], myPoints[1]);
double diagonalB = getDistance(myPoints[2], myPoints[3]);
// lineA = myPoint[0]과 myPoint[3]의 거리
double powOfLineA = getPowOfDistance(myPoints[0], myPoints[3]);
// lineB = myPoint[0]과 myPoint[2]의 거리
double powOfLineB = getPowOfDistance(myPoints[0], myPoints[2]);
// lineC = myPoint[1]과 myPoint[2]의 거리
double powOfLineC = getPowOfDistance(myPoints[1], myPoints[2]);
// lineD = myPoint[1]과 myPoint[3]의 거리
double powOfLineD = getPowOfDistance(myPoints[1], myPoints[3]);
double powOfLineAB = powOfLineA + powOfLineB;
double powOfLineCD = powOfLineC + powOfLineD;
double powOfDiagonalB = getPowOfDistance(myPoints[2], myPoints[3]);
if ((diagonalA == diagonalB)&&(powOfLineAB == powOfDiagonalB)&&(powOfLineCD == powOfDiagonalB)) {
return RECT_TYPE_TILTED;
}
}
}
// 일반적으로 들어오는 사각형 좌표.
Point sameXPoint;
Point sameYPoint;
Point otherPoint;
memset(&sameXPoint, 0x00, sizeof(Point));
memset(&sameYPoint, 0x00, sizeof(Point));
memset(&otherPoint, 0x00, sizeof(Point));
// sameXPoint 구하는 for문.
for (int i = 1; i < 4; i++) {
if (points[0].posX == points[i].posX) {
sameXPoint = points[i];
break;
}
}
// sameYPoint 구하는 for문.
for (int i = 1; i < 4; i++) {
if (points[0].posY == points[i].posY) {
sameYPoint = points[i];
break;
}
}
// sameXPoint 구하는 for문.
for (int i = 1; i < 4; i++) {
if ((points[0].posX != points[i].posX)&& (points[0].posY != points[i].posY)){
otherPoint = points[i];
break;
}
}
// 좌표 최종 확인.
if ((otherPoint.posX == sameYPoint.posX) && (otherPoint.posY == sameXPoint.posY)) {
return RECT_TYPE_NORMAL;
}
return 0;
}
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()
{
if (this->rectType == RECT_TYPE_TILTED) {
double lineA = getDistance(myPoints[0], myPoints[1]);
double lineB = getDistance(myPoints[2], myPoints[3]);
return lineA * lineB / 2;
}
else if (this->rectType == RECT_TYPE_NORMAL) {
double lineA = getDistance(myPoints[0], myPoints[1]);
double lineB = getDistance(myPoints[0], myPoints[2]);
return lineA * lineB;
return 0;
}
else {
return 0;
}
}
int main()
{
Point points[4];
//확인 테스트
points[0].posX = 0;
points[0].posY = 3;
points[1].posX = 3;
points[1].posY = 0;
points[2].posX = 4;
points[2].posY = 2;
points[3].posX = 2;
points[3].posY = 4;
// 테스트 : 정상적으로 돌아갔던 좌표.
//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 11, 2018