2008-09-19 19 views

Respuesta

1

Suponga que sus puntos originales son (x1, y1) -> (x2, y2). Use los siguientes puntos (x1-width/2, y1), (x1 + width/2, y1), (x2-width/2, y2), (x2 + width/2, y2) para construir un rectángulo y luego use quads/tris para dibujarlo. Esta es la manera simple e ingenua. Tenga en cuenta que para anchos de línea grandes obtendrá un comportamiento de punto final extraño. Lo que realmente quiere hacer entonces son algunos cálculos inteligentes de líneas paralelas (que no deberían ser tan malos) utilizando vectores matemáticos. Por alguna razón, viene a la mente el producto punto/cruz y la proyección vectorial.

+0

respuesta @Ozgur 's es mucho mejor. Considere agregar el vector matemático del que está hablando. – Valdrinit

14

se puede dibujar dos triángulos:

// Draws a line between (x1,y1) - (x2,y2) with a start thickness of t1 and 
// end thickness t2. 
void DrawLine(float x1, float y1, float x2, float y2, float t1, float t2) 
{ 
    float angle = atan2(y2 - y1, x2 - x1); 
    float t2sina1 = t1/2 * sin(angle); 
    float t2cosa1 = t1/2 * cos(angle); 
    float t2sina2 = t2/2 * sin(angle); 
    float t2cosa2 = t2/2 * cos(angle); 

    glBegin(GL_TRIANGLES); 
    glVertex2f(x1 + t2sina1, y1 - t2cosa1); 
    glVertex2f(x2 + t2sina2, y2 - t2cosa2); 
    glVertex2f(x2 - t2sina2, y2 + t2cosa2); 
    glVertex2f(x2 - t2sina2, y2 + t2cosa2); 
    glVertex2f(x1 - t2sina1, y1 + t2cosa1); 
    glVertex2f(x1 + t2sina1, y1 - t2cosa1); 
    glEnd(); 
} 
+3

¡Esto es demasiado complicado! Demasiada trigonometría donde no es necesaria también. – PierreBdR

+0

Resultó esto no es lo que quería el OP (véase su respuesta a continuación). Pero me gustaría ver un algoritmo más simple, si le importaría compartirlo. –

+0

he añadido una versión libre trig aquí ahora – bobobobo

0

un rectángulo (es decir, dos o GL_QUAD GL_TRIANGLES) suena como su mejor apuesta por los sonidos de la misma, no está seguro de lo que puedo pensar en ninguna otra manera.

9

Ok, ¿qué tal esto: (Ozgar)

 

     A 
    /\ 
    / \ 
    . p1  \ 
/    \ 
/     D 
B -     .p2 
     - - - C 

Así AB es width1 y el CD es width2.

Entonces,

// find line between p1 and p2 
Vector p1p2 = p2 - p1 ; 

// find a perpendicular 
Vector perp = p1p2.perpendicular().normalize() 

// Walk from p1 to A 
Vector A = p1 + perp*(width1/2) 
Vector B = p1 - perp*(width1/2) 

Vector C = p2 - perp*(width2/2) 
Vector D = p2 - perp*(width2/2) 

// wind triangles 
Triangle(A, B, D) 
Triangle(B, D, C) 

Nota hay potencialmente un problema CCW CW/bobinado con este algoritmo - si perp se calcula como (-y, x) en el diagrama anterior, entonces será devanado CCW, si (y, -x) entonces será un bobinado CW.

1

Otra forma de hacerlo, si está escribiendo un rasterizador de software por casualidad, es utilizar coordenadas baricéntricas en la etapa de coloración de píxeles y píxeles de color cuando una de las coordenadas baricéntricas está cerca de 0. Mientras más asignación hagas, más gruesas serán las líneas.

1

He tenido que hacer lo mismo hoy.

Para la creación de una línea que se extiende por (x1,y1) -> (x2,y2) de un determinado width, un método muy fácil es transformar un simple cuadrados unidad de tamaño que abarca (0., -0.5) -> (1., 0.5) usando:

  1. glTranslatef(...) para moverlo a su (x1,y1) ubicación deseada;
  2. glScalef(...) para escalarlo a la derecha length y width deseado: utilice length = sqrt((x2-x1)^2 + (y2-y1)^2) o cualquier otra aproximación de baja complejidad;
  3. glRotatef(...) a angle a la orientación correcta: use angle = atan2(y2-y1, x2-x1).

La unidad-cuadrado se crea de forma muy simple a partir de una tira de dos triángulos GL_TRIANGLE_STRIP, que se convierte en una línea continua después de las transformaciones anteriores.

La carga aquí se coloca principalmente en OpenGL (y su hardware de gráficos) en lugar de su código de aplicación. El procedimiento anterior se convierte fácilmente en una función genérica al rodear llamadas glPushMatrix() y glPopMatrix().

2

Para los que vienen en busca de una buena solución a esto, este código se escribe utilizando LWJGL, pero puede adaptarse fácilmente a cualquier implementación de OpenGL.

import java.awt.Color; 
import org.lwjgl.opengl.GL11; 
import org.lwjgl.util.vector.Vector2f; 
public static void DrawThickLine(int startScreenX, int startScreenY, int endScreenX, int endScreenY, Color color, float alpha, float width) { 

    Vector2f start = new Vector2f(startScreenX, startScreenY); 
    Vector2f end = new Vector2f(endScreenX, endScreenY); 

    float dx = startScreenX - endScreenX; 
    float dy = startScreenY - endScreenY; 

    Vector2f rightSide = new Vector2f(dy, -dx); 
    if (rightSide.length() > 0) { 
     rightSide.normalise(); 
     rightSide.scale(width/2); 
    } 
    Vector2f leftSide = new Vector2f(-dy, dx); 
    if (leftSide.length() > 0) { 
     leftSide.normalise(); 
     leftSide.scale(width/2); 
    } 

    Vector2f one = new Vector2f(); 
    Vector2f.add(leftSide, start, one); 

    Vector2f two = new Vector2f(); 
    Vector2f.add(rightSide, start, two); 

    Vector2f three = new Vector2f(); 
    Vector2f.add(rightSide, end, three); 

    Vector2f four = new Vector2f(); 
    Vector2f.add(leftSide, end, four); 

    GL11.glBegin(GL11.GL_QUADS); 
    GL11.glColor4f(color.getRed(), color.getGreen(), color.getBlue(), alpha); 
    GL11.glVertex3f(one.x, one.y, 0); 
    GL11.glVertex3f(two.x, two.y, 0); 
    GL11.glVertex3f(three.x, three.y, 0); 
    GL11.glVertex3f(four.x, four.y, 0); 
    GL11.glColor4f(1, 1, 1, 1); 
    GL11.glEnd(); 
}