Author Topic: Geometry help, drawing a polyline with a width attribute.  (Read 3858 times)

0 Members and 1 Guest are viewing this topic.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile


Recently I've been stuck trying to draw a polyline with a width attribute. I'm using OpenGl. Even when you set the width of a line you get uguly corners when you draw rotated lines. I'm calling a series of lines that share points a polyline.

Basically how can I draw a series of thick lines (as quads) with unbroken end joints? I don't have my trusty AutoCAD on me right now or I would make a diagram. I can't just use a circle at each joint in the polyline because I want sharp corners.

Any ideas?
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
If the line is R wide, then draw a circle radius R at the beginning and end, and draw a line between the edges of each circle.  I did a rounded triangle routine once that needed this...I can hunt it out...

Jim
Challenge Trophies Won:

Offline relsoft

  • DBF Aficionado
  • ******
  • Posts: 3303
  • Karma: 47
    • View Profile
x-out once told me how to do it by giving me an image.  All I needed to do was to use line normals to make my lines volumetric.  It's limited to 2d though. 
Challenge Trophies Won:

Offline stormbringer

  • Time moves by fast, no second chance
  • Amiga 1200
  • ****
  • Posts: 453
  • Karma: 73
    • View Profile
    • www.retro-remakes.net
I wrote a couple of algorithms to do this, but cannot share the code since it's for commercial use... anyway the technique is simple, but quite complex if you want to have it rock-solid.

The idea is for every segment in your poly-line, calculate the normal vectors. the width of you thick line would be a scale factor for your normal vectors. This will give you 2 new vertices and then you can link them with a line => for each of your lines in your poly-line you will end up with a quad that you can draw or fill, easily with OpenGL.

This will give you the same results as OpenGL's thick line capabilities. The next step is to handle how these new segments are joined. You can either join them with a straight line (bevel join), an arc (round join) or à  la Postscript mitter-joins which is a sort of modified bevel-join. In any case reading the theory on the subject in the PostScript manual is a good start. Just google for "postscript path stroke", you will find enough information.

Obvioulsy, the method above only gives you the contour on one side of your poly-line. The orientation of your polyline (the order of the vertices in your array) will tell you if it's the "inside" or "outside" contour.

The difficult part is degenrated polygons, self-intersecting poly-lines and of course self-intersections in the newly generated contours... You will have to do some math and treat cases almost one by one, as there is no unique and clean algorithm to draw perfect thick lines.

It also depends a lot on what you intend to do. If your thick lines are all of the same color (no gradients, plain color only) you can cheat and forget about selft interections... up to some point.
We once had a passion
It all seemed so right
So young and so eager
No end in sight
But now we are prisoners
In our own hearts
Nothing seems real
It's all torn apart

Offline relsoft

  • DBF Aficionado
  • ******
  • Posts: 3303
  • Karma: 47
    • View Profile
Rock: I believe we have almost the same approach in rendering 2d volume lines:

Code: [Select]
sub draw_line_glow ( byval x1 as single, byval y1 as single, byval x2 as single, byval y2 as single,_
byval lwidth as single, byval r as single, byval g as single, byval b as single,_
byval alpha as single)



dim as single nx,ny
nx = -(y2-y1)
ny =  (x2-x1)

dim leng as single
    leng = sqr(nx * nx + ny * ny )
    nx = nx / leng
    ny = ny / leng

nx *= lwidth/2
ny *= lwidth/2

dim as single lx1, ly1, lx2, ly2, lx3, ly3, lx4, ly4

lx1 = x2+nx
    ly1 = y2+ny
    lx2 = x2-nx
    ly2 = y2-ny                           
    lx3 = x1-nx
    ly3 = y1-ny
    lx4 = x1+nx
    ly4 = y1+ny

glColor4f (r, g, b, alpha)
glPushmatrix()
glbegin(GL_QUADS)
glTexCoord2f( 0.5,0 )
glVertex3f( lx1,ly1,0 )

glTexCoord2f( 0.5,1 )
glVertex3f( lx2,ly2,0 )

glTexCoord2f( 0.5,1 )
glVertex3f( lx3, ly3,0 )

glTexCoord2f( 0.5,0 )
glVertex3f( lx4,ly4,0 )
glend()

'RIGHT
dim as single lx5, ly5,lx6,ly6,vx,vy
vx = (x2-x1)
vy = (y2-y1)
leng = sqr(vx * vx + vy * vy )
    vx = vx / leng
    vy = vy / leng
    vx *= lwidth/2
    vy *= lwidth/2
   
    lx5 = lx1 + vx
    ly5 = ly1 + vy
    lx6 = lx2 + vx
    ly6 = ly2 + vy
   
    glbegin(GL_QUADS)
glTexCoord2f( 0.5,0 )
glVertex3f( lx1,ly1,0 )

glTexCoord2f( 1,0 )
glVertex3f( lx5,ly5,0 )

glTexCoord2f( 1,1 )
glVertex3f( lx6, ly6,0 )

glTexCoord2f( 0.5,1 )
glVertex3f( lx2,ly2,0 )
glend()

  'LEFT
  lx5 = lx4 -vx
    ly5 = ly4 -vy
    lx6 = lx3 -vx
    ly6 = ly3 -vy
    glbegin(GL_QUADS)
glTexCoord2f( 0.5,0 )
glVertex3f( lx4,ly4,0 )

glTexCoord2f( 1,0 )
glVertex3f( lx5,ly5,0 )

glTexCoord2f( 1,1 )
glVertex3f( lx6, ly6,0 )

glTexCoord2f( 0.5,1 )
glVertex3f( lx3,ly3,0 )
glend()
   
glPopMatrix()

end sub

Added a zip file for the exe and the a diagram x-out gave me which gave me the start:
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile

Rel I was told that I was missing FREEIMAGE.DLL.

I've finally got back to my AutoCAD program and have drawn a rough image. The set of line points would be the inner red dotted line and the outer filled area would be the polygon.

Challenge Trophies Won:

Offline relsoft

  • DBF Aficionado
  • ******
  • Posts: 3303
  • Karma: 47
    • View Profile
Oh, you could download freeimafe.dll just about everywhere(google).

The code I posted above would do that with little modifications.
Challenge Trophies Won: