line()
Shape / 2D PrimitivesDescription
Draws a line between two points. Supports both 2D and 3D.
Syntax
void line(float x1, float y1, float x2, float y2)
void line(float x1, float y1, float z1, float x2, float y2, float z2)
Parameters
| Name | Type | Description |
|---|---|---|
| x1 | float | x-coordinate of the first point |
| y1 | float | y-coordinate of the first point |
| x2 | float | x-coordinate of the second point |
| y2 | float | y-coordinate of the second point |
| z1/z2 | float | z-coordinates (3D only, optional) |
Returns
voidRelated
Under the Hood
From Processing.h:
void line(float x1, float y1, float x2, float y2);
void line(float,float,float,float);
void line(float,float,float,float,float,float);
inline void line(A x1,B y1,C x2,D y2){ _api::line((float)x1,(float)y1,(float)x2,(float)y2);
inline void line(A x1,B y1,C z1,D x2,E y2,F z2){ _api::line((float)x1,(float)y1,(float)z1,(float)x2,(float)y2,(float)z2);
void line(float x1, float y1, float z1, float x2, float y2, float z2);
template<typename A,typename B,typename C,typename D,typename=std::enable_if_t<std::is_arithmetic_v<A>&&std::is_arithmetic_v<B>&&std::is_arithmetic_v<C>&&std::is_arithmetic_v<D>>>
void line(A x1,B y1,C x2,D y2){ line((float)x1,(float)y1,(float)x2,(float)y2);
template<typename A,typename B,typename C,typename D,typename E,typename F,typename=std::enable_if_t<std::is_arithmetic_v<A>&&std::is_arithmetic_v<B>&&std::is_arithmetic_v<C>&&std::is_arithmetic_v<D>&&std::is_arithmetic_v<E>&&std::is_arithmetic_v<F>>>
void line(A x1,B y1,C z1,D x2,E y2,F z2){ line((float)x1,(float)y1,(float)z1,(float)x2,(float)y2,(float)z2);
inline void line(float x1,float y1,float x2,float y2){ if(PApplet::g_papplet) PApplet::g_papplet->line(x1,y1,x2,y2); }
inline void line(float x1,float y1,float z1,float x2,float y2,float z2){ if(PApplet::g_papplet) PApplet::g_papplet->line(x1,y1,z1,x2,y2,z2); }
inline void PGraphics::line(float x1, float y1, float x2, float y2) { if(PApplet::g_papplet) PApplet::g_papplet->line(x1,y1,x2,y2); }
Under the Hood
From Processing.cpp:
void PApplet::line(float x1, float y1, float x2, float y2) {
{
GLint mvDepth=0, projDepth=0;
glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &mvDepth);
glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &projDepth);
double mv[16], proj[16];
glGetDoublev(GL_MODELVIEW_MATRIX, mv);
glGetDoublev(GL_PROJECTION_MATRIX, proj);
GLint vp[4]; glGetIntegerv(GL_VIEWPORT, vp);
GLint curFbo=0; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curFbo);
PDEBUG("PApplet::line(%.1f,%.1f,%.1f,%.1f) ENTRY: mvDepth=%d projDepth=%d curFbo=%d viewport=(%d,%d,%d,%d)\n",
x1,y1,x2,y2, mvDepth, projDepth, curFbo, vp[0],vp[1],vp[2],vp[3]);
PDEBUG(" mv[0]=%.3f mv[5]=%.3f mv[12]=%.3f mv[13]=%.3f\n", mv[0],mv[5],mv[12],mv[13]);
PDEBUG(" proj[0]=%.6f proj[5]=%.6f proj[12]=%.6f proj[13]=%.6f\n", proj[0],proj[5],proj[12],proj[13]);
}
if (!doStroke) return;
applyStroke();
float w = strokeW;
if (w <= 1.0f) {
// Thin lines: use GL_LINES
glLineWidth(1.0f);
glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x2,y2); glEnd();
restoreLighting();
return;
}
// Thick line: quad body + round caps using stencil to prevent double-blend
float dx = x2-x1, dy = y2-y1;
float len = std::sqrt(dx*dx+dy*dy);
if(len < 0.0001f){ restoreLighting(); return; }
float ux = dx/len, uy = dy/len;
float r = w*0.5f;
float px2 = -uy*r, py2 = ux*r; // perpendicular
int segs = std::max(16, (int)(r*4.0f));
// Use stencil to draw all geometry, then fill once -- prevents double-blend
glEnable(GL_STENCIL_TEST);
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
// Draw body into stencil
glBegin(GL_QUADS);
glVertex2f(x1+px2,y1+py2); glVertex2f(x2+px2,y2+py2);
glVertex2f(x2-px2,y2-py2); glVertex2f(x1-px2,y1-py2);
glEnd();
// Draw end caps into stencil
for(int ep=0;ep<2;ep++){
float cx2=ep?x2:x1, cy2=ep?y2:y1;
glBegin(GL_TRIANGLE_FAN);
glVertex2f(cx2,cy2);
for(int s=0;s<=segs;s++){
float a=s*TWO_PI/segs;
glVertex2f(cx2+std::cos(a)*r, cy2+std::sin(a)*r);
}
glEnd();
}
// Now draw color only where stencil=1
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFF);
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// Fill bounding box with stroke color
float minx=std::min(x1,x2)-r, maxx=std::max(x1,x2)+r;
float miny=std::min(y1,y2)-r, maxy=std::max(y1,y2)+r;
glBegin(GL_QUADS);
glVertex2f(minx,miny); glVertex2f(maxx,miny);
glVertex2f(maxx,maxy); glVertex2f(minx,maxy);
glEnd();
glDisable(GL_STENCIL_TEST);
restoreLighting();
}
void PApplet::line(float x1, float y1, float z1, float x2, float y2, float z2) {
if (!doStroke) return;
applyStroke();
glLineWidth(strokeW);
glBegin(GL_LINES); glVertex3f(x1,y1,z1); glVertex3f(x2,y2,z2); glEnd();
restoreLighting();
}
std::string line;
line = charLine;
line = tok;
line = candidate;
std::string curMat, line;
std::string line(buf);