이 과제는 3 단계로 이루어진다. 각 단계를 완수할 때마다 부분점수가 주어지지만, 주의할 점은 실행가능한 코드가 아니면 0점이라는 것이다.
예를 들어 1단계까지만 했다면 1단계가 완성되어 실행가능한 형태의 코드로 제출해야 한다.
1단계를 수행한 후 2단계를 하려다 만 코드라면 점수를 얻지 못하고 0점이다.
1단와와 2단계를 완료한 직후에 파일을 따로 저장해 놓고 그 다음 단계 작업을 진행하는 것을 추천한다.
수정해도 된다고 밝힌 클래스의 정의만 수정해야 한다.
여러개의 ShapeObj2D로 구성된 GroupObj2D의 정의를 완성하라. 즉, toString 및 Displayable과 ToSVG에서 오버라이드하라고 요구하는 메소드를 구현하라는 뜻이다.
테스트로 3개 이상의 ShapeObj2D를 함께 묶어놓은 GroupObj2D 오브젝트를 정의하여 display 해보라.
HW3에서 작성한 3가지 변환함수 메소드를 Trans2D 인터페이스로 추상화하라.
그리고 ShapeObj2D와 GroupObj2D 클래스가 공통적인 인터페이스 Trans2D를 구현하도록 두 클래스의 정의를 수정하라.
이차원 변환에 테스트는 Level 1에서 정의했던 GroupObj2D 오브젝트에 대해 수행하면 된다.
GroupObj2D 클래스의 멤버 변수 배열인 objects에 ShapeObj2D 인스턴스 뿐만 아니라 GroupObj2D 인스턴스도 포함될 수 있도록 GroupObj2D 클래스의 정의를 개선하라. 필요하다면 ShapeObj2D 클래스의 (심하게 뜯어고치는 건 안되고) 정의를 약간은 수정해도 된다.
import org.apache.commons.lang3.tuple.*;
interface Displayable {
public void display();
}
interface ToSVG {
public String toSVG();
// points of the bounding rectangle
public Integer minX();
public Integer minY();
public Integer maxX();
public Integer maxY();
// default methods using above four abstract methods
default public Pair<Integer,Integer> minPoint() {
return Pair.of( this.minX(), this.minY() );
}
default public Pair<Integer,Integer> maxPoint() {
return Pair.of( this.maxX(), this.maxY() );
}
}
import io.github.spencerpark.ijava.runtime.*;
import org.apache.commons.lang3.tuple.*;
abstract class Shape {
// 인스턴스 변수
int width; // 양과 음의 정수값 모두 가능
int height; // 양과 음의 정수값 모두 가능
String fill; // 도형의 안쪽을 채우는 색깔
double opacity; // 도형을 그렸을 때 투명도
Shape(int width, int height, String fill, double opacity) {
this.width = width;
this.height = height;
this.fill = fill;
this.opacity = opacity;
}
// 추상 메소드
abstract double area(); // 넓이 계산
abstract String toSVGshape(Pair<Integer,Integer> point); // SVG 기본 도형 태그 생성
@Override
public String toString() {
return super.toString()
+ String.format("(width=%d, height=%d, fill=%s, opacity=%f)",
width, height, fill, opacity );
}
void display() { // 이미지 형태로 보여주기 위한 메소드
Pair<Integer,Integer> point = Pair.of( (width<0)? Math.abs(width) :0,
(height<0)? Math.abs(height):0 );
String svgStr = String.format(
"<svg width='%d' height='%d'>%s</svg>",
Math.abs(width), Math.abs(height), this.toSVGshape(point) );
Display.display(svgStr,"text/html");
}
}
class RightTri extends Shape {
RightTri(int width, int height, String fill, double opacity) {
super(width, height, fill, opacity);
}
@Override
double area() { return Math.abs(width * height) / 2; } // 삼각형 넓이공식에 맞게
@Override
String toSVGshape(Pair<Integer,Integer> point) {
int x0 = point.getLeft();
int y0 = point.getRight();
return
String.format("<circle cx='%d' cy='%d' r='3' fill='%s' opacity='%f' />",
x0,y0, fill, opacity)
+
String.format("<polygon points='%d,%d %d,%d %d,%d' fill='%s' opacity='%f' />",
x0,y0, x0+width,y0, x0,y0+height, fill, opacity );
}
}
class Rectangle extends Shape {
Rectangle(int width, int height, String fill, double opacity) {
super(width, height, fill, opacity);
}
@Override
double area() { return Math.abs(width * height); } // 직사각형 넓이공식에 맞게
@Override
String toSVGshape(Pair<Integer,Integer> point) {
int x0 = point.getLeft();
int y0 = point.getRight();
return
String.format("<circle cx='%d' cy='%d' r='3' fill='%s' opacity='%f' />",
x0,y0, fill, opacity)
+
String.format("<rect x='%d' y='%d' width='%d' height='%d' fill='%s' opacity='%f' />",
(width>0)? x0: x0+width, (height>0)? y0: y0+height,
Math.abs(width), Math.abs(height), fill, opacity );
}
}
class ShapeObj2D implements Displayable, ToSVG {
Pair<Integer, Integer> point;
Shape shape;
ShapeObj2D(Pair<Integer, Integer> point, Shape shape) {
this.point = point;
this.shape = shape;
}
@Override
public String toString() {
return
super.toString()
+
String.format("( point=%s, shape=%s )",
point.toString(), shape.toString() );
}
// Displayable에서 오버라이드하라고 요구하는 메소드를 구현
@Override // 지금은 무조건 원점부터 1사분면만 그리고 있다고 생각하고 작성하고 있음
public void display() { // 이미지 형태로 보여주기 위한 메소드
String svgStr = String.format(
"<svg width='%d' height='%d'>%s</svg>",
maxX(), maxY(), this.toSVG() );
Display.display(svgStr,"text/html");
}
// ToSVG에서 오버라이드하라고 요구하는 메소드들을 구현
@Override
public String toSVG() { return shape.toSVGshape(point); }
// points of the bounding rectangle
@Override
public Integer minX() { return Math.min(point.getLeft(), point.getLeft()+shape.width); }
@Override
public Integer minY() { return Math.min(point.getRight(), point.getRight()+shape.height); }
@Override
public Integer maxX() { return Math.max(point.getLeft(), point.getLeft()+shape.width); }
@Override
public Integer maxY() { return Math.max(point.getRight(), point.getRight()+shape.height); }
/*
// Trans2D에서 오버라이드하라고 요구하는 메소드들을 구현
*/
}
class GroupObj2D implements Displayable, ToSVG {
ShapeObj2D [] objects;
GroupObj2D(ShapeObj2D[] objects) {
this.objects = objects;
}
/*
@Override
public String toString() { ... }
*/
/*
// Displayable에서 오버라이드하라고 요구하는 메소드를 구현
*/
/*
// ToSVG에서 오버라이드하라고 요구하는 메소드들을 구현
*/
/*
// Trans2D에서 오버라이드하라고 요구하는 메소드들을 구현
*/
}
| class GroupObj2D implements Displayable, ToSVG { | ShapeObj2D [] objects; | | GroupObj2D(ShapeObj2D[] objects) { | this.objects = objects; | } | | /* | @Override | public String toString() { ... } | */ | | /* | // Displayable에서 오버라이드하라고 요구하는 메소드를 구현 | */ | | /* | // ToSVG에서 오버라이드하라고 요구하는 메소드들을 구현 | */ | | /* | // Trans2D에서 오버라이드하라고 요구하는 메소드들을 구현 | */ | } GroupObj2D is not abstract and does not override abstract method display() in Displayable