Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

swh:1:snp:c78d7a14cc07423acb6a43d0e3059b9afd67996a
  • Code
  • Branches (1)
  • Releases (0)
    • Branches
    • Releases
    • HEAD
    • refs/heads/master
    No releases to show
  • f9aac5f
  • /
  • src
  • /
  • makePolyhedralMesh.cpp
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
  • revision
  • snapshot
content badge
swh:1:cnt:507dafd075bd68cddd6409d2ecd80a3eeb8237d0
directory badge
swh:1:dir:4f575ba51229ed8a439e690987eb7223782b67ec
revision badge
swh:1:rev:c5be799ee3dad53f5edf10eeb39527bbca5add11
snapshot badge
swh:1:snp:c78d7a14cc07423acb6a43d0e3059b9afd67996a

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
  • revision
  • snapshot
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Tip revision: c5be799ee3dad53f5edf10eeb39527bbca5add11 authored by LorenzoDiazzi on 29 May 2025, 10:15:58 UTC
Update README.md
Tip revision: c5be799
makePolyhedralMesh.cpp
#include "conforming_mesh.h"
#include "extended_predicates.h"
#include "BSP.h"
#include <time.h>
#include "string.h"
#include "stdarg.h"

double getPeakMegabytesUsed();
void PrintMemoryInfo();

int vertex_compare(const void* void_v1, const void* void_v2)
{
    const vertex_t* v1 = (vertex_t*)void_v1;
    const vertex_t* v2 = (vertex_t*)void_v2;
    const double dx = v1->coord[0] - v2->coord[0];
    const double dy = v1->coord[1] - v2->coord[1];
    const double dz = v1->coord[2] - v2->coord[2];
    return (4 * ((dx > 0) - (dx < 0)) +
        2 * ((dy > 0) - (dy < 0)) +
        ((dz > 0) - (dz < 0)));
}

inline bool coincident_points(const vertex_t* a, const vertex_t* b)
{
    return !vertex_compare(a->coord, b->coord);
}

void remove_duplicated_points(vertex_t** vertices_p, uint32_t* npts,
    vertex_t* vrts_copy,
    uint32_t* map, uint32_t* diff) {

    // Sorting vertices by coordinates lexicographic order (x,y,z)
    qsort(vrts_copy, *npts, sizeof(vertex_t), vertex_compare);

    // Count and memory position of duplicated vertices.
    uint32_t vrts_counter = 0;
    for (uint32_t i = 1; i < (*npts); i++) {
        if (coincident_points(vrts_copy + i - 1, vrts_copy + i)) vrts_counter++;
        diff[i] = vrts_counter;
    }

    // Set original_index to follow vertices permutation.
    for (uint32_t i = 0; i < (*npts); i++)  map[vrts_copy[i].original_index] = i;

    // Allocating memory to store uinque mesh vertices (vertices_p).
    *vertices_p = (vertex_t*)malloc(sizeof(vertex_t) * (*npts - vrts_counter));

    // Fill mesh vertices (vertices_p)
    memcpy(*vertices_p, vrts_copy, sizeof(vertex_t));
    for (uint32_t i = vrts_counter = 1; i < (*npts); i++)
        if (!coincident_points(vrts_copy + i - 1, vrts_copy + i))
            memcpy(*vertices_p + (vrts_counter++), vrts_copy + i, sizeof(vertex_t));

    // Update uinque vertices number.
    (*npts) = vrts_counter;
}


/// //////////////////////////////////////////////////////////////////////////////////////////

void read_nodes_and_constraints(double* coords_A, uint32_t npts_A, uint32_t* tri_idx_A, uint32_t ntri_A,
    vertex_t** vertices_p, uint32_t* npts,
    uint32_t** tri_vertices_p, uint32_t* ntri, bool verbose) {

    // Reading points coordinates.
    *npts = npts_A;
    *ntri = ntri_A;
    vertex_t* tmp = (vertex_t*)malloc(*npts * sizeof(vertex_t));
    uint32_t* diff = (uint32_t*)calloc(*npts, sizeof(uint32_t));
    uint32_t* map = (uint32_t*)malloc(*npts * sizeof(uint32_t));
    *tri_vertices_p = (uint32_t*)malloc(sizeof(uint32_t) * 3 * (*ntri));

    for (uint32_t i = 0; i < (*npts); i++) {
        tmp[i].coord[0] = coords_A[i * 3];
        tmp[i].coord[1] = coords_A[i * 3 + 1];
        tmp[i].coord[2] = coords_A[i * 3 + 2];
        tmp[i].original_index = i;
    }

    if (*npts > 1) remove_duplicated_points(vertices_p, npts, tmp, map, diff);
    if (verbose) printf("Using %u unique vertices\n", *npts);

    free(tmp);

    for (uint32_t i = 0, j = 0; i < (*ntri); j++) {

        const uint32_t i1 = tri_idx_A[j * 3];
        const uint32_t i2 = tri_idx_A[j * 3 + 1];
        const uint32_t i3 = tri_idx_A[j * 3 + 2];
        (*tri_vertices_p)[3 * i] = map[i1] - diff[map[i1]];
        (*tri_vertices_p)[3 * i + 1] = map[i2] - diff[map[i2]];
        (*tri_vertices_p)[3 * i + 2] = map[i3] - diff[map[i3]];

        const double* v1c = ((*vertices_p) + (*tri_vertices_p)[3 * i])->coord;
        const double* v2c = ((*vertices_p) + (*tri_vertices_p)[3 * i + 1])->coord;
        const double* v3c = ((*vertices_p) + (*tri_vertices_p)[3 * i + 2])->coord;

        if (!misAlignment(v1c, v2c, v3c)) (*ntri)--;
        else i++;
    }
    free(map);
    free(diff);

    if (verbose) printf("Using %u non-degenerate constraints\n", *ntri);

    //// DEBUG
    //FILE *file = fopen("prova.off", "w");
    //fprintf(file, "OFF\n%u %u 0\n", *npts, *ntri);
    //for (uint32_t i = 0; i < (*npts); i++) fprintf(file, "%f %f %f\n", (*vertices_p)[i].coord[0], (*vertices_p)[i].coord[1], (*vertices_p)[i].coord[2]);
    //for (uint32_t i = 0; i < (*ntri); i++) fprintf(file, "3 %u %u %u\n", (*tri_vertices_p)[3 * i], (*tri_vertices_p)[3 * i + 1], (*tri_vertices_p)[3 * i + 2]);
    //fclose(file);
    //exit(0);
}

void read_nodes_and_constraints_twoInput(double* coords_A, uint32_t npts_A, uint32_t* tri_idx_A, uint32_t ntri_A,
    double* coords_B, uint32_t npts_B, uint32_t* tri_idx_B, uint32_t ntri_B,
    vertex_t** vertices_p, uint32_t* npts, uint32_t** tri_vertices_p, uint32_t* ntri, CONSTR_GROUP_T** tri_group, bool verbose) {

    // Global numbers of points and triangles.
    *npts = npts_A + npts_B;
    *ntri = ntri_A + ntri_B;

    // Reading points coordinates.
    vertex_t* tmp = (vertex_t*)malloc(*npts * sizeof(vertex_t));
    uint32_t* diff = (uint32_t*)calloc(*npts, sizeof(uint32_t));
    uint32_t* map = (uint32_t*)malloc(*npts * sizeof(uint32_t));

    for (uint32_t i = 0; i < npts_A; i++) {
        tmp[i].coord[0] = coords_A[i * 3];
        tmp[i].coord[1] = coords_A[i * 3 + 1];
        tmp[i].coord[2] = coords_A[i * 3 + 2];
        tmp[i].original_index = i;
    }
    for (uint32_t i = 0; i < npts_B; i++) {
        tmp[i + npts_A].coord[0] = coords_B[i * 3];
        tmp[i + npts_A].coord[1] = coords_B[i * 3 + 1];
        tmp[i + npts_A].coord[2] = coords_B[i * 3 + 2];
        tmp[i + npts_A].original_index = i + npts_A;
    }

    if (*npts > 1) remove_duplicated_points(vertices_p, npts, tmp, map, diff);
    if (verbose) printf("Using %u unique vertices\n", *npts);

    free(tmp);

    // Reading triangle vertices indices.
    *tri_vertices_p = (uint32_t*)malloc(*ntri * 3 * sizeof(uint32_t));
    *tri_group = (uint32_t*)malloc(*ntri * sizeof(uint32_t));

    uint32_t i1, i2, i3, base_ntri_A = ntri_A;
    for (uint32_t ti = 0, j = 0; ti < (*ntri); j++) {

        if (ti < ntri_A) {

            i1 = tri_idx_A[3 * j];
            i2 = tri_idx_A[3 * j + 1];
            i3 = tri_idx_A[3 * j + 2];

            (*tri_vertices_p)[3 * ti] = map[i1] - diff[map[i1]];
            (*tri_vertices_p)[3 * ti + 1] = map[i2] - diff[map[i2]];
            (*tri_vertices_p)[3 * ti + 2] = map[i3] - diff[map[i3]];
            (*tri_group)[ti] = CONSTR_A;

            const double* v1c = (*vertices_p + (*tri_vertices_p)[3 * ti])->coord;
            const double* v2c = (*vertices_p + (*tri_vertices_p)[3 * ti + 1])->coord;
            const double* v3c = (*vertices_p + (*tri_vertices_p)[3 * ti + 2])->coord;
            if (!misAlignment(v1c, v2c, v3c)) { (*ntri)--; ntri_A--; }
            else ti++;

        }
        else {
            if (ti == ntri_A) j = 0;
            i1 = tri_idx_B[3 * j];
            i2 = tri_idx_B[3 * j + 1];
            i3 = tri_idx_B[3 * j + 2];

            i1 += npts_A;
            i2 += npts_A;
            i3 += npts_A;
            (*tri_vertices_p)[3 * ti] = map[i1] - diff[map[i1]];
            (*tri_vertices_p)[3 * ti + 1] = map[i2] - diff[map[i2]];
            (*tri_vertices_p)[3 * ti + 2] = map[i3] - diff[map[i3]];
            (*tri_group)[ti] = CONSTR_B;

            const double* v1c = (*vertices_p + (*tri_vertices_p)[3 * ti])->coord;
            const double* v2c = (*vertices_p + (*tri_vertices_p)[3 * ti + 1])->coord;
            const double* v3c = (*vertices_p + (*tri_vertices_p)[3 * ti + 2])->coord;
            if (!misAlignment(v1c, v2c, v3c)) (*ntri)--;
            else ti++;
        }

    }

    *tri_vertices_p = (uint32_t*)realloc(*tri_vertices_p, *ntri * 3 * sizeof(uint32_t));
    *tri_group = (uint32_t*)realloc(*tri_group, *ntri * sizeof(uint32_t));
    free(map);
    free(diff);

    if (verbose) printf("Using %u non-degenerate constraints\n", *ntri);
}




void logger(FILE* fp, const char* msg, ...)
{
    char fmt[2048], fms[4096];
    va_list ap;
    va_start(ap, msg);
    strcpy(fmt, msg);
    vsprintf(fms, fmt, ap);

    fprintf(fp, fms);

    va_end(ap);
}





//void saveVRML(const char* filename, double* coords_A, uint32_t npts_A, uint32_t* tri_idx_A, uint32_t ntri_A, bool wireframe)
//{
//    FILE* fp = fopen(filename, "w");
//    fprintf(fp, 
//        "#VRML V1.0 ascii\n\n");
//    fprintf(fp, 
//        "Separator {\n"
//        "ShapeHints{\n"
//        "vertexOrdering COUNTERCLOCKWISE creaseAngle 0.0\n"
//        "shapeType SOLID\n"
//        "}\n"
//        "Separator{\n"
//        "Coordinate3 {\n"
//        "point[\n");
//
//    for (uint32_t i = 0; i < npts_A; i++)
//        fprintf(fp, "%f %f %f,\n", coords_A[3 * i], coords_A[3 * i + 1], coords_A[3 * i + 2]);
//    
//    fprintf(fp,
//        "]\n"
//        "}\n"
//        "Material{\n"
//        "diffuseColor 0.7 0.5 0.5\n"
//        "}\n"
//        "IndexedFaceSet{\n"
//        "coordIndex[\n");
//
//    for (uint32_t i = 0; i < ntri_A; i++)
//        fprintf(fp, "%u, %u, %u, -1,\n", tri_idx_A[3 * i], tri_idx_A[3 * i + 1], tri_idx_A[3 * i + 2]);
//
//    fprintf(fp,
//        "]\n"
//        "}\n");
//
//    if (wireframe)
//    {
//
//        fprintf(fp,
//            "Material{\n"
//            "diffuseColor 0.0 0.0 0.0\n"
//            "}\n"
//            "DrawStyle{\n"
//            "lineWidth 2\n"
//            "}\n"
//            "IndexedLineSet{\n"
//            "coordIndex[\n");
//
//        for (uint32_t i = 0; i < ntri_A; i++)
//        {
//            uint32_t i1, i2;
//            i1 = tri_idx_A[3 * i];
//            i2 = tri_idx_A[3 * i + 1];
//            if (i1 < i2) fprintf(fp, "%u, %u, -1,\n", i1, i2);
//            i1 = tri_idx_A[3 * i + 1];
//            i2 = tri_idx_A[3 * i + 2];
//            if (i1 < i2) fprintf(fp, "%u, %u, -1,\n", i1, i2);
//            i1 = tri_idx_A[3 * i + 2];
//            i2 = tri_idx_A[3 * i];
//            if (i1 < i2) fprintf(fp, "%u, %u, -1,\n", i1, i2);
//        }
//
//        fprintf(fp, "]\n}\n");
//    }
//    fprintf(fp, "}\n}\n");
//
//    fclose(fp);
//}









/// <summary>
/// Main function - Create a polyhedral mesh out of the input
/// Input may be made of either one or two models to be combined into a boolean composition
/// </summary>
/// <param name="fileA_name">Name of first model</param>
/// <param name="coords_A">Serialized coordinates of first model vertices</param>
/// <param name="npts_A">Number of first model vertices</param>
/// <param name="tri_idx_A">Serialized indexes of first model triangles</param>
/// <param name="ntri_A">Number of first model triangles</param>
/// <param name="fileB_name">Name of second model</param>
/// <param name="coords_B">Serialized coordinates of second model vertices</param>
/// <param name="npts_B">Number of second model vertices</param>
/// <param name="tri_idx_B">Serialized indexes of second model triangles</param>
/// <param name="ntri_B">Number of second model triangles</param>
/// <param name="bool_opcode">Boolean operation (0 = no op, U = union, D = difference, I = intersection</param>
/// <param name="free_mem">Input models memory is released</param>
/// <param name="verbose">Print useful info during the process</param>
/// <param name="logging">Append info to mesh_generator.log</param>
/// <returns>The resulting BSPcomplex structure</returns>
BSPcomplex* makePolyhedralMesh(
    const char* fileA_name, double* coords_A, uint32_t npts_A, uint32_t* tri_idx_A, uint32_t ntri_A,
    const char* fileB_name, double* coords_B, uint32_t npts_B, uint32_t* tri_idx_B, uint32_t ntri_B,
    char bool_opcode, bool free_mem, bool verbose, bool logging)
{
    //saveVRML("input1.wrl", coords_A, npts_A, tri_idx_A, ntri_A, false);
    //saveVRML("input2.wrl", coords_A, npts_A, tri_idx_A, ntri_A, true);

    bool two_input = (bool_opcode != '0');

    if (verbose)
    {
        if (coords_B == NULL) {
            printf("\nResolve auto-intersections and/or repair.\n\n");
        }
        else {
            printf("\nBoolean operator: ");
            if (bool_opcode == 'U') printf(" union.\n\n");
            else if (bool_opcode == 'I') printf(" intersection.\n\n");
            else if (bool_opcode == 'D') printf(" difference.\n\n");
            else { ip_error("INVALID\n\n"); }
        }
    }

    //--Initialization-----------------

    TetMesh* mesh = new TetMesh;
    constraints_t* constraints = new constraints_t;

    if (!two_input) {
        read_nodes_and_constraints(coords_A, npts_A, tri_idx_A, ntri_A,
            &mesh->vertices,
            &mesh->num_vertices,
            &constraints->tri_vertices,
            &constraints->num_triangles,
            verbose);
        constraints->constr_group = (uint32_t*)calloc(constraints->num_triangles, sizeof(uint32_t));
    }
    else { // two input
        read_nodes_and_constraints_twoInput(coords_A, npts_A, tri_idx_A, ntri_A,
            coords_B, npts_B, tri_idx_B, ntri_B,
            &mesh->vertices,
            &mesh->num_vertices,
            &constraints->tri_vertices,
            &constraints->num_triangles,
            &constraints->constr_group,
            verbose);
    }

    if (mesh->num_vertices < 4) ip_error("Cannot mesh less than 4 vertices.");
    if (constraints->num_triangles < 1) ip_error("No non-degenerate constraints loaded.");

    if (free_mem)
    {
        free(coords_A);
        free(tri_idx_A);
        if (two_input) { free(coords_B); free(tri_idx_B); }
    }
    FILE* logfile;

    if (logging)
    {
        logfile = fopen("mesh_generator.log", "r");
        if (logfile == NULL)
        {
            logfile = fopen("mesh_generator.log", "a");
            logger(logfile, "Filename,Delaunay,Virtual,Mapping,Total Delaunay,Conversion,Subdivision,Face Coloring,In-Out,Total BSP,TOTAL,Mem\n");
        }
        else logfile = freopen("mesh_generator.log", "a", logfile);

        if (two_input) logger(logfile, "%s_%c_%s,", fileA_name, bool_opcode, fileB_name);
        else logger(logfile, "%s,", fileA_name);
        fflush(logfile);
    }

    clock_t time0 = clock();
    clock_t time1 = time0;

    //--Delaunay-Insertion-----------------

    // Setup for following vertex permutation in tetrahedrize
    for (uint32_t i = 0; i < mesh->num_vertices; i++)
        mesh->vertices[i].original_index = i;

    // Create Delaunay tetrahedrization of the vertices
    mesh->tetrahedrize();
    //mesh->saveTET("delaunay.tet");

    // Align constraint vertices after vertex permutation

    if (mesh->vertices[2].original_index != 3)
    {
        for (uint32_t k = 0; k < 3 * constraints->num_triangles; k++)
            constraints->tri_vertices[k] = mesh->vertices[constraints->tri_vertices[k]].original_index;
    }
    else
    {
        for (uint32_t k = 0; k < 3 * constraints->num_triangles; k++)
        {
            uint32_t l = mesh->vertices[3].original_index;
            uint32_t c = constraints->tri_vertices[k];
            if (c == 2) constraints->tri_vertices[k] = l;
            else if (c == 3) constraints->tri_vertices[k] = 2;
            else if (c == l) constraints->tri_vertices[k] = 3;
        }
    }


    clock_t time2 = clock();
    if (verbose) printf("\tDelaunay insertion: %f s\n", (double)(time2 - time1) / CLOCKS_PER_SEC);

    //--Half-Edges-and-Virtual-Constraints----------------------

    half_edge_t* half_edges = (half_edge_t*)calloc(3 * constraints->num_triangles, sizeof(half_edge_t));
    fill_half_edges(constraints, half_edges);

    sort_half_edges(half_edges, 3 * constraints->num_triangles);

    uint32_t nvc = place_virtual_constraints(mesh, constraints, half_edges);
    if (verbose) printf("\t%u virtual constraints added\n", nvc);

    free(half_edges);

    clock_t time3 = clock();
    if (verbose) printf("\tHalf-edges: %f s\n", (double)(time3 - time2) / CLOCKS_PER_SEC);

    //--Map-Tetrahedra-Constraint-Intersections----------------

    // Initialize an array to map the tetrahedra improperly intersecated
    // by the constraints:
    //    the i-th element is a pointer (of tetrahedra index type) used to store
    //    the indices of the constraints that improper intersect the i-th
    //    tetrahedron,
    //    it points to an array (map[i] of lenght num_map[i]) whose elements
    //    are the indices of the constraints which improperly intersect the
    //    i-th tetrahedron.
    uint32_t* num_map = (uint32_t*)calloc(mesh->tet_num, sizeof(uint32_t));
    uint32_t** map = (uint32_t**)calloc(mesh->tet_num, sizeof(uint32_t*));

    // Initalize other 4 maps to memory the tet-faces that are partially or
    // completely overlap with a constraint.
    uint32_t* num_map_f0 = (uint32_t*)calloc(mesh->tet_num, sizeof(uint32_t));
    uint32_t** map_f0 = (uint32_t**)calloc(mesh->tet_num, sizeof(uint32_t*));
    uint32_t* num_map_f1 = (uint32_t*)calloc(mesh->tet_num, sizeof(uint32_t));
    uint32_t** map_f1 = (uint32_t**)calloc(mesh->tet_num, sizeof(uint32_t*));
    uint32_t* num_map_f2 = (uint32_t*)calloc(mesh->tet_num, sizeof(uint32_t));
    uint32_t** map_f2 = (uint32_t**)calloc(mesh->tet_num, sizeof(uint32_t*));
    uint32_t* num_map_f3 = (uint32_t*)calloc(mesh->tet_num, sizeof(uint32_t));
    uint32_t** map_f3 = (uint32_t**)calloc(mesh->tet_num, sizeof(uint32_t*));

    insert_constraints(mesh, constraints, num_map, map,
        num_map_f0, map_f0,
        num_map_f1, map_f1,
        num_map_f2, map_f2,
        num_map_f3, map_f3);

    clock_t time4 = clock();
    if (verbose) printf("\tMap creation: %f s\n", (double)(time4 - time3) / CLOCKS_PER_SEC);

    double DEL_time = (double)(time4 - time0) / CLOCKS_PER_SEC;
    if (verbose) printf("TOTAL Delaunay+map: %f s\n\n", DEL_time);

    initFPU(); // From here on we need indirect predicates

    //-Init BSP with mesh and constraints---------------------------------------
    BSPcomplex* complex_p = new BSPcomplex(mesh, constraints, (const uint32_t**)map, num_map, (const uint32_t**)map_f0, num_map_f0,
        (const uint32_t**)map_f1, num_map_f1, (const uint32_t**)map_f2, num_map_f2, (const uint32_t**)map_f3, num_map_f3);
    BSPcomplex& complex = *complex_p;

    // Free the memory used by map(s) and num_map(s)
    for (uint64_t i = 0; i < mesh->tet_num; i++) {
        if (num_map[i]) free(map[i]);
        if (num_map_f0[i]) free(map_f0[i]);
        if (num_map_f1[i]) free(map_f1[i]);
        if (num_map_f2[i]) free(map_f2[i]);
        if (num_map_f3[i]) free(map_f3[i]);
    }
    free(num_map);
    free(map);
    free(num_map_f0);
    free(map_f0);
    free(num_map_f1);
    free(map_f1);
    free(num_map_f2);
    free(map_f2);
    free(num_map_f3);
    free(map_f3);

    delete mesh;
    delete constraints;

    clock_t time5 = clock();
    if (verbose) printf("\tDelaunay -> Complex %lf s\n", (double)(time5 - time4) / CLOCKS_PER_SEC);
    if (verbose) printf("\tInitial cells: %llu\n", complex.cells.size());

    //-Subdivision----------------------------------------------------------------

  //#define MEM_THRESHOLD   32768

    uint64_t cell_ind = 0;
    while (cell_ind < complex.cells.size())
    {
#ifdef MEM_THRESHOLD
        if ((cell_ind & 0x0000000000000fff) == 0) {
            printf("\r%llu cells created                  ", cell_ind); fflush(stdout);
            if (getPeakMegabytesUsed() > MEM_THRESHOLD) ip_error("Maximum memory reached\n");
        }
#endif
        if (complex.cells[cell_ind].constraints.size() > 0)
            complex.splitCell(cell_ind);
        else  cell_ind++;
    }
    clock_t time6 = clock();
    if (verbose) printf("\tCell subdivision %f s\n", (double)(time6 - time5) / CLOCKS_PER_SEC);
    if (verbose) printf("\tFinal cells: %llu\n", complex.cells.size());


    //for (BSPcell& c : complex.cells) c.place = INTERNAL_A;
    //complex.saveMesh("splitch.tet", '0', true);
    //exit(0);



    //--Decide colour of GREY faces-----------------------------------------------
    for (uint64_t face_ind = 0; face_ind < complex.faces.size(); face_ind++) {
        BSPface& face = complex.faces[face_ind];
        if (face.colour == GREY)   face.colour = complex.blackAB_or_white(face_ind, bool_opcode != '0');
    }

    clock_t time7 = clock();
    if (verbose) printf("\tFind black faces %f s\n", (double)(time7 - time6) / CLOCKS_PER_SEC);

    //-Classification:intrenal/external cells-------------------------------------
    complex.constraintsSurface_complexPartition(bool_opcode != '0');

    clock_t time8 = clock();
    if (verbose) printf("\tInt-ext class. %f s\n", (double)(time8 - time7) / CLOCKS_PER_SEC);


    clock_t time9 = clock();
    double BSP_time = (double)(time9 - time4) / CLOCKS_PER_SEC;
    if (verbose) printf("TOTAL BSP: %f s\n\n", BSP_time);
    if (verbose) printf("TOTAL time: %f s\n\n", BSP_time + DEL_time);
    if (verbose) PrintMemoryInfo();

    if (logging)
    {
        logger(logfile, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
            (double)(time2 - time1) / CLOCKS_PER_SEC,
            (double)(time3 - time2) / CLOCKS_PER_SEC,
            (double)(time4 - time3) / CLOCKS_PER_SEC,
            DEL_time,
            (double)(time5 - time4) / CLOCKS_PER_SEC,
            (double)(time6 - time5) / CLOCKS_PER_SEC,
            (double)(time7 - time6) / CLOCKS_PER_SEC,
            (double)(time8 - time7) / CLOCKS_PER_SEC,
            BSP_time,
            BSP_time + DEL_time
#ifdef _MSC_VER
            , getPeakMegabytesUsed()
#endif
        );
        fclose(logfile);
    }

    //uint32_t npts, ntri, * tri_idx;
    //double* coord;
    //complex.extractSkinTriMesh("input4.wrl", bool_opcode, &coord, &npts, &tri_idx, &ntri);
    //saveVRML("input4.wrl", coord, npts, tri_idx, ntri, false);
    //saveVRML("input5.wrl", coord, npts, tri_idx, ntri, true);
    //exit(0);

    return complex_p;
}

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API