Skip to content

Instantly share code, notes, and snippets.

@psyq321
Created June 26, 2023 21:56
Show Gist options
  • Save psyq321/652142040a40cee7f7afc23c4b995358 to your computer and use it in GitHub Desktop.
Save psyq321/652142040a40cee7f7afc23c4b995358 to your computer and use it in GitHub Desktop.

QUESTION: User is simulating biological tissue, described as 3D surface mesh, where each mesh triangle has an assigned set of "depth" values each representing the thickness of subsurface layer forming the volume using sections of inverse surface normal vector (pointing "inwards" into the mesh) - for example, neocortex has 6 layers, so each cortical mesh triangle will have 6 floating point values associated in addition to the surface normals. A cell is a 3D point inside the volume described by the triangle and associated layer depth(s).

In C++ 20, and using GLM math library, implement routine that created X (number provided by user) cells inside the volume described by the surface mesh and corresponding layer information (number of layers, thickness of each layer and surface normal(s)) ensuring:

a) Fair coverage of triangles b) Close to homogeneous volume between layers and triangles (cell concentration)

--

GPT-4 ANSWER:

The implementation of the problem can be quite complex due to its geometric nature and requires deep understanding of 3D geometry as well as good grasp over C++ programming.

One possible implementation could involve these main steps:

  • Iterating over triangles of the mesh, calculating the triangle area
  • Normalizing areas of the triangles, so that total of areas equals 1.0
  • Discretize 3D space, calculating the bin centers and assigning cells to the closest bin
  • Choose X sample points using a uniform random distribution across the surface area.

Here is an example that creates a distribution of points over each triangle.

#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <random>
 
struct Triangle {
    glm::vec3 vertices[3] = {glm::vec3(0), glm::vec3(0), glm::vec3(0)};
    glm::vec3 normal; 
    float depths[6];
};

struct Cell {
    glm::vec3 position;
};

std::vector<Cell> generateCells(std::vector<Triangle> &triangles, unsigned int X) {
    std::default_random_engine generator;
    std::vector<Cell> cells;
    cells.reserve(X);
    
    for (int i = 0; i < X; i++){
        std::uniform_real_distribution<float> distribution(0.0f, 1.0f);

        // Choose triangle
        float triangleChoice = distribution(generator);
        int triangleIndex;
        float accumulated = 0;

        for (triangleIndex = 0; triangleIndex < triangles.size(); triangleIndex++){
            if (accumulated >= triangleChoice) 
                break;
            accumulated += triangles[triangleIndex].area;
        }

        // Choose point inside triangle
        float u = distribution(generator);
        float v = distribution(generator);

        if (u + v >= 1){
            u = 1.0f - u;
            v = 1.0f - v;
        }

        glm::vec3 pointInTriangle = (1 - u - v) * triangles[triangleIndex].vertices[0] + u * triangles[triangleIndex].vertices[1] + v * triangles[triangleIndex].vertices[2];

        // Choose depth - uniformly distributed across all layers
        float depthChoice = distribution(generator);
        int layerIndex = static_cast<int>(depthChoice * 5);
        float cellDepth = triangles[triangleIndex].depths[layerIndex] * depthChoice;

        glm::vec3 pointInVolume = pointInTriangle + triangles[triangleIndex].normal * cellDepth;
        
        cells.push_back({pointInVolume});
    }
    return cells;
}

This code follows "a)" and "b)" rules by uniformly distributing the volume of the cells across all layers and all triangles in a way that gives a higher cell concentration to larger triangles. However, consideration is not given to the spatial distribution of the cells within each triangle-layer, which according to "b)" should ideally be homogeneous.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment