블로그 이미지
.
속눈썹맨

공지사항

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

[CG]2006.5.9. MS Research Asia - Harry Shum

2006. 5. 9. 00:39 | Posted by 속눈썹맨

. 오늘 소개한 논문 2편
Yin Li, Jian Sun, Chi-Keung Tang and Heung-Yeung Shum. Lazy Snapping. SIGGRAPH 2004. (ACM Transaction on Graphics)  (Video 19M)
http://research.microsoft.com/research/pubs/view.aspx?pubid=1266
http://research.microsoft.com/~jiansun/papers/LazySnapping_SIGGRAPH04.pdf
http://research.microsoft.com/~jiansun/videos/ImageCompletion_tiny.wmv

Jian Sun, Lu Yuan, Jiaya Jia and Heung-Yeung Shum. Image Completion with Structure Propagation. SIGGRAPH 2005 (Video 56M).
http://research.microsoft.com/~jiansun/papers/ImageCompletion_SIGGRAPH05.pdf

. 참석자
신성용, 좌경룡, 홍세준, 최성희, 한환수, 김진수 교수님을 포함한
10여명의 CS 교수님들과 터만홀을 가득 채운 학생들.

. 관련 분야
Signal processing, Image processing, Computer Vision, Computer Graphics

. MSRA 소개
1998년 베이징에 설립, 200여명의 researchers, 2,000명의 intern students.
거기 있는 유명한 사람들 : SGI 설립자, IBM Deepblue 설계자 등..
주로 computer Graphics관련 분야를 집중적으로 연구함.
(UI, Digital Media, Digital Entertainment, Networking and systems, searching and mining)
중국 학생이 70%이상, official language는 english
2005년 Siggraph에 9편, SIGIR에 12편이 실림.
(전체 논문의 10%에 해당하는 엄청난 양임.)
World's hottest lab 등으로 잡지에 소개됨.

. TTG(Technology Transfor Group) : Parachut group
  Research를 product로 바꿈.                                  

. Dr. Harry Shum
CMU Robotics 전공, 4년전 신성용 교수님초대로 KAIST 방문
Managing Director MSRA(1999~2006)

. Prior, Context and Interactive Computer Vision
  완전 자동이 아니라 약간 step back해서 User의 입력을 약간 받아서
  쉽게 feedback해주고 잘 해보자.

. IBM : Image Based Modeling

. Lazy Snapping
Just draw two lines
In line와 out line만 그리면 됨.
Red line : What you want
Blue line : What you don't want
Lazy : 부지런하게 모든 boundary를 그리지 않고 선만 대충 그음.
Interactive Graph Cut

Divide and Conquer : Input -> Coarse Boundary -> Refine Boundary
Stroke Drawing <-> Graph cut Algorithm
Graph cut problem -> Per-Pixel Graph cut 대신 Pre-segmentation first
Energy Minimization E(x) = E1(Xi) + lE2(Xi, Xj)
E1 : difference
E2 : Similarity

Noting new algorithm, Present New system.

. 논문 잘 쓰는 법
Write -> Intoducting, Abstract, Summary -> Title
Good title is short title => 2 words, end with ing

. Image completion
Small Missing : Pixel-level, PDE based
Large Missing : how?
Curve-based : BP(Belief propagation) Algorithm
Our Motivation : Missing salient structures, fill-in
Abstract window, curve - a few curves - human specify that.
Structures completion befor texture complete
Fragment-based Image completion, Image Repairing, object Removal

Node Energy, Coherence Energy => Dynamic Programming
Graph Labeling, discretize nodes
Decouple Image into two part

Multiple Intersecting Curves
Loopy Belief Propagation
Tour Into pictures도 쉽게 가능

사진을 2장 찍은 것이 아니라 object를 지우고 그 부분을 메꿈.
자세히 비교하면 이상할 수도 있지만 결과 사진만 보면 매우 그럴듯 함.
걸리적거리는 사람이나 물체를 깔끔하게 지워버릴 수 있다.
Boundary를 바꾸고 싶을 때 가리고 새로 그리기만 하면 된다.

. 감상
마치 무슨 마법이나 장난을 보는 것 같다.
이런 신기한 툴이라면 누구나 써보고 싶어할만한 것 같다.
연구자나 사용자 모두 직관적이고 매우 재미있어할 수 밖에 없겠다.

지겨운 algorithm이나 math가 이런 멋진 결과들을 가져오다니.


[CG]CG Term project 발표정리 - 2006.5.2

2006. 5. 2. 22:56 | Posted by 속눈썹맨

. 조원 : (주한별, Linda), (김지혜, 이춘석 tclab)
. Color2gray : Salience-Preserving color removal
  . gray로 바꾸면 intensity만 남아 안 보이게 되는 것이 있다.
  (Intensity가 같고 chrominance만 다른 경우)
  . Intensity를 희생하더라도 차이가 구분되게 한다.
  . Chrominance difference -> luminance
  . f(g) = sigma((i,j) in k, ((gi - gj) - dij)^2)
  . d : chrominance difference
  . f(g)를 minimize하는 g를 찾으면 된다.(optimization)
  . 색, 인지과학이용.(human visual sensitivity)

. 조원 : (김윤영 tclab)
. Feature Preserving Regular Remeshing
  . surface remeshing : 3D mesh를 remesh해서 다시 3D로 만듬.
  . mesh : polygon으로 정의된 연결 집합
  . Regular remeshing
  . Regular remesh : 모든 vertex가 같은 valence를 가짐.
  . Valence : vertex에 연결된 edge의 수
  . Connectivity가 좋다. 압축률이 좋다.
  . Goal : feature를 잘 보존하면서 remesh
  . Segmentation : 3D를 자름
  . Parameterization : 3D를 2D에 펼침 => feature preserving
  . least square conformal Map => regular remeshing

  . Parameterization
  . 각도 보존(Conformal map, angle-preserving)
  . 경위도 보존
  . 넓이 보존
  . Contribution - 기존방법의 단접 - 삼각형이 매우 찌그러짐.

. 조원 : 공내진
. Fast bilateral filtering for the display of high-dynamic range
  . HDR : High-dynamic-range
  . device들보다 인간이 보는 contrast range가 훨씬 넓다.
  따라서 완벽하게 표현하지 못한다.
  . 선형으로 변환하면 대비가 분명하지 않다.
  . 영화가 너무 어두울 때
  . 밝은 것(오랜노출)부터 어두운 것(짧은 노출)순으로 16장을 찍고 합쳐서 만든다.
  . Tone reproduction problem : contrast를 잘 맞추기
  = Tone mapping operator 찾기
  . Anisotropic diffusion : 가까운 pixel의 영향을 더 많이 받음.
  . Bilateral filter : contrast를 잘 변환

  . bilateral : 쌍방의, 좌우 양측의
  . anisotropic : directionally dependent
  . have different characteristic in different direction
  . ex) polarising lens, polaroid sunglasses

  . isotropic : directionally independent
  . diffusion : spotaneous spreading of matter, heat or momentum

  . layes
  . base layer : operation을 함
  . Detail layer : 보존
  . Color layer : 안씀

  . Bilateral mask
  . f : 관심 pixel의 주변만 봄
  . g : edge에서는 intensity가 달라지는 속성을 이용,
         너무 intensity가 커지면 중단.

. 조원 : (최영남 AI, 김효실 GC), (양형진)
. A new voronoi based surface reconstruction algorithm
  . Laser scan으로 물체를 sampleing하여 point를 얻음.
  . Surface reconstruction : surface 위의 점을 sampling하고
  그것을 다시 construct해서 surface를 만듬.

  . Delaunay triangle : 점들을 이어 삼각형으로 만듬.
  . edge property : 어느 삼각형의 외접원도 그 세 점 외에 다른 점을 포함하지 않음.
  . http://www.ics.uci.edu/~eppstein/gina/delaunay.html

  . Mesh : simple element로 discretization

  . Voronoi diagram : R^d를 point로 cell로 나눔. (decomposition)
  . closest point에 의해 분할되는 공간

  . Medial Axis
  . voronoi diagram의 edge의 boundary
  . tree-like skeleton
  . continuous cousin of the Voronoi diagram
  . http://www.cs.utexas.edu/users/amenta/powercrust/tools.html#mat
 
  . Power crust
  . Medial axis transform을 이용한 3D surface reconstruction algorithm

  . Clakrson's hull
  . n-d Delaunay triangulation을 위한 Exact arighmetic을 해준다.

  . Geodesic distance와 euclidean distance가 다른 것을 구별하기 위해
  axis를 사용한다.

. Surface reconstruction algorithm
  . CGAL library 이용
  . Improve : handling sharp edge
  . Compression 해보기

. 조원 : 유상욱
. Realistic 3D face construction
  . Final fantasy : Model의 사진을 기반으로 만듬
  . 사진 + camera parameter
  . 3D face Model construction - 사용자가 feature point 추가가능
  . Image Texturing
  . Virtual Boundary
  . Matching
  . Embedding
  . Smoothing

. 조원 : 서원필(VR), 이용준
. Sequential Point trees
  . Point based rendering (삼각형이 아닌 point cloud를 이용하자.)
  . Inefficient when all vertices are rendered
  . Hole problem
  . Qsplat - Octree처럼 공간을 나눔
  . tree라서 array보다 느리다.
  . CPU + GPU를 모두 쓰므로 bottleneck이 있다.

. 조원 : 이지현
. Making paper craft toys from meshes using strip-based approximate unfolding
  . Paper craft
  . Unfolding : Mesh -> 전개도

  . 기존의 방법
  . Unrealistic to assemble
  . simplify-smoothness 보존
  . Triangle strip : 언제나 unfold가능, loop도 ㅣㅇㅆ을 수 있음.
  . Zonal region : 띠를 만듬.

. 조원 : (주현성, 이지원), (이정환 CG)
. Particle system
  . 20년이 넘어 이미 모두 상업화됨.
  . Research topic이 없음.
  . 최초의 motion blur 작품(streaks of lights)

. Digital Photography of flash and no-flash image pairs
  . flash : High-frequency, red-eye, harsh shadow
  . No-flash : Ambient illumination, noise
  . 동일한 카메라 위치에서 찍은 두 사진을 합성하고 장점만 취해 더 좋은 이미지를 얻는 다.

. Art-based rendering of fur, grass and trees

. Stanford computer Graphics Laboratory
http://www-graphics.stanford.edu/
-> Data archives
The digital michelangelo project의 일환으로 status scanner가 있어서
데이터가 많음 point set sample data를 얻을 수 있음.
Bunny, Lion, Happy Buddha, Dragon, Lucy 등이 있다.

[CG]오차누적 - rotation transformation

2006. 4. 16. 20:18 | Posted by 속눈썹맨

수학적으로는 360도 회전하는 것이나 5도씩 72번 회전하는 것이 같다.
하지만 numerical하게는 변수에 값을 누적하기 시작하면 오차가 매우 커진다.

5도씩 100번 회전하면 물체의 크기가 30%나 적어진다.
5도 회전할 때마다 오차가 0.3%있는 것이다.
또한 도형이 shearing되기 시작한다.
(shearing + scale down)

시뮬레이션)
#include "math.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
long double x0 = 100;
long double y0 = 100;
long double x = 0;
long double y = 0;
float theta = 5.0 * 3.141592 / 180.0;

for (int i = 0; i < 100; i++)
{
x0 = x + (x0 - x) * cos(theta) - (y0 - y) * sin(theta);
y0 = y + (y0 - y) * cos(theta) + (x0 - x) * sin(theta);

cout << "i : (x0, y0), d : " << i << ", " << x0 << ", " << y0 << ", " << sqrt(pow(x0, 2) + pow(y0, 2)) << endl;
}

cout << "theta : " << theta << endl;
cout << "cos(theta) : " << cos(theta) << endl;
cout << "sin(theta) : " << sin(theta) << endl;
cout << "sqrt(pow(cos(0.1), 2) + pow(sin(0.1), 2)) : " << sqrt(pow(cos(0.1), 2) + pow(sin(0.1), 2)) << endl;

return 0;
}

해결책 1)
. 원본과 transformation을 항상 저장한다.
- 복잡한 transformation을 했을 경우 모두 저장하기 힘들고 performance가 떨어진다.

가짜 해결책 2)
Rotation 각도를 크게 해서 한, 두 번만 한다.

가짜 해결책 3)
Rotation 각도를 작게 해서 잠시만 보여준다.

가짜 해결책 4)
Rotation과 함께 scale을 시도한다.

실패한 해결책 5)
변수를 double, long double 등으로 바꾼다.
(truncation error를 줄이려는 생각이었으나 실패.)

진짜 해결책)
사실은 vector, matrix 곱셈을 잘못한 것이다.
x0의 값이 바뀐 후 값이 y0의 계산에 이용되고 있다.
따라서 임시변수 2개를 만들어서 x0, y0값을 따로 저장해두고 계산이 끝난 후 복사해야 한다.
(혹은 먼저 값을 복사해두고 계산해야 한다.)

[OpenGL]Zoom in, out, pan 구현하기

2006. 4. 16. 02:31 | Posted by 속눈썹맨

방법 1)
glOrtho를 이용한다.
World coordinate에서 clipping할 영역을 지정하는 방법

int g_screenX = 800; // 화면의 가로 크기
int g_screenY = 600; // 화면의 세로 크기
float g_zoomFactor = 1;
float g_panningX = 0;
float g_panningY = 0;
float g_worldLeft = - g_screenX / 2.0 * g_zoomFactor + g_panningX;
float g_worldRight = g_screenX / 2.0 * g_zoomFactor + g_panningX;
float g_worldBottom = - g_screenY / 2.0 * g_zoomFactor + g_panningY;
float g_worldTop = g_screenY / 2.0 * g_zoomFactor + g_panningY;

void setCamera()
{
g_worldLeft = - g_screenX / 2 * g_zoomFactor + g_panningX;
g_worldRight = g_screenX / 2 * g_zoomFactor + g_panningX;
g_worldBottom = - g_screenY / 2 * g_zoomFactor + g_panningY;
g_worldTop = g_screenY / 2* g_zoomFactor + g_panningY;

glOrtho(g_worldLeft, g_worldRight, g_worldBottom, g_worldTop, -1, 1);
}

// 좌표 계산을 함
void calculateGLcoordinate(const int x, const int y, GLfloat* retX, GLfloat* retY)
{
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);

// openGL window coordinate는 system의 window coordinates와 반대이므로
// y좌표를 얻으려면 viewport[3] - y를 해야 한다.
// grid처리를 위해 gridWidth로 나눈 나머지 값을 버리고 다시 곱한다.
*retX = floorf((static_cast<float>(x) * (g_worldRight - g_worldLeft) / g_screenX  + g_worldLeft) / gridWidth) * gridWidth;
*retY = floorf((static_cast<float>(viewport[3] - y) * (g_worldTop - g_worldBottom) / g_screenY  + g_worldBottom) / gridWidth) * gridWidth;

//cout << "x : " << x << endl;
//cout << "y : " << y << endl;
//cout << "*retX : " << *retX << endl;
//cout << "*retY : " << *retY << endl;
}

방법 2)
glPerspective, glFrustum 등을 이용
Camera를 조절.
- 어떻게 하는 지 잘 모르겠음.

방법 3)
glScale, glTranslate를 이용한다.
Model Matrix를 고치는 방법.

방법 4)
glVertex에 입력하는 물체의 좌표를 직접 고친다.

주의)
이 방법이 모든 Model, view matrix에 적용되게 해야 한다.
. 화면에 그릴 때 (OpenGL이 지원)
. pick 할 때 (OpenGL이 지원)
. 화면에 입력할 때 (직접 고쳐야 함.)

[Algorithm] Ellipse Drawing

2006. 4. 7. 00:52 | Posted by 속눈썹맨

문제) Modify Midpoint circle drawing algorithm to draw Ellipses

타원의 방정식)
  . (x^2 / a^2) + (y^2 / b^2) = 1
  . (b^2 * x^2) + (a^2 * y^2) = (b^2 * a^2)

  . (b^2 * x^2) + (a^2 * y^2) - (b^2 * a^2)
  (음수이면 타원의 외부, 양수이면 타원의 내부, 0이면 타원 위의 점)

  . EllipseError(xi, yi) = abs((b^2 * xi^2) + (a^2 * yi^2) - (b^2 * a^2))

방법)
. 1사분면(quadrant)에 대해 계산하고 4-way symmetry를 이용하여 2,3,4분면에 그린다.
. 1사분면에서 tangent line의 slope는 항상 음수
. tangent line의 slope가 -1보다 큰 곳과 작은 곳을 나누어 계산한다.

구현) Pseudo code(Algol 코드와 유사함)
Procedure PlotEllipse(CX, CY, XRadius, YRadius : Integer);
var X, Y, XChange, YChange, EllipseError, TwoASquare, TwoBSquare, StoppingX, stoppingY : Integer;
begin
  { CX : 타원의 중심의 X좌표 }
  { CY : 타원의 중심의 Y좌표 }
  TwoASquare := 2 * XRadius * XRadius; { 제곱을 미리 계산 }
  TwoBSquare := 2 * YRadius * YRadius;

  { 동 -> 북 }
  X:= XRadius;
  Y:= 0;
  XChange := YRadius*YRadius*(1-2*XRadius);
  YChange := XRadius*XRadius;
  EllipseError := 0;
  StoppingX := TwoBSquare*XRadius
  StoppingY := 0;

  while(StoppingX >= StoppingY) do {1st set of points, y'>-1}
      begin
          Plot4EllipsePoints(X,Y);
          ++Y;
          StoppingY := StoppingY + TwoASquare;
          EllipseError := EllipseError + YChange;
          YChange := YChange + TwoASquare;
          if ((2*EllipseError + XChange) > 0) then
              begin
                  --X;
                  StoppingX := StoppingX - TwoBSquare;
                  EllipseError := EllipseError + XChange;
                  XChange := XChange + TwoBSquare
              end
      end;

  { 북 -> 동 }
  X := 0;
  Y := YRadius;
  XChange := YRadius*YRadius;
  YChange := XRadius*XRadius*(1-2*YRadius);
  EllipseError := 0;
  StoppingX := 0;
  while (StoppingX <= StoppingY) do {2nd set of points, y' < -1}
      begin
          Plot4EllipsePoints(X,Y); {subroutine appears later}
          ++X;
          StoppingX := StoppingX + TwoBSquare;
          EllipseError := EllipseError + Xchange;
          XChange := XChange + TwoBSquare;
          if ((2*EllipseError + YChange) > 0) then
              begin
                  --Y;
                  StoppingY := StoppingY - TwoASquare;
                  EllipseError := EllipseError + YChange;
                  YChange := YChange + TwoASquare
              end
      end
end; {procedure PlotEllipse}

{ 4-way symmetry point draw }
procedure Plot4EllipsePoints(X, Y : integer)
begin
  display(CX+X,CY+Y); {point in quadrant 1}
  display(CX-X,CY+Y); {point in quadrant 2}
  display(CX-X,CY-Y); {point in quadrant 3}
  display(CX+X,CY-Y); {point in quadrant 4}
end; {procedure Plot4EllipsePoints}

참고)
Jerry R. Van Aken, An Efficient Ellipse-Drawing Algorithm, IEEE Computer Graphics & Applications, September 1984, pp.24~35
A Fast Bresenham Type Algorithm For Drawing Ellipses : http://homepage.smc.edu/kennedy_john/BELIPSE.PDF



[Algorithm]Anti-aliasing Lines

2006. 4. 7. 00:25 | Posted by 속눈썹맨

. Aliasing(Jagged or blocky pattern), artifact, black and white noise
  . Line뿐만 아니라 texture에서도 많이 나옴
  . 계단현상(stairecase)
  . raster effect
  . small object : 작은 물체는 안 그려진다.
  . Texture : pixel보다 얇은 texture는 안 그려진다.

. Anti-aliasing : removing data at too high a freequency to represent
  . 완벽하게는 안되고 최대한 잘해보자.
  . 두께를 가지는 line으로 생각함.
  . 각 rectangle(pixel)과 두께를 가지는 line의 면적비를 intensity로 줌
  . intensity adjusing along to line
   . 대각선으로 그려진 라인이 sqrt(2)배 더 길므로 그만큼 더 밝게 해주자.

방식)
. Supersampling(Postfiltering)
  . Increasing resolution - hardware이용, 계산량 증가
. Area Sampling(Prefiltering)
  . intensity를 0~1사이의 gray scale로 넣자.
  . Box filter(Unweighted filter)
  . Cone filter(Weighted filter)
   . 같은 크기의 area라도 line의 center에 가까우면 weight를 더 준다.
   . Box filter는 Cone filter의 special case
   . Intensity functions f(D,t)
     . t : Line의 width
     . D : Line center로부터 pixel center까지의 거리
     . V : Vertical한 거리
     . D = v * cos(theta) = v dx / sqrt(dx^2+dy^2)
   . 그 점뿐만 아니라 그 위, 아래 점도 계산한다.

. Stochastic Sampling

. Curve fitting
  . Interpolation : 모든 control point를 지나야 함.
  control point가 많으면 noisy해짐(oscillatory feature)
  Lagrange, Hermite, Cubic spline, B-spline, piece-wise method
  참고) Numerical Analysis
  . Approximation : 모든 control point를 지날 필요 없음.
  control point가 많아도 smooth하다.


 

[CG Algorhtim]Midpoint circle algorithm

2006. 4. 6. 17:16 | Posted by 속눈썹맨

. 방법 1 : 원의 방정식에서 x값을 증가시키면서 y를 구하자.
  . 문제점
  . x가 원의 가장 왼쪽, 오른쪽 근처에서 원 위의 점들이 듬성듬성 찍힌다.
  . sqrt() 함수를 써야 한다. (느리다.)
  . y = yc +-sqrt(r^2-(x-xc)^2)

. 방법 2 : Polar coordinate를 이용하자.
  . 듬성듬성찍히는 문제를 해결
  . sin(), cos() 함수를 써야 한다. (느리다.) 
  . x = xc + rcos(theta)
  . y = yc + rsin(theta)

. 방법 3
  . 8-way symmetry를 이용하자.(x축 대칭, y축 대칭, y=x 대칭)
  2 x 2 x 2 = 8, 1/8, 45도만 계산하면 된다.
  . 북~북서쪽의 45도를 계산하자.(듬성듬성하지 않게)
  . Midpoint line algorithm을 응용하자.

void MidpointCircle ( int radius, int value )
{
  int   x, y;
  float d;

  x = 0;
  y = radius;
  d = 5.0 / 4 - radius;
  CirclePoints ( x, y, value );
 
  while ( y > x ) {
     if ( d < 0 ) {
        d = d + x * 2.0 + 3;
  ++x;
     }
     else {
        d = d + (x - y) * 2.0 + 5;
  ++x;
  --y;
     }
     CirclePoints ( x, y, value );
  }
}

. 방법 4
  . floating point 연산을 없애자

void MidpointCircle (int radius, int value )
{
  int x, y;
  int d;

  x = 0;
  y = radius;
  d = 1 - radius;
  CirclePoints ( x, y, value );
 
  while ( y > x ) {
     if ( d < 0 ) {
        d = d + x * 2 + 3;
  ++x;
     }
     else {
        d += (x - y) * 2 + 5;
  ++x;
  --y;
     }
     CirclePoints ( x, y, value );
  }
}

. 방법 5
  . loop 내의 곱셈을 없애자.
  . Second Order Differences
  . Key idea: Just as we calculate x and y incrementally, we can also calculate deltaE and deltaSE incrementally
caseE:
  deltaEold = 2xp + 3
  deltaEnew = 2xp + 5
  deltaDeltaE  = 2
  deltaDeltaSE = ( 2(xp - 1) - 2yp + 5 ) - ( 2xp - 2yp + 5 )
               = 2
caseSE:
  deltaDeltaE  = (2xp + 5) - (2xp + 3)
               = 2
  deltaDeltaSE = ( 2(xp + 1) - 2(yp - 1) + 5 ) - ( 2xp - 2yp - 5 )
               = 4

Starting out:
  deltaEstart = 2 * 0 + 3 = 3
  deltaSEstart = 2 * 0 - 2 * R + 5
                  = 5 - 2R

void MidpointCircle ( int radius, int value )
{                  
  int     x, y, d, deltaE, deltaSE;

  x       = 0;
  y       = radius;
  d       = 1 - radius;
  deltaE  = 3;
  deltaSE = 5 - radius * 2;

  CirclePoints ( x, y, value );
 
  while ( y > x ) {
     if ( d < 0 ) { /* Select E */
        d       += deltaE;
  deltaE  += 2;
  deltaSE += 2;
  x       ++;
     }
     else {         /* Select SE */
        d       += deltaSE;
  deltaE  += 2;
  deltaSE += 4;
  x       ++;
  y       ++;
     }
     CirclePoints ( x, y, value );
  }
}

참고)
http://www.cs.umbc.edu/~rheingan/435/pages/res/gen-3.Circles-single-page-0.html

Midpoint Circle Algorithm
Implicit Equation
  f(x,y) = x^2 + y^2 - R^2
     f(x,y) > 0  =>  point outside circle
     f(x,y) < 0  =>  point inside circle

Midpoint Criteria
  f(M) = f(xp+1, yp - 1/2)
       = (xp + 1)^2 + (yp - 1/2)^2 - R^2

  d >= 0 choose SE
       next M: +1 in x, -1 in y

  d <  0 choose E
       next M: +1 in x

Book keeping
  deltaE  = dnew - dold
          = f(xp + 2, yp - 1/2) - f(xp+1, yp - 1/2)
  = 2xp + 3

  deltaSE = f(xp + 2, yp - 3/2) - f(xp+1, yp - 1/2)
      = 2xp - 2yp + 5

  dstart   = f(x0 + 1, y0 - 1/2) = f(1, R - 1/2)
        = 5/4 - R

void CirclePoints (float x, float y, int value)
{
  WritePixel (  x,  y, value );
  WritePixel (  y,  x, value );
  WritePixel (  y, -x, value );
  WritePixel (  x, -y, value );
  WritePixel ( -x, -y, value );
  WritePixel ( -y, -x, value );
  WritePixel ( -y,  x, value );
  WritePixel ( -x,  y, value );
}

[CG]circular arc 그리기

2006. 4. 1. 15:54 | Posted by 속눈썹맨
. (x1, y1), (x2, y2), (x3, y3) 세점이 주어졌을 때
(x1, y1) -> (x2, y2) -> (x3, y3)를 차례로 지나는 arc를 그린다.
. 점을 지나는 순서를 지켜야 한다는 사실이 중요하다. 그렇게 해야 unique하게 arc가 결정된다.
. 두 점과 원의 중심이 주어지는 경우에는 arc가 unique하게 결정되지 않고 시계방향과 반시계방향의 2개가 나온다.

// theta들은 360 degree(not radian)

// 두 각이 입력되었을 때 같은 각인지 검사한다.
bool isEqualDegree(const int theta1, const int theta2)
{
int diff = (theta1 - theta2) % 360;

if (diff == 0)
return true;

return false;
}

int arcDirectionTest(const int theta1, const int theta2, const int theta3)
{
// 시계방향으로 돌아야 할지, 반시계방향으로 돌아야 할지 test
// direction = 1 : 반시계방향
// direction = -1 : 시계방향
int direction = 1;

for (int theta_i = theta1; theta_i < 360 + theta1; theta_i++)
{
if (isEqualDegree(theta_i, theta3)) {
// theta2를 theta3보다 먼저 지나게 그려야 하므로
// 방향을 바꾸자.
direction = -1;
break;
}

if (isEqualDegree(theta_i, theta2)) {
// theta2를 theta3보다 먼저 지나고 있으므로 방향 유지
break;
}
}

return direction;
}

// arc 그리기
direction = arcDirectionTest(theta1, theta2, theta3);
int theta_i = theta1;

while(1)
{
if (theta_i >= 180) {
theta_i = -179;
}

if (theta_i <= -180) {
theta_i = 180
}
// -179 <= theta_i <= 180

glVertex3f(x0 + r * cos(theta_i) , y0 + r * sin(theta_i), 0);

if (isEqualDegree(theta_i, theta3))
break;

theta_i += direction
}

[CG]외접원 - Circumscribed Circle

2006. 4. 1. 15:23 | Posted by 속눈썹맨
외접원 구하기

// (x1, y1), (x2, y2), (x3, y3) 삼각형의 세 꼭지점
// (x0, y0) - 외접원의 중심
// r - 외접원의 반지름

void circumscribedCircle(const float x1, const float y1, const float x2, const float y2, const float x3, const float y3, float* x0, float* y0, float r)
{
// (x1, y1), (x2, y2), (x3, y3) 세 점 중 2개 이상이 같거나
// 세 점이 일직선 상에 있으면 안된다.

// divide by 0 조건도 피해야 한다.
// 1. y1 - y2 = 0
// 2. y1 - y2 = 0
// 3. (x1 - x3 - (y1 - y3) * (x1 - x2) / (y1 - y2)) = 0
// 4. x1 - x2 = 0

*x0 = (pow(y1, 2) + pow(x1, 2) - pow(y3, 2) - pow(x3, 2) - (y1 - y3) * (pow(y1, 2) + pow(x1, 2) - pow(y2, 2) - pow(x2, 2)) / (y1 - y2)) / 2 / (x1 - x3 - (y1 - y3) * (x1 - x2) / (y1 - y2));
*y0 = (pow(y1, 2) + pow(x1, 2) - pow(y2, 2) - pow(x2, 2) - 2 * x0 * (x1 - x2)) / (y1 - y2) / 2;
*r = sqrt(pow(x3 - x0, 2) + pow(y3 - y0, 2));
}
이전 1 2 다음