Monthly Archive for April, 2007

Area of a triangle via the cross product

막상 3D 상의 임의의 세 점으로 구성된 삼각형의 넓이를 구하려고 하면 좀처럼 마땅한 방법이 떠오르지 않는다. 여기에 비교적 간단한 방법으로 공간상의 삼각형 넓이를 구하는 방법을 소개한다

공간상의 두 벡터 P,Q 가 주어졌을때, 외적(cross product) 은 다음의 식을 만족한다.

1195641316

위식의 우변을 잘 살펴보면 외적 PxQ 의 크기가 P와 Q에 의해 만들어지는 평행사변형의 넓이와 같음을 알수 있다. 이를 이용하면 꼭지점이 P,Q,R 인 임의의 삼각형의 넓이A를 다음과 같은 식에 의해 계산할 수 있다.

1358145576

예를 들어 P(4, 2, -1), Q(-1, 4, 2), R(2, 1, -4) 같이 세점으로 구성된 삼각형 넓이를 구해보면,

PQ
= [-1 - 4]i + [4- 2]j + [2- (-1)]k = -5i +2j + 3k.

PR = [2 - 4]i + [1 - 2]j + [-4 - (-1)]k = -2ij – 3k.

PQ X PR = <2*(-3)-3*(-1) , 3*(-2)-(-5)*(-3) , (-5)*(-1)-2*(-2)>
=  <-3,-21,-1>

A=1/2 * sqrt( (-3)*(-3) + (-21)*(-21) + (-1)*(-1) ) = 10.618

Template method pattern

Template method 패턴은 디자인 패턴 중에서도 가장 기본이 되는 패턴중에 하나다.
템플릿이란 단어에서 유추할 수 있듯이 어떤 일정한 틀을 기본으로 클래스를 구성하는 방식이다.
추상클래스(Abstract class) 에 정의되어있는 Abstract method 를 기반으로 알고리즘을 구성하는 template method 를 만들어 동작시키는 것이다. 다시말해 알고리즘의 캡슐화(encapsulation) 라고 할수 있다.

추상클래스(Abstract class) 에서는 단지 알고리즘만 기술하는 역할만 한다. 실제 구현은 서브클래스 (Concrete class) 에서 기술한다. 따라서 Template method 를 이용하면 알고리즘의 구조는 유지하면서 서브클래스에서 추상메소드를 오버라이드하여 재정의 할 수 있다.
서브클래스에서 행동을 지정할 수 있게 하면서도 코드의 재사용이 가능한 특징으로  Template method 패턴은 framework 를 제작하는데 자주 등장한다.

플래시에서는 abstract 키워드가 지원되지 않지만 개념상 큰차이없이 패턴을 사용할 수 있다.

<Abstract class>

class AbstractButton {
 
 private var _mc:MovieClip;
 
 public function setController(inMc : MovieClip) : Void {
  _mc=inMc;
 }
 public function getController() : MovieClip {
  return _mc;
 }
 
 //Constructor function
 function AbstractButton(inMc:MovieClip){
  setController(inMc);
  setButton();
 }
 
 //Template method
 public function setButton():Void{
     getController().onRollOver=Delegate.create(this,onRollOver);
     getController().onRollOut=Delegate.create(this,onRollOut);
     getController().onRelease=Delegate.create(this,onRelease);
     getController().onReleaseOutside=Delegate.create(this,onReleaseOutside);
 
 }
 
 public function onRollOver() : Void{
  // override in sub-class
  throw new Error("Abstract method!!!!!");
 }
  public function onRollOut() : Void{
   // override in sub-class
  throw new Error("Abstract method!!!!!");
 }
  public function onRelease() : Void{
  // override in sub-class
  throw new Error("Abstract method!!!!!");
 }
  public function onReleaseOutside() : Void{
   // override in sub-class
  throw new Error("Abstract method!!!!!");
 }
 
  public function enabled(mode:Boolean):Void{
  // override in sub-class
  throw new Error("Abstract method!!!!!");
 }
 
}

<Concrete class>

class ConcreteButton extends AbstractButton{
 
function ConcreteButton(inMc:MovieClip){
super(inMc);
}
 
public function onRollOver() : Void{
getController().gotoAndPlay("over");
}
 
public function onRollOut() : Void{
getController().gotoAndPlay("out");
}
 
public function onRelease() : Void{
getController().gotoAndPlay("release");
}
 
public function onReleaseOutside() : Void{
 
}
 
public function enabled(mode:Boolean):Void{
getController().enabled=mode;
}
 
}

위 sample 은 버튼을 구성하는 간단한 클래스이다.
플래시에서 Interaction 을 구현할때 거의 대부분버튼을 구현하여 접근한다. 일반적으로 버튼 액션을 구현하려면 버튼 인스턴스나 무비클립 인스턴스를 통해 버튼 이벤트를 주어서 사용하지만 그럴경우 제어해야할 버튼이 많아지면 코드길이가 늘어날 뿐더러 코드 유연성이 떨어지게 된다.

실제 버튼을 구현하려면 추상클래스를 확장하여 추상메소드를 구현하기만 하면 된다.
추상클래스의 추상메소드의 정의는 개발자가 신중히 결정해서 정해야한다. 추상메소드가 너무 많게 되면 서브클래스에서 구현해야할 코드가 많아져 불편한점이 있을 수 있다. 반대로 너무 추상메소드 자체를 큰 덩어리로 나누게되면 유연성을 떨어뜨리게 된다.