1. <tfoot id='UydP1'></tfoot>

    2. <small id='UydP1'></small><noframes id='UydP1'>

        <legend id='UydP1'><style id='UydP1'><dir id='UydP1'><q id='UydP1'></q></dir></style></legend>

      1. <i id='UydP1'><tr id='UydP1'><dt id='UydP1'><q id='UydP1'><span id='UydP1'><b id='UydP1'><form id='UydP1'><ins id='UydP1'></ins><ul id='UydP1'></ul><sub id='UydP1'></sub></form><legend id='UydP1'></legend><bdo id='UydP1'><pre id='UydP1'><center id='UydP1'></center></pre></bdo></b><th id='UydP1'></th></span></q></dt></tr></i><div id='UydP1'><tfoot id='UydP1'></tfoot><dl id='UydP1'><fieldset id='UydP1'></fieldset></dl></div>
        • <bdo id='UydP1'></bdo><ul id='UydP1'></ul>

        多边形轮廓上的边缘并不总是正确的

        时间:2023-09-18
        • <legend id='NWScQ'><style id='NWScQ'><dir id='NWScQ'><q id='NWScQ'></q></dir></style></legend>
              <tfoot id='NWScQ'></tfoot>

                  <tbody id='NWScQ'></tbody>
                <i id='NWScQ'><tr id='NWScQ'><dt id='NWScQ'><q id='NWScQ'><span id='NWScQ'><b id='NWScQ'><form id='NWScQ'><ins id='NWScQ'></ins><ul id='NWScQ'></ul><sub id='NWScQ'></sub></form><legend id='NWScQ'></legend><bdo id='NWScQ'><pre id='NWScQ'><center id='NWScQ'></center></pre></bdo></b><th id='NWScQ'></th></span></q></dt></tr></i><div id='NWScQ'><tfoot id='NWScQ'></tfoot><dl id='NWScQ'><fieldset id='NWScQ'></fieldset></dl></div>

                <small id='NWScQ'></small><noframes id='NWScQ'>

                  <bdo id='NWScQ'></bdo><ul id='NWScQ'></ul>

                  本文介绍了多边形轮廓上的边缘并不总是正确的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

                  我使用下面的算法来生成四边形,然后渲染成这样的轮廓

                  <块引用>

                  I'm using the algorithm below to generate quads which are then rendered to make an outline like this

                  http://img810.imageshack.us/img810/8530/uhohz.png

                  The problem as seen on the image is that sometimes the lines are too thin when they should always be the same width. My algorithm finds the 4 vertices for the first one then the top 2 vertices of the next ones are the bottom 2 of the previous. This creates connected lines, but it seems to not always work. How could I fix this?

                  This is my algorithm:

                   void OGLENGINEFUNCTIONS::GenerateLinePoly(const std::vector<std::vector<GLdouble>> &input,
                                            std::vector<GLfloat> &output, int width)
                   {
                       output.clear();
                  
                       if(input.size() < 2)
                       {
                           return;
                       }
                  
                       int temp;
                       float dirlen;
                       float perplen;
                       POINTFLOAT start;
                       POINTFLOAT end;
                       POINTFLOAT dir;
                       POINTFLOAT ndir;
                       POINTFLOAT perp;
                       POINTFLOAT nperp;
                  
                       POINTFLOAT perpoffset;
                       POINTFLOAT diroffset;
                  
                       POINTFLOAT p0, p1, p2, p3;
                  
                       for(unsigned int i = 0; i < input.size() - 1; ++i)
                       {
                  
                           start.x = static_cast<float>(input[i][0]);
                           start.y = static_cast<float>(input[i][1]);
                  
                           end.x = static_cast<float>(input[i + 1][0]);
                           end.y = static_cast<float>(input[i + 1][1]);
                  
                           dir.x = end.x - start.x;
                           dir.y = end.y - start.y;
                  
                           dirlen = sqrt((dir.x * dir.x) + (dir.y * dir.y));
                  
                           ndir.x = static_cast<float>(dir.x * 1.0 / dirlen);
                           ndir.y = static_cast<float>(dir.y * 1.0 / dirlen);
                  
                           perp.x = dir.y;
                           perp.y = -dir.x;
                  
                           perplen = sqrt((perp.x * perp.x) + (perp.y * perp.y));
                  
                           nperp.x = static_cast<float>(perp.x * 1.0 / perplen);
                           nperp.y = static_cast<float>(perp.y * 1.0 / perplen);
                  
                           perpoffset.x = static_cast<float>(nperp.x * width * 0.5);
                           perpoffset.y = static_cast<float>(nperp.y * width * 0.5);
                  
                           diroffset.x = static_cast<float>(ndir.x * 0 * 0.5);
                           diroffset.y = static_cast<float>(ndir.y * 0 * 0.5);
                  
                              // p0 = start + perpoffset - diroffset
                              // p1 = start - perpoffset - diroffset
                              // p2 = end + perpoffset + diroffset
                              // p3 = end - perpoffset + diroffset 
                  
                           p0.x = start.x + perpoffset.x - diroffset.x;
                           p0.y = start.y + perpoffset.y - diroffset.y;
                  
                           p1.x = start.x - perpoffset.x - diroffset.x;
                           p1.y = start.y - perpoffset.y - diroffset.y;
                  
                           if(i > 0)
                           {
                               temp = (8 * (i - 1));
                               p2.x = output[temp + 2];
                               p2.y = output[temp + 3];
                               p3.x = output[temp + 4];
                               p3.y = output[temp + 5];
                  
                           }
                           else
                           {
                               p2.x = end.x + perpoffset.x + diroffset.x;
                               p2.y = end.y + perpoffset.y + diroffset.y;
                  
                               p3.x = end.x - perpoffset.x + diroffset.x;
                               p3.y = end.y - perpoffset.y + diroffset.y;
                           }
                  
                  
                  
                           output.push_back(p2.x);
                           output.push_back(p2.y);
                           output.push_back(p0.x);
                           output.push_back(p0.y);
                           output.push_back(p1.x);
                           output.push_back(p1.y);
                           output.push_back(p3.x);
                           output.push_back(p3.y);
                  
                       }
                   }
                  


                  Edit:

                   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 + v1.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;
                   }
                  
                   void OGLENGINEFUNCTIONS::GenerateLinePoly(const std::vector<std::vector<GLdouble> > &input,
                                            std::vector<GLfloat> &output, int width)
                   {
                       output.clear();
                  
                       if(input.size() < 2)
                       {
                           return;
                       }
                  
                       float w = width / 2.0f;
                  
                       //glBegin(GL_TRIANGLES);
                       for( size_t i = 0; i < input.size()-1; ++i )
                       {
                           POINTFLOAT cur;
                           cur.x = input[i][0];
                           cur.y = input[i][1];
                  
                  
                           POINTFLOAT nxt;
                           nxt.x = input[i+1][0];
                           nxt.y = input[i+1][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;
                  
                           output.push_back(p0.x);
                           output.push_back(p0.y);
                           output.push_back(p1.x);
                           output.push_back(p1.y);
                           output.push_back(p2.x);
                           output.push_back(p2.y);
                  
                           output.push_back(p2.x);
                           output.push_back(p2.y);
                           output.push_back(p1.x);
                           output.push_back(p1.y);
                           output.push_back(p3.x);
                           output.push_back(p3.y);
                  
                  
                  
                           // only do joins when we have a prv
                           if( i == 0 ) continue;
                  
                           POINTFLOAT prv;
                           prv.x = input[i-1][0];
                           prv.y = input[i-1][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 = 4;
                  
                           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 )
                           {
                  
                               output.push_back(cur.x);
                               output.push_back(cur.y);
                  
                               if( det > 0 )
                               {
                                   output.push_back(round[j + 1].x);
                                   output.push_back(round[j + 1].y);
                                   output.push_back(round[j].x);
                                   output.push_back(round[j].y);
                               }
                               else
                               {
                  
                                   output.push_back(round[j].x);
                                   output.push_back(round[j].y);
                  
                                   output.push_back(round[j + 1].x);
                                   output.push_back(round[j + 1].y);
                               }
                           }
                       }
                   }
                  

                  解决方案

                  Requires Eigen as written, but the core operations should map easily to whatever vector class you're using.

                  // 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 = 4;
                          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);
                          }
                  
                          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();
                  }
                  

                  EDIT: Screenshots:

                  这篇关于多边形轮廓上的边缘并不总是正确的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                  上一篇:使用 opengl 进行真正的等距投影 下一篇:Mac OSX 10.9 中的 Glut 弃用,IDE:QT Creator

                  相关文章

                  最新文章

                • <legend id='3eVv8'><style id='3eVv8'><dir id='3eVv8'><q id='3eVv8'></q></dir></style></legend>

                  <small id='3eVv8'></small><noframes id='3eVv8'>

                  <i id='3eVv8'><tr id='3eVv8'><dt id='3eVv8'><q id='3eVv8'><span id='3eVv8'><b id='3eVv8'><form id='3eVv8'><ins id='3eVv8'></ins><ul id='3eVv8'></ul><sub id='3eVv8'></sub></form><legend id='3eVv8'></legend><bdo id='3eVv8'><pre id='3eVv8'><center id='3eVv8'></center></pre></bdo></b><th id='3eVv8'></th></span></q></dt></tr></i><div id='3eVv8'><tfoot id='3eVv8'></tfoot><dl id='3eVv8'><fieldset id='3eVv8'></fieldset></dl></div>
                  <tfoot id='3eVv8'></tfoot>
                    • <bdo id='3eVv8'></bdo><ul id='3eVv8'></ul>