Note that there are some explanatory texts on larger screens.

plurals
  1. POEdges on polygon outlines not always correct
    text
    copied!<p>I'm using the algorithm below to generate quads which are then rendered to make an outline like this </p> <blockquote> <p><a href="http://img810.imageshack.us/img810/8530/uhohz.png" rel="nofollow noreferrer">http://img810.imageshack.us/img810/8530/uhohz.png</a></p> </blockquote> <p>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 <code>4</code> vertices for the first one then the top <code>2</code> vertices of the next ones are the bottom <code>2</code> of the previous. This creates connected lines, but it seems to not always work. How could I fix this?</p> <p>This is my algorithm:</p> <pre><code> void OGLENGINEFUNCTIONS::GenerateLinePoly(const std::vector&lt;std::vector&lt;GLdouble&gt;&gt; &amp;input, std::vector&lt;GLfloat&gt; &amp;output, int width) { output.clear(); if(input.size() &lt; 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 &lt; input.size() - 1; ++i) { start.x = static_cast&lt;float&gt;(input[i][0]); start.y = static_cast&lt;float&gt;(input[i][1]); end.x = static_cast&lt;float&gt;(input[i + 1][0]); end.y = static_cast&lt;float&gt;(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&lt;float&gt;(dir.x * 1.0 / dirlen); ndir.y = static_cast&lt;float&gt;(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&lt;float&gt;(perp.x * 1.0 / perplen); nperp.y = static_cast&lt;float&gt;(perp.y * 1.0 / perplen); perpoffset.x = static_cast&lt;float&gt;(nperp.x * width * 0.5); perpoffset.y = static_cast&lt;float&gt;(nperp.y * width * 0.5); diroffset.x = static_cast&lt;float&gt;(ndir.x * 0 * 0.5); diroffset.y = static_cast&lt;float&gt;(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 &gt; 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); } } </code></pre> <hr> <p><strong>Edit:</strong></p> <pre><code> POINTFLOAT multiply(const POINTFLOAT &amp;a, float b) { POINTFLOAT result; result.x = a.x * b; result.y = a.y * b; return result; } POINTFLOAT normalize(const POINTFLOAT &amp;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 &lt; -1.0f ) dot = -1.0f; if( dot &gt; 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&lt;std::vector&lt;GLdouble&gt; &gt; &amp;input, std::vector&lt;GLfloat&gt; &amp;output, int width) { output.clear(); if(input.size() &lt; 2) { return; } float w = width / 2.0f; //glBegin(GL_TRIANGLES); for( size_t i = 0; i &lt; 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 &gt; 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&lt; POINTFLOAT&gt; 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 &lt; num_pts+1; ++j ) { float t = (float)j / (float)(num_pts + 1); if( det &gt; 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 &lt; round.size()-1; ++j ) { output.push_back(cur.x); output.push_back(cur.y); if( det &gt; 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); } } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload