star-cad

Geometric operators for computer-aided design
git clone git://git.meso-star.fr/star-cad.git
Log | Files | Refs | README | LICENSE

commit 843b2f9ec4776950d8033f2617e47267568453f9
parent 6baf1b85f7bfe5571767da5e88069b1b38156e60
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed, 23 Nov 2022 17:18:15 +0100

Add tests

Diffstat:
Mcmake/CMakeLists.txt | 5++++-
Asrc/test_api.c | 252+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_common.h | 1+
Asrc/test_export.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_partition.c | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 435 insertions(+), 1 deletion(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -23,7 +23,7 @@ option(NO_TEST "Disable the test" OFF) ################################################################################ # Check dependencies ################################################################################ -find_package(gmsh 4.9.5 EXACT REQUIRED) +find_package(gmsh 4.9.5 REQUIRED) find_package(RCMake 0.4.1 REQUIRED) find_package(RSys 0.12.1 REQUIRED) @@ -92,6 +92,9 @@ if(NOT NO_TEST) endfunction() new_test(test1) + new_test(test_api) + new_test(test_export) + new_test(test_partition) rcmake_copy_runtime_libraries(test) diff --git a/src/test_api.c b/src/test_api.c @@ -0,0 +1,252 @@ +/* Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "scad.h" +#include "scad_geometry.h" +#include "test_common.h" + +#include <rsys/rsys.h> +#include <rsys/math.h> +#include <rsys/mem_allocator.h> +#include <rsys/logger.h> + +#include <stdlib.h> +#include <stdio.h> + +static void +get_position + (const size_t ivert, double pos[2], void* data) +{ + double* coord = data; + ASSERT(pos && coord); + pos[0] = coord[2*ivert]; + pos[1] = coord[1+2*ivert]; + +} + +int +main(int argc, char* argv[]) +{ + res_T res = RES_OK; + double p1[3] = {0, 0, 0}; + double p2[3] = {0.25, 0.25, 0.8}; + double d1[3] = {1, 1, 1}; + double coord[] = {0, 1.6, 0.5, 0.9, 0.8, 0.6}; + struct scad_geometry* geom1 = NULL; + struct scad_geometry* geom2 = NULL; + struct scad_geometry* geom = NULL; + struct scad_geometry** geom_array = NULL; + struct scad_geometry* geoms[2]; + struct mem_allocator allocator; + struct logger logger; + size_t c; + + (void)argc; (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(logger_init(&allocator, &logger)); + + /* cannot call any API function before a successful call to scad_initialize */ + BAD(scad_finalize()); + BAD(scad_set_options(NULL)); + BAD(scad_synchronize()); + BAD(scad_scene_clear()); + BAD(scad_add_rectangle(NULL, p1, d1, &geom)); + BAD(scad_add_disk(NULL, p1, 1, &geom)); + BAD(scad_add_polygon(NULL, get_position, coord, 0, 3, &geom)); + BAD(scad_add_box(NULL, p1, d1, &geom)); + BAD(scad_add_cylinder(NULL, p1, d1, 2, 1, &geom)); + BAD(scad_add_sphere(NULL, p1, 1, &geom)); + BAD(scad_step_import("test.step", NULL, &geom_array, &c)); + BAD(scad_scene_mesh()); + BAD(scad_run_ui()); + + /* cannot call any API function after a successful call to scad_finalize */ + OK(scad_initialize(&logger, &allocator, 3)); + OK(scad_finalize()); + + BAD(scad_finalize()); + BAD(scad_set_options(NULL)); + BAD(scad_synchronize()); + BAD(scad_scene_clear()); + BAD(scad_add_rectangle(NULL, p1, d1, &geom)); + BAD(scad_add_disk(NULL, p1, 1, &geom)); + BAD(scad_add_polygon(NULL, get_position, coord, 0, 3, &geom)); + BAD(scad_add_box(NULL, p1, d1, &geom)); + BAD(scad_add_cylinder(NULL, p1, d1, 2, 1, &geom)); + BAD(scad_add_sphere(NULL, p1, 1, &geom)); + BAD(scad_step_import("test.step", NULL, &geom_array, &c)); + BAD(scad_scene_mesh()); + BAD(scad_run_ui()); + + BAD(scad_initialize(&logger, &allocator, 4)); + BAD(scad_initialize(&logger, &allocator, -1)); + + OK(scad_initialize(&logger, &allocator, 3)); + OK(scad_add_sphere("sphere 1", p1, .1, &geom1)); + OK(scad_add_sphere(NULL, p2, .2, &geom2)); + geoms[0] = geom1; + geoms[1] = geom2; + + OK(scad_add_sphere(NULL, p1, .1, &geom)); + BAD(scad_geometry_delete(NULL)); + OK(scad_geometry_delete(geom)); + + BAD(scad_geometry_get_count(NULL, &c)); + BAD(scad_geometry_get_count(geom1, NULL)); + OK(scad_geometry_get_count(geom1, &c)); + + BAD(scad_add_rectangle(NULL, NULL, d1, &geom)); + BAD(scad_add_rectangle(NULL, p1, NULL, &geom)); + BAD(scad_add_rectangle(NULL, p1, d1, NULL)); + BAD(scad_add_rectangle("sphere 1", p1, d1, &geom)); /* Name already used */ + OK(scad_add_rectangle(NULL, p1, d1, &geom)); + OK(scad_geometry_delete(geom)); + + BAD(scad_add_disk(NULL, NULL, 1, &geom)); + BAD(scad_add_disk(NULL, p1, 0, &geom)); + BAD(scad_add_disk(NULL, p1, 1, NULL)); + OK(scad_add_disk(NULL, p1, 1, &geom)); + OK(scad_geometry_delete(geom)); + + BAD(scad_add_polygon(NULL, NULL, coord, 0, 3, &geom)); + BAD(scad_add_polygon(NULL, get_position, coord, 0, 2, &geom)); + BAD(scad_add_polygon(NULL, get_position, coord, 0, 2, &geom)); + BAD(scad_add_polygon(NULL, get_position, coord, 0, 3, NULL)); + OK(scad_add_polygon(NULL, get_position, coord, 0, 3, &geom)); + OK(scad_geometry_delete(geom)); + + BAD(scad_add_box(NULL, NULL, d1, &geom)); + BAD(scad_add_box(NULL, p1, NULL, &geom)); + BAD(scad_add_box(NULL, p1, d1, NULL)); + OK(scad_add_box(NULL, p1, d1, &geom)); + OK(scad_geometry_delete(geom)); + + BAD(scad_add_cylinder(NULL, NULL, d1, 2, 1, &geom)); + BAD(scad_add_cylinder(NULL, p1, NULL, 2, 1, &geom)); + BAD(scad_add_cylinder(NULL, p1, d1, 0, 1, &geom)); + BAD(scad_add_cylinder(NULL, p1, d1, 2, -1, &geom)); + BAD(scad_add_cylinder(NULL, p1, d1, 2, 3*PI, &geom)); + BAD(scad_add_cylinder(NULL, p1, d1, 2, 1, NULL)); + OK(scad_add_cylinder(NULL, p1, d1, 2, 1, &geom)); + OK(scad_geometry_delete(geom)); + + BAD(scad_add_sphere(NULL, NULL, 1, &geom)); + BAD(scad_add_sphere(NULL, p1, 0, &geom)); + BAD(scad_add_sphere(NULL, p1, 1, NULL)); + OK(scad_add_sphere(NULL, p1, 1, &geom)); + OK(scad_geometry_delete(geom)); + + /* BAD(scad_fuse_geometries(NULL, NULL, 0, geoms, 2, &geom)); */ + BAD(scad_fuse_geometries(NULL, geoms, 2, NULL, 0, &geom)); + BAD(scad_fuse_geometries(NULL, NULL, 1, &geom2, 1, &geom)); + BAD(scad_fuse_geometries(NULL, &geom1, 1, NULL, 1, &geom)); + BAD(scad_fuse_geometries(NULL, &geom1, 1, &geom2, 1, NULL)); + OK(scad_fuse_geometries(NULL, &geom1, 1, &geom2, 1, &geom)); + OK(scad_geometry_delete(geom)); + + /* BAD(scad_cut_geometries(NULL, NULL, 0, geoms, 2, &geom)); */ + BAD(scad_cut_geometries(NULL, geoms, 2, NULL, 0, &geom)); + BAD(scad_cut_geometries(NULL, NULL, 1, &geom2, 1, &geom)); + BAD(scad_cut_geometries(NULL, &geom1, 1, NULL, 1, &geom)); + BAD(scad_cut_geometries(NULL, &geom1, 1, &geom2, 1, NULL)); + OK(scad_cut_geometries(NULL, &geom1, 1, &geom2, 1, &geom)); + OK(scad_geometry_delete(geom)); + + /* BAD(scad_intersect_geometries(NULL, NULL, 0, geoms, 2, &geom)); */ + BAD(scad_intersect_geometries(NULL, geoms, 2, NULL, 0, &geom)); + BAD(scad_intersect_geometries(NULL, NULL, 1, &geom2, 1, &geom)); + BAD(scad_intersect_geometries(NULL, &geom1, 1, NULL, 1, &geom)); + BAD(scad_intersect_geometries(NULL, &geom1, 1, &geom2, 1, NULL)); + OK(scad_intersect_geometries(NULL, &geom1, 1, &geom2, 1, &geom)); + OK(scad_geometry_delete(geom)); + + /* BAD(scad_geometries_common_boundaries(NULL, NULL, 0, geoms, 2, &geom)); */ + BAD(scad_geometries_common_boundaries(NULL, geoms, 2, NULL, 0, &geom)); + BAD(scad_geometries_common_boundaries(NULL, NULL, 1, &geom2, 1, &geom)); + BAD(scad_geometries_common_boundaries(NULL, &geom1, 1, NULL, 1, &geom)); + BAD(scad_geometries_common_boundaries(NULL, &geom1, 1, &geom2, 1, NULL)); + OK(scad_geometries_common_boundaries(NULL, &geom1, 1, &geom2, 1, &geom)); + OK(scad_geometry_delete(geom)); + + BAD(scad_geometries_partition(NULL, NULL, 2, 1, geoms)); + BAD(scad_geometries_partition(NULL, geoms, 0, 1, geoms)); + BAD(scad_geometries_partition(NULL, geoms, 2, 1, NULL)); + OK(scad_geometries_partition(NULL, geoms, 2, 1, geoms)); + OK(scad_geometry_delete(geom)); + + BAD(scad_geometry_boundary(NULL, NULL, 0, &geom)); + BAD(scad_geometry_boundary(NULL, &geom1, 1, NULL)); + OK(scad_geometry_boundary(NULL, &geom1, 1, &geom)); + OK(scad_geometry_delete(geom)); + + BAD(scad_geometry_copy(NULL, NULL, &geom)); + BAD(scad_geometry_copy(geom1, NULL, NULL)); + BAD(scad_geometry_copy(geom1, "sphere 1", NULL)); /* Name already in use */ + OK(scad_geometry_copy(geom1, "Sphere 1", &geom)); + OK(scad_geometry_delete(geom)); + + BAD(scad_geometry_rename(NULL, NULL)); + BAD(scad_geometry_rename(geom2, "sphere 1")); /* Name already in use */ + OK(scad_geometry_rename(geom2, NULL)); + + BAD(scad_geometry_translate(NULL, d1)); + BAD(scad_geometry_translate(geom1, NULL)); + OK(scad_geometry_translate(geom1, d1)); + + BAD(scad_geometry_rotate(NULL, p1, d1, 1)); + BAD(scad_geometry_rotate(geom1, NULL, d1, 1)); + BAD(scad_geometry_rotate(geom1, p1, NULL, 1)); + OK(scad_geometry_rotate(geom1, p1, d1, 1)); + + BAD(scad_geometry_extrude(NULL, NULL, d1, &geom)); + BAD(scad_geometry_extrude(geom1, NULL, NULL, &geom)); + BAD(scad_geometry_extrude(geom1, NULL, d1, NULL)); +#if 0 + /* Crash!? */ + OK(scad_geometry_extrude(geom1, NULL, d1, &geom)); + OK(scad_geometry_delete(geom)); +#endif + + BAD(scad_scene_write(NULL)); + ERR(scad_scene_write("")); + OK(scad_scene_write("/tmp/test.step")); + + BAD(scad_step_import(NULL, "step", &geom_array, &c)); + BAD(scad_step_import("/tmp/test.step", NULL, &geom_array, &c)); + BAD(scad_step_import("/tmp/test.step", "step", NULL, &c)); + BAD(scad_step_import("/tmp/test.step", "step", &geom_array, NULL)); + ERR(scad_step_import("dont_exist.step", "step", &geom_array, &c)); + OK(scad_step_import("/tmp/test.step", "step", &geom_array, &c)); + + BAD(scad_stl_export(NULL, NULL, 0)); + BAD(scad_stl_export(geom2, NULL, 0)); /* geom2 has no name */ + OK(scad_stl_export(geom2, "/tmp/test", 0)); + OK(scad_stl_export(geom1, NULL, 0)); + + BAD(scad_stl_export_split(NULL, NULL, 0)); + BAD(scad_stl_export_split(geom2, NULL, 0)); /* geom2 has no name */ + OK(scad_stl_export_split(geom2, "/tmp/test", 0)); + OK(scad_stl_export_split(geom1, NULL, 0)); + + logger_release(&logger); + OK(scad_finalize()); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + + return (res == RES_OK) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/test_common.h b/src/test_common.h @@ -24,6 +24,7 @@ #define OK(Expr) CHK(RES_OK == (Expr)) #define BAD(Expr) CHK(RES_BAD_ARG == (Expr)) +#define ERR(Expr) CHK(RES_OK != (Expr)) static void check_memory_allocator(struct mem_allocator* allocator) { diff --git a/src/test_export.c b/src/test_export.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "scad.h" +#include "scad_geometry.h" +#include "test_common.h" + +#include <rsys/rsys.h> +#include <rsys/math.h> +#include <rsys/mem_allocator.h> +#include <rsys/logger.h> + +#include <stdlib.h> + +int +main(int argc, char* argv[]) +{ + res_T res = RES_OK; + double p1[3] = {0, 0, 0}; + double p2[3] = {4.25, 4.25, 4.8}; + double d1[3] = {1, 1, 1}; + struct scad_geometry* rectangle = NULL; + struct scad_geometry* cube = NULL; + struct scad_geometry* cube2 = NULL; + struct scad_geometry* geoms[2]; + struct mem_allocator allocator; + struct logger logger; + + (void)argc; (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(logger_init(&allocator, &logger)); + logger_release(&logger); + OK(scad_initialize(&logger, &allocator, 3)); + + OK(scad_add_rectangle("rectangle", p1, d1, &rectangle)); + OK(scad_add_box("cube", p1, d1, &cube)); + OK(scad_add_box(NULL, p2, d1, geoms+1)); + + geoms[0] = cube; + OK(scad_fuse_geometries("cube2", geoms, 1, geoms+1, 1, &cube2)); + + OK(scad_scene_mesh()); + + OK(scad_stl_export(rectangle, NULL, 0)); + OK(scad_stl_export(rectangle, "bin_rectangle", 1)); + + OK(scad_stl_export(cube, NULL, 0)); + OK(scad_stl_export(cube, "bin_cube", 1)); + + OK(scad_stl_export(cube2, NULL, 0)); + OK(scad_stl_export(cube2, "bin_cube2", 1)); + + OK(scad_finalize()); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + + return (res == RES_OK) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/test_partition.c b/src/test_partition.c @@ -0,0 +1,105 @@ +/* Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#define _POSIX_C_SOURCE 200112L + +#include "scad.h" +#include "scad_geometry.h" +#include "test_common.h" + +#include <rsys/rsys.h> +#include <rsys/math.h> +#include <rsys/mem_allocator.h> +#include <rsys/logger.h> +#include <rsys/double3.h> + +#include <stdlib.h> +#include <stdio.h> + +static res_T +two_geoms + (double x, + const int allow_overlapping, + struct mem_allocator* allocator, + struct logger* logger) +{ + double p0[3] = {0, 0, 2}; + double d0[3] = {1, 1, 1}; + double p1[3] = {0, 0, 0}; + double d1[3] = {1, 1, 1}; + double p2[3]; + double d2[3] = {0.5, 0.5, 0.5}; + struct scad_geometry* geoms[2]; + struct scad_geometry* tmp[2]; + struct scad_geometry* pgeoms[2]; + char name[64]; + res_T res; + + OK(scad_initialize(logger, allocator, 3)); + + /* set position for cube #2 */ + d3(p2, x, 0.25, 0.25); + + OK(scad_add_box("cube0", p0, d0, tmp)); + OK(scad_add_box("cube1", p1, d1, tmp+1)); + + OK(scad_fuse_geometries("cubes", tmp, 1, tmp+1, 1, geoms)); + OK(scad_add_box("cube2", p2, d2, geoms+1)); + + res = scad_geometries_partition(NULL, geoms, 2, allow_overlapping, pgeoms); + if(res != RES_OK) goto end; + + OK(scad_scene_mesh()); + + snprintf(name, sizeof(name), "part_%g_1", x); + OK(scad_stl_export(pgeoms[0], name, 0)); + snprintf(name, sizeof(name), "part_%g_2", x); + OK(scad_stl_export(pgeoms[1], name, 1)); + +end: + OK(scad_finalize()); + return res; +} + +int +main(int argc, char* argv[]) +{ + struct mem_allocator allocator; + struct logger logger; + res_T res = RES_OK; + + (void)argc; (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(logger_init(&allocator, &logger)); + + /* First with distant geometries */ + OK(two_geoms(1.1, 0, &allocator, &logger)); + + /* First with contacting geometries */ + OK(two_geoms(1, 0, &allocator, &logger)); + + /* First with overlapping geometries */ + BAD(two_geoms(0.9, 0, &allocator, &logger)); + OK(two_geoms(0.9, 1, &allocator, &logger)); + + logger_release(&logger); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + + return (res == RES_OK) ? EXIT_SUCCESS : EXIT_FAILURE; +}