Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/main/java/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import coordinate.PointMaker;
import coordinate.GeometricElement;
import coordinate.GeometricFactory;
import coordinate.Point;
import util.Plate;
import util.Terminal;

import java.io.IOException;

public class Main {
public static void main(String[] args) throws IOException {
String in = Terminal.in("좌표를 입력하세요." + System.lineSeparator());
Point[] points = PointMaker.toPoints(in);
Plate plate = new Plate();
plate.drawPoints(points);
plate.print();
GeometricElement geometricElement = GeometricFactory.getGeometricElement(points);
geometricElement.printCalculateResult();
}
}
7 changes: 7 additions & 0 deletions src/main/java/coordinate/GeometricElement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package coordinate;

public interface GeometricElement {
double calculate();

void printCalculateResult();
}
35 changes: 35 additions & 0 deletions src/main/java/coordinate/GeometricFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package coordinate;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import static exception.ExceptionMessage.NO_LINE_OR_SHAPE;

public class GeometricFactory {

private final static Map<Integer, Class<? extends GeometricElement>> GEOMETRIC_ELEMENTS = new HashMap<>();

static {
int linesPointCount = 2;
int rectanglesPointCount = 4;
int trianglesPointCount = 3;

GEOMETRIC_ELEMENTS.put(linesPointCount, Line.class);
GEOMETRIC_ELEMENTS.put(rectanglesPointCount, Rectangle.class);
GEOMETRIC_ELEMENTS.put(trianglesPointCount, Triangle.class);
}

public static GeometricElement getGeometricElement(Point[] points) {
if (!GEOMETRIC_ELEMENTS.containsKey(points.length)) {
throw new ArithmeticException(NO_LINE_OR_SHAPE.getMessage());
}

try {
Class<? extends GeometricElement> geometricElementClass = GEOMETRIC_ELEMENTS.get(points.length);
return geometricElementClass.getDeclaredConstructor(Point[].class).newInstance((Object) points);
} catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
}
35 changes: 35 additions & 0 deletions src/main/java/coordinate/Line.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package coordinate;

import util.Terminal;

import java.util.Arrays;

public class Line implements GeometricElement {
private final Point[] points;

protected Line(Point[] in) {
points = Arrays.copyOf(in, 2);
}

public Line(Point point1, Point point2) {
this(new Point[]{point1, point2});
}
Comment on lines +14 to +16
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 진짜 깔끔한 코드인듯! 멋집니다.


public Point[] getEndPoints() {
return Arrays.copyOf(points, 2);
}

@Override
public double calculate() {
int dx = points[0].getX() - points[1].getX();
int dy = points[0].getY() - points[1].getY();

return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
}

@Override
public void printCalculateResult() {
String message = String.format("두 점 사이의 거리는 %.6f", this.calculate());
Terminal.out(message);
}
}
37 changes: 37 additions & 0 deletions src/main/java/coordinate/Point.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package coordinate;

public class Point {
private final int x;
private final int y;

public Point(int x, int y) {
this.x = x;
this.y = y;
}

public int getX() {
return this.x;
}

public int getY() {
return this.y;
}

@Override
public int hashCode() {
int result = 17;
result = 37 * result + this.x;
result = 37 * result + this.y;
return result;
}

@Override
public boolean equals(Object obj) {
if (obj.getClass() != Point.class) {
return false;
}

Point compare = (Point) obj;
return compare.x == this.x && compare.y == this.y;
}
}
69 changes: 69 additions & 0 deletions src/main/java/coordinate/PointMaker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package coordinate;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static exception.ExceptionMessage.*;

public class PointMaker {

public static Point[] toPoints(String input) {
if (isBlank(input)) {
throw new IllegalArgumentException(NO_INPUT.getMessage());
}

Pattern pattern = Pattern.compile("\\(([^)]+)\\)");
Matcher matcher = pattern.matcher(input);

int hit = 0;
while (matcher.find()) {
hit++;
}
Point[] result = new Point[hit];

matcher.reset();
for (int i = 0; i < result.length && matcher.find(); i++) {
String[] coordinate = matcher.group().replaceAll("[()]", "")
.split(",");

if (coordinate.length != 2 || isBlank(coordinate[0]) || isBlank(coordinate[1])) {
throw new ArithmeticException(NO_TWO_DIMENSION_POINT.getMessage());
}

int x = validationNumberAndGet(coordinate[0]);
int y = validationNumberAndGet(coordinate[1]);
result[i] = new Point(x, y);
}

return result;
}

private static boolean isBlank(String in) {
return in == null || in.trim().isEmpty();
}

private static int validationNumberAndGet(String in) {
in = in.trim();
// "-" 부호만 입력 했을 때는 0으로 간주됨
if (in.charAt(0) != '-' && !Character.isDigit(in.charAt(0))) {
throw new ArithmeticException(INPUT_NOT_NUMBER.getMessage());
}

for (int i = 1; i < in.length(); i++) {
boolean isDigit = Character.isDigit(in.charAt(i));
if (!isDigit) {
throw new ArithmeticException(INPUT_NOT_NUMBER.getMessage());
}
}

int rangeMin = 1;
int rangeMax = 24;

int num = Integer.parseInt(in);
if (num < rangeMin || num > rangeMax) {
throw new IllegalArgumentException(String.format(INPUT_OUT_OF_RANGE.getMessage(), rangeMin, rangeMax));
}

return num;
}
}
102 changes: 102 additions & 0 deletions src/main/java/coordinate/Rectangle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package coordinate;

import util.Terminal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static exception.ExceptionMessage.NO_SHAPE;

public class Rectangle extends Shape implements GeometricElement {

protected Rectangle(Point[] in) {
super(in);
List<Point> points = new ArrayList<>(4);
Collections.addAll(points, in);
getSortedVertexes(points);
validate();
}

/**
* 네 점을 다음과 같이 대칭 점끼리 묶어서 정렬
* 1. 한 점을 고른다
* 2. 다른 세 점 중 앞서 정한 한 점과 가장 멀리 있는 한점을 찾는다 (고른 점과 대칭점)
* 3. 위의 두 점을 순서 대로 배열에 저장
* 4. 나머지 두 점을 이어서 배열에 저장 (나머지 두점은 또 서로의 대칭점)
* @param points 입력 받은 점들
*/
private void getSortedVertexes(List<Point> points) {
Point base = points.get(0);
points.remove(base);

Point opposite = points.get(0);
double maxLength = new Line(base, opposite).calculate();
for (int i = 1; i < points.size(); i++) {
double compareLength = new Line(base, points.get(i)).calculate();

if (maxLength < compareLength) {
maxLength = compareLength;
opposite = points.get(i);
}
}

points.remove(opposite);

vertexes[0] = base;
vertexes[1] = opposite;
vertexes[2] = points.get(0);
vertexes[3] = points.get(1);
}

@Override
public void validate() {
boolean result1;
boolean result2;

result1 = isRightAngle(new Line(vertexes[0], vertexes[2]), new Line(vertexes[0], vertexes[3]));
result2 = isRightAngle(new Line(vertexes[1], vertexes[2]), new Line(vertexes[1], vertexes[3]));

if (!(result1 && result2)) {
throw new ArithmeticException(String.format(NO_SHAPE.getMessage(), this.getClass().getSimpleName()));
}
}

private boolean isRightAngle(Line line1, Line line2) {
Point[] p1 = line1.getEndPoints();
double angle1 = getAngle(p1[0], p1[1]);

Point[] p2 = line2.getEndPoints();
double angle2 = getAngle(p2[0], p2[1]);

double betweenAngle = Math.abs(angle1 - angle2);
return betweenAngle == 90;
}

private double getAngle(Point start, Point end) {
double dx = start.getX() - end.getX();
double dy = start.getY() - end.getY();

double angle = Math.atan2(dy, dx) * (180.0 / Math.PI);
return Math.abs(angle);
}

@Override
public Point[] getVertex() {
return Arrays.copyOf(vertexes, 4);
}

@Override
public double calculate() {
int width = vertexes[0].getX() - vertexes[2].getX();
int height = vertexes[0].getY() - vertexes[3].getY();
return width * height;
}

@Override
public void printCalculateResult() {
String message = String.format("사각형 넓이는 %.0f", this.calculate());
Terminal.out(message);
}
}
14 changes: 14 additions & 0 deletions src/main/java/coordinate/Shape.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package coordinate;

public abstract class Shape {

protected final Point[] vertexes;

protected Shape(Point[] in) {
this.vertexes = new Point[in.length];
}

abstract void validate();

abstract Point[] getVertex();
}
55 changes: 55 additions & 0 deletions src/main/java/coordinate/Triangle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package coordinate;

import util.Terminal;

import java.util.Arrays;

import static exception.ExceptionMessage.NO_SHAPE;

public class Triangle extends Shape implements GeometricElement {

protected Triangle(Point[] in) {
super(in);
System.arraycopy(in, 0, vertexes, 0, in.length);
validate();
}

@Override
public double calculate() {
double a = new Line(vertexes[0], vertexes[1]).calculate();
double b = new Line(vertexes[0], vertexes[2]).calculate();
double c = new Line(vertexes[1], vertexes[2]).calculate();

double s = (a + b + c) / 2;

return Math.sqrt(s * (s - a) * (s - b) * (s - c));
}

@Override
public void printCalculateResult() {
String message = String.format("삼각형 넓이는 %.1f", this.calculate());
Terminal.out(message);
}

@Override
public void validate() {
int dx = vertexes[0].getX() - vertexes[1].getX();
int dy = vertexes[0].getY() - vertexes[1].getY();

double slope1 = Math.abs((double) dy / dx);

dx = vertexes[0].getX() - vertexes[2].getX();
dy = vertexes[0].getY() - vertexes[2].getY();

double slope2 = Math.abs((double) dy / dx);

if (slope1 == slope2) {
throw new ArithmeticException(String.format(NO_SHAPE.getMessage(), this.getClass().getSimpleName()));
}
}

@Override
public Point[] getVertex() {
return Arrays.copyOf(vertexes, 3);
}
}
Loading