sandbox/acastillo/input_fields/draw_filaments.h

    #include "PointTriangle.h"
    void draw_space_curve(int n_seg, coord *p){
      // // Set the clear color to a shade of blue (RGBA)
      // glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    
      // // Clear the color buffer
      // glClear(GL_COLOR_BUFFER_BIT);
    
      // Set the line width to a thicker value
      glLineWidth(3.0f);
    
      // Change the color
      glColor3f(1.0f, 0.0f, 0.0f);
      for (int i = 0; i < n_seg-1; i++){
        glBegin(GL_LINES);
          glVertex3f(p[i  ].x, p[i  ].y, p[i  ].z);
          glVertex3f(p[i+1].x, p[i+1].y, p[i+1].z);
        glEnd();
      }
    }
    
    void draw_space_curve_with_vector(int n_seg, coord *p, coord *t, float scale=1.0) {
      // // Set the clear color to a shade of blue (RGBA)
      // glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    
      // // Clear the color buffer
      // glClear(GL_COLOR_BUFFER_BIT);
    
      glLineWidth(5.0f);
      for (int i = 0; i < n_seg-1; i++) {
        // Start point of the vector is the curve point p[i]
        // End point of the vector is p[i] + t[i]
        glColor3f(1.0f, 0.0f, 0.0f);
        glBegin(GL_LINES);
          glVertex3f(p[i].x,                p[i].y,                p[i].z);
          glVertex3f(p[i].x + scale*t[i].x, p[i].y + scale*t[i].y, p[i].z + scale*t[i].z);
        glEnd();
      }
    }
    
    void draw_space_curve_with_vectors(int n_seg, coord *p, coord *t, coord *n, coord *b, float scale=1.0) {
      // // Set the clear color to a shade of blue (RGBA)
      // glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    
      // // Clear the color buffer
      // glClear(GL_COLOR_BUFFER_BIT);
    
      glLineWidth(5.0f);
      for (int i = 0; i < n_seg-1; i++) {
        // Start point of the vector is the curve point p[i]
        // End point of the vector is p[i] + t[i]
        glColor3f(1.0f, 0.0f, 0.0f);
        glBegin(GL_LINES);
          glVertex3f(p[i].x,                p[i].y,                p[i].z);
          glVertex3f(p[i].x + scale*t[i].x, p[i].y + scale*t[i].y, p[i].z + scale*t[i].z);
        glEnd();
        
        // End point of the vector is p[i] + n[i]
        glColor3f(0.0f, 1.0f, 0.0f);
        glBegin(GL_LINES);
          glVertex3f(p[i].x,                p[i].y,                p[i].z);
          glVertex3f(p[i].x + scale*n[i].x, p[i].y + scale*n[i].y, p[i].z + scale*n[i].z);
        glEnd();
    
        // End point of the vector is p[i] + b[i]
        glColor3f(0.0f, 0.0f, 1.0f);
        glBegin(GL_LINES);
          glVertex3f(p[i].x,                p[i].y,                p[i].z);
          glVertex3f(p[i].x + scale*b[i].x, p[i].y + scale*b[i].y, p[i].z + scale*b[i].z);
        glEnd();
      }
    }
    
    void draw_tube_along_curve(int n, coord *p, double *a, int segments=16, double scale=1.0) {
      // // Set the clear color to a shade of blue (RGBA)
      // glClearColor(0.384f, 0.365f, 0.353f, 1.0f);
    
      // // Clear the color buffer
      // glClear(GL_COLOR_BUFFER_BIT);
    
      if (n < 2) return; // Need at least two points to form a segment
    
      for (int i = 0; i < n - 1; ++i) {
        // Define the two endpoints of the current segment
        coord p1 = p[i];
        float a1 = a[i]*scale;
        coord p2 = p[i + 1];    
        float a2 = a[i + 1]*scale;
    
        // Calculate the tangent vector of the curve segment
        coord tangent = vecdiff(p2, p1);
        
        // Normalize the tangent vector
        float tangentLength = sqrtf(vecdot(tangent,tangent));
        if (tangentLength < 1e-6f) continue; // Avoid division by zero for degenerate segments
        foreach_dimension()
          tangent.x /= tangentLength;
    
        // Find a vector orthogonal to the tangent    
        coord up = {0.0f, 1.0f, 0.0f}; // A default up vector
        // If the tangent is close to the up vector, use a different reference
        if (fabsf(tangent.y) > 0.99f) {
          up = (coord){1.0f, 0.0f, 0.0f};
        }
    
        coord normal;
        foreach_dimension()
          normal.x = tangent.y * up.z - tangent.z * up.y;
    
        // Normalize the normal vector
        float normalLength = sqrtf(vecdot(normal,normal));
        foreach_dimension()
          normal.x /= normalLength;
        
        // Calculate the binormal vector (orthogonal to both tangent and normal)
        coord binormal;
        foreach_dimension()
          binormal.x = tangent.y * normal.z - tangent.z * normal.y;
        
        // Generate vertices for the tube segment using GL_QUADS
        for (int j = 0; j < segments; ++j) {
          float angle1 = 2.0f * pi * j / segments;
          float angle2 = 2.0f * pi * (j + 1) / segments;
    
          float cosAngle1 = cosf(angle1);
          float sinAngle1 = sinf(angle1);
          float cosAngle2 = cosf(angle2);
          float sinAngle2 = sinf(angle2);
    
          // Calculate the coordinates of the vertices on the circles at p1 and p2
          coord v1p1 = {p1.x + a1 * (cosAngle1 * normal.x + sinAngle1 * binormal.x),
                        p1.y + a1 * (cosAngle1 * normal.y + sinAngle1 * binormal.y),
                        p1.z + a1 * (cosAngle1 * normal.z + sinAngle1 * binormal.z)};
    
          coord v2p1 = {p1.x + a1 * (cosAngle2 * normal.x + sinAngle2 * binormal.x),
                        p1.y + a1 * (cosAngle2 * normal.y + sinAngle2 * binormal.y),
                        p1.z + a1 * (cosAngle2 * normal.z + sinAngle2 * binormal.z)};
    
          coord v1p2 = {p2.x + a2 * (cosAngle1 * normal.x + sinAngle1 * binormal.x),
                        p2.y + a2 * (cosAngle1 * normal.y + sinAngle1 * binormal.y),
                        p2.z + a2 * (cosAngle1 * normal.z + sinAngle1 * binormal.z)};
    
          coord v2p2 = {p2.x + a2 * (cosAngle2 * normal.x + sinAngle2 * binormal.x),
                        p2.y + a2 * (cosAngle2 * normal.y + sinAngle2 * binormal.y),
                        p2.z + a2 * (cosAngle2 * normal.z + sinAngle2 * binormal.z)};
    
          // Draw the white panels (GL_QUADS)
          glColor3f(1.0f, 1.0f, 1.0f);
          glBegin(GL_QUADS);
            glVertex3f(v1p1.x, v1p1.y, v1p1.z);
            glVertex3f(v2p1.x, v2p1.y, v2p1.z);
            glVertex3f(v2p2.x, v2p2.y, v2p2.z);
            glVertex3f(v1p2.x, v1p2.y, v1p2.z);
          glEnd();
    
          // Draw the black edges (GL_LINES)
          glColor3f(0.0f, 0.0f, 0.0f);
          glBegin(GL_LINES);
            // Around the first circle
            glVertex3f(v1p1.x, v1p1.y, v1p1.z);
            glVertex3f(v2p1.x, v2p1.y, v2p1.z);
    
            // Around the second circle
            glVertex3f(v1p2.x, v1p2.y, v1p2.z);
            glVertex3f(v2p2.x, v2p2.y, v2p2.z);
    
            // Connecting the two circles
            glVertex3f(v1p1.x, v1p1.y, v1p1.z);
            glVertex3f(v1p2.x, v1p2.y, v1p2.z);
    
            glVertex3f(v2p1.x, v2p1.y, v2p1.z);
            glVertex3f(v2p2.x, v2p2.y, v2p2.z);
          glEnd();
        }
      }
    }