2010-07-22 2 views
1

나는 다각형을 생성하기 위해 다음과 같은 알고리즘을 설명 발견내부 마이 터 계산이란 무엇입니까?

void CGlShape::GenerateLinePoly(std::vector<DOUBLEPOINT> &input, int width) 
{ 
OutlineVec.clear(); 
if(input.size() < 2) 
{ 
    return; 
} 


if(connected) 
{ 
    input.push_back(input[0]); 
    input.push_back(input[1]); 
} 


float w = width/2.0f; 

//glBegin(GL_TRIANGLES); 
for(size_t i = 0; i < input.size()-1; ++i) 
{ 
    POINTFLOAT cur; 
    cur.x = input[i].point[0]; 
    cur.y = input[i].point[1]; 


    POINTFLOAT nxt; 


    nxt.x = input[i+1].point[0]; 
    nxt.y = input[i+1].point[1]; 

    POINTFLOAT b; 
    b.x = nxt.x - cur.x; 
    b.y = nxt.y - cur.y; 

    b = normalize(b); 



    POINTFLOAT b_perp; 
    b_perp.x = -b.y; 
    b_perp.y = b.x; 


    POINTFLOAT p0; 
    POINTFLOAT p1; 
    POINTFLOAT p2; 
    POINTFLOAT p3; 

    p0.x = cur.x + b_perp.x * w; 
    p0.y = cur.y + b_perp.y * w; 

    p1.x = cur.x - b_perp.x * w; 
    p1.y = cur.y - b_perp.y * w; 

    p2.x = nxt.x + b_perp.x * w; 
    p2.y = nxt.y + b_perp.y * w; 

    p3.x = nxt.x - b_perp.x * w; 
    p3.y = nxt.y - b_perp.y * w; 

    OutlineVec.push_back(p0.x); 
    OutlineVec.push_back(p0.y); 
    OutlineVec.push_back(p1.x); 
    OutlineVec.push_back(p1.y); 
    OutlineVec.push_back(p2.x); 
    OutlineVec.push_back(p2.y); 

    OutlineVec.push_back(p2.x); 
    OutlineVec.push_back(p2.y); 
    OutlineVec.push_back(p1.x); 
    OutlineVec.push_back(p1.y); 
    OutlineVec.push_back(p3.x); 
    OutlineVec.push_back(p3.y); 



    // only do joins when we have a prv 
    if(i == 0) continue; 


    POINTFLOAT prv; 
    prv.x = input[i-1].point[0]; 
    prv.y = input[i-1].point[1]; 

    POINTFLOAT a; 
    a.x = prv.x - cur.x; 
    a.y = prv.y - cur.y; 

    a = normalize(a); 

    POINTFLOAT a_perp; 
    a_perp.x = a.y; 
    a_perp.y = -a.x; 

    float det = a.x * b.y - b.x * a.y; 
    if(det > 0) 
    { 
    a_perp.x = -a_perp.x; 
    a_perp.y = -a_perp.y; 

    b_perp.x = -b_perp.x; 
    b_perp.y = -b_perp.y; 
    } 

    // TODO: do inner miter calculation 

    // flip around normals and calculate round join points 
    a_perp.x = -a_perp.x; 
    a_perp.y = -a_perp.y; 

    b_perp.x = -b_perp.x; 
    b_perp.y = -b_perp.y; 

    size_t num_pts = 16; 

    std::vector< POINTFLOAT> round(1 + num_pts + 1); 
    POINTFLOAT nc; 
    nc.x = cur.x + (a_perp.x * w); 
    nc.y = cur.y + (a_perp.y * w); 

    round.front() = nc; 

    nc.x = cur.x + (b_perp.x * w); 
    nc.y = cur.y + (b_perp.y * w); 

    round.back() = nc; 

    for(size_t j = 1; j < num_pts+1; ++j) 
    { 
    float t = (float)j/(float)(num_pts+1); 
    if(det > 0) 
    { 
    POINTFLOAT nin; 
    nin = slerp2d(b_perp, a_perp, 1.0f-t); 
    nin.x *= w; 
    nin.y *= w; 

    nin.x += cur.x; 
    nin.y += cur.y; 

    round[j] = nin; 
    } 
    else 
    { 
    POINTFLOAT nin; 
    nin = slerp2d(a_perp, b_perp, t); 
    nin.x *= w; 
    nin.y *= w; 

    nin.x += cur.x; 
    nin.y += cur.y; 

    round[j] = nin; 
    } 
    } 

    for(size_t j = 0; j < round.size()-1; ++j) 
    { 

    OutlineVec.push_back(cur.x); 
    OutlineVec.push_back(cur.y); 


    if(det > 0) 
    { 
    OutlineVec.push_back(round[j + 1].x); 
    OutlineVec.push_back(round[j + 1].y); 
    OutlineVec.push_back(round[j].x); 
    OutlineVec.push_back(round[j].y); 
    } 
    else 
    { 

    OutlineVec.push_back(round[j].x); 
    OutlineVec.push_back(round[j].y); 

    OutlineVec.push_back(round[j + 1].x); 
    OutlineVec.push_back(round[j + 1].y); 
    } 
    } 
} 

} 

    POINTFLOAT multiply(const POINTFLOAT &a, float b) 
    { 
    POINTFLOAT result; 
    result.x = a.x * b; 
    result.y = a.y * b; 
    return result; 
    } 

    POINTFLOAT normalize(const POINTFLOAT &a) 
    { 
    return multiply(a, 1.0f/sqrt(a.x*a.x+a.y*a.y)); 
    } 


    POINTFLOAT slerp2d(const POINTFLOAT &v0, 
      const POINTFLOAT &v1, float t) 
    { 
    float dot = (v0.x * v1.x + v0.y * v1.y); 

    if(dot < -1.0f) dot = -1.0f; 
    if(dot > 1.0f) dot = 1.0f; 

    float theta_0 = acos(dot); 
    float theta = theta_0 * t; 

    POINTFLOAT v2; 
    v2.x = -v0.y; 
    v2.y = v0.x; 

    POINTFLOAT result; 
    result.x = v0.x * cos(theta) + v2.x * sin(theta); 
    result.y = v0.y * cos(theta) + v2.y * sin(theta); 

    return result; 
    } 

은 내부 마이 계산을 수행해야하지만 이것이하거나이 방법을 수행해야 모르겠어요한다는 의견이있다. 지금이 알고리즘은 둥근 모서리를 생성하지만 대신 이등변 모서리 (사각형)를 만들기 위해 수정하고 싶습니다. 어떻게이 작업을 수행 할 수 있습니까? 내부 연귀 계산이 포함됩니까?

감사

+0

이 코드 읽기가 매우 가난, 왜 추가 및 무효화 등 같은 기본적인 벡터 서비스를 제공 할 기능이 없다? 곱하기 위해 사용되지 않는 좋은'multiply' 함수가 있습니다. 또한 우리는 일부 값도 누락 된 것처럼 보입니다. 첫 번째 스 니펫에서 'w'는 어디에서 왔습니까? –

+0

그래, 누락 된 코드 – jmasterx

+0

[일부 스타일] (http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node281.html)을 수정했습니다. 바깥 쪽 연귀 또는 바깥 쪽 경사를 원하십니까? – genpfault

답변

2

가이 수정을 시도 내 other answer :

// v0 and v1 are normalized 
// t can vary between 0 and 1 
// http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/ 
Vector2f slerp2d(const Vector2f& v0, const Vector2f& v1, float t) 
{ 
    float dot = v0.dot(v1); 
    if(dot < -1.0f) dot = -1.0f; 
    if(dot > 1.0f) dot = 1.0f; 

    float theta_0 = acos(dot); 
    float theta = theta_0 * t; 

    Vector2f v2(-v0.y(), v0.x()); 

    return (v0*cos(theta) + v2*sin(theta)); 
} 


void glPolyline(const vector<Vector2f>& polyline, float width) 
{ 
    if(polyline.size() < 2) return; 
    float w = width/2.0f; 

    glBegin(GL_TRIANGLES); 
    for(size_t i = 0; i < polyline.size()-1; ++i) 
    { 
     const Vector2f& cur = polyline[ i ]; 
     const Vector2f& nxt = polyline[i+1]; 

     Vector2f b = (nxt - cur).normalized(); 
     Vector2f b_perp(-b.y(), b.x()); 

     Vector2f p0(cur + b_perp*w); 
     Vector2f p1(cur - b_perp*w); 
     Vector2f p2(nxt + b_perp*w); 
     Vector2f p3(nxt - b_perp*w); 

     // first triangle 
     glVertex2fv(p0.data()); 
     glVertex2fv(p1.data()); 
     glVertex2fv(p2.data()); 
     // second triangle 
     glVertex2fv(p2.data()); 
     glVertex2fv(p1.data()); 
     glVertex2fv(p3.data()); 

     // only do joins when we have a prv 
     if(i == 0) continue; 

     const Vector2f& prv = polyline[i-1]; 
     Vector2f a = (prv - cur).normalized(); 
     Vector2f a_perp(a.y(), -a.x()); 

     float det = a.x()*b.y() - b.x()*a.y(); 
     if(det > 0) 
     { 
      a_perp = -a_perp; 
      b_perp = -b_perp; 
     } 

     // TODO: do inner miter calculation 

     // flip around normals and calculate round join points 
     a_perp = -a_perp; 
     b_perp = -b_perp; 

     size_t num_pts = 1; 
     vector<Vector2f> round(1 + num_pts + 1); 
     for(size_t j = 0; j <= num_pts+1; ++j) 
     { 
      float t = (float)j/(float)(num_pts+1); 
      if(det > 0) 
       round[j] = cur + (slerp2d(b_perp, a_perp, 1.0f-t) * w); 
      else 
       round[j] = cur + (slerp2d(a_perp, b_perp, t) * w); 
     } 

     /////////////////////// 
     // new outer miter code 
     float theta = acos(a.dot(b))/2.0; 
     float val = w/tan(theta); 
     float miter_length = sqrt(w*w + val*val); 
     Vector2f miter = ((a_perp+b_perp)*0.5).normalized() * miter_length; 

     round[1] = cur + miter; 
     // end new outer miter code 
     /////////////////////// 

     for(size_t j = 0; j < round.size()-1; ++j) 
     { 
      glVertex2fv(cur.data()); 
      if(det > 0) 
      { 
       glVertex2fv(round[j+1].data()); 
       glVertex2fv(round[j+0].data()); 
      } 
      else 
      { 
       glVertex2fv(round[j+0].data()); 
       glVertex2fv(round[j+1].data()); 
      } 
     } 
    } 
    glEnd(); 
} 
+0

감사합니다. 내 프로젝트를 다시 저장했습니다. :) – jmasterx

+0

마이 터가 무한대로 떨어져 나가는 경향이 있기 때문에 가파른 각도로 보입니다. – genpfault

+0

각도 조건을 추가 할 것입니다. – jmasterx

0

코드는 바깥 쪽 가장자리에 다각형 설명에 둥근 모서리 (주교관)을두고 있지만, . 당신이 그 안에 자리 잡은 작은 흰색 상자와 큰, 블랙 박스로 사각형의 윤곽을 개념화 할 수있는 경우

,이 코드는 블랙 박스의 모서리를 둥글게하지만 이것은 하나의 흰색
(하지 그냥 생각한 운동, 코드는 실제로 이런 식으로 작동하지 않습니다)

그게 전부가 slerp 물건이 무엇입니까; 첫 번째 가장자리와 두 번째 가장자리에 수직 인 방향 사이를 보간하고, 호를 따라 점을 추가합니다.

의견을 통해 누군가가 내부 모서리에 동일한 작업을 수행해야한다고 제안합니다.

+0

괜찮습니다. 둥근 사각형 대신 사각형 모서리를 만들려면 어떻게해야합니까? – jmasterx

+0

코드를 그대로두고'size_t num_pts = 16;'을'size_t num_pts = 0;'으로 변경하거나 더 나은 방법으로 (아마도 기본) 매개 변수를 허용하도록 변경하십시오. 'num_pts'는 반올림 한 비트 수입니다. – kibibu

+0

경사가 아닌 모서리가없는 부분을 생성하지 않습니다. – jmasterx

관련 문제