star-enclosures-2d

Extract enclosures from 2D geometry
git clone git://git.meso-star.fr/star-enclosures-2d.git
Log | Files | Refs | README | LICENSE

commit a3a20d5ec56d8fd6bb490ba4d06bdce9eb6bc2e9
parent 5d34498c3e45d1bb7b7477581f8b784c20311577
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri,  3 Jul 2020 15:58:33 +0200

Merge branch 'feature_no_add' into develop

Diffstat:
MREADME.md | 17++++++++++++-----
Mcmake/CMakeLists.txt | 81++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Msrc/senc2d.h | 331+++++++++++++++++++++++++------------------------------------------------------
Msrc/senc2d_descriptor.c | 320++++++++++++++++++-------------------------------------------------------------
Dsrc/senc2d_descriptor_c.h | 109-------------------------------------------------------------------------------
Msrc/senc2d_device.c | 14+++++++-------
Msrc/senc2d_enclosure.c | 72++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/senc2d_enclosure_c.h | 9+++++----
Msrc/senc2d_enclosure_data.h | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/senc2d_internal_types.h | 100++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Dsrc/senc2d_s2d_wrapper.h | 80-------------------------------------------------------------------------------
Asrc/senc2d_sXd_helper.h | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/senc2d_scene.c | 393+++++++++++++++++++++++++++----------------------------------------------------
Msrc/senc2d_scene_analyze.c | 448+++++++++++++++++++++++++++++++++++++------------------------------------------
Dsrc/senc2d_scene_analyze.c.save | 1254-------------------------------------------------------------------------------
Msrc/senc2d_scene_analyze_c.h | 36+++++++++++++-----------------------
Msrc/senc2d_scene_c.h | 190+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Asrc/senc2d_side_range.h | 44++++++++++++++++++++++++++++++++++++++++++++
Asrc/sencX2d.h | 44++++++++++++++++++++++++++++++++++++++++++++
Asrc/sencX2d_undefs.h | 33+++++++++++++++++++++++++++++++++
Dsrc/test_senc2d_add_n_merge.c | 204-------------------------------------------------------------------------------
Dsrc/test_senc2d_descriptor.c | 254-------------------------------------------------------------------------------
Msrc/test_senc2d_device.c | 46+++++++++++++++++++++++-----------------------
Msrc/test_senc2d_enclosure.c | 272+++++++++++++++++++++++++++++++++----------------------------------------------
Msrc/test_senc2d_inconsistant_square.c | 48++++++++++++++++++++----------------------------
Msrc/test_senc2d_many_enclosures.c | 132+++++++++++++++++++++++++------------------------------------------------------
Msrc/test_senc2d_many_segments.c | 119+++++++++++++++++++++++++++----------------------------------------------------
Msrc/test_senc2d_sample_enclosure.c | 67++++++++++++++++++++++++-------------------------------------------
Msrc/test_senc2d_scene.c | 459++++++++++++++++++++++++++++++++++++++++---------------------------------------
Asrc/test_senc2d_some_enclosures.c | 3173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc2d_some_segments.c | 3259+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_senc2d_square_behind_square.c | 223++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/test_senc2d_square_in_square.c | 238+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/test_senc2d_square_on_square.c | 191+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Dsrc/test_senc2d_undefined_medium.c | 279-------------------------------------------------------------------------------
Dsrc/test_senc2d_undefined_medium_attr.c | 376-------------------------------------------------------------------------------
Asrc/test_senc2d_unspecified_medium.c | 267+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_senc2d_utils.h | 148+++++++++++++++++++++++++++++++++++--------------------------------------------
Asrc/test_senc2d_utils2.h | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
39 files changed, 8896 insertions(+), 4704 deletions(-)

diff --git a/README.md b/README.md @@ -1,7 +1,7 @@ -StarEnclosures 2D -================= +Star-enclosures-2d +================== -The purpose of Star-enclosures-2D is to extract enclosures from raw +The purpose of Star-enclosures-2d is to extract enclosures from raw geometry. An enclosure is a set of segments enclosing a given area. The enclosure notion extends to open enclosures for which there is no inside or outside. For every detected enclosure, the library provides the set @@ -19,7 +19,7 @@ segments can be set. How to build ------------ -StarEnclosures 2D relies on the [CMake](http://www.cmake.org) and the +Star-enclosures-2d relies on the [CMake](http://www.cmake.org) and the [RCMake](https://gitlab.com/vaplv/rcmake/) package to build. It also depends on the [RSys](https://gitlab.com/vaplv/rsys/) and [Star-2D](https://gitlab.com/meso-star/star-2d/) libraries. Additionaly, @@ -32,6 +32,13 @@ all the aforementioned prerequisites. Finally generate the project from the `cmake/CMakeLists.txt` file by appending to the `CMAKE_PREFIX_PATH` variable the install directories of its dependencies. +Known Bugs +---------- + +In some rare circumstances, raytracing accuracy problems can lead to +incorrect connex components pairing. This bug has already been fixed +in star-enclosures-3d but is still present in star-enclosures-2d. + Release notes ------------- @@ -87,7 +94,7 @@ Release notes License ------- -StarEnclosures 2D is Copyright (C) |Méso|Star> 2018-2020 +Star-enclosures-2d is Copyright (C) |Méso|Star> 2018-2020 (<a href="mailto:contact@meso-star.com" class="email">contact@meso-star.com</a>). It is free software released under the GPLv3+ license. You are welcome to redistribute it under certain conditions; refer to the COPYING files diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -13,13 +13,19 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -cmake_minimum_required(VERSION 3.0) -project(Star-Enclosures2D C) +cmake_minimum_required(VERSION 3.1) +project(star-enclosures-2d C) enable_testing() +include(CMakeDependentOption) + set(SENC2D_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) option(NO_TEST "Do not build tests" OFF) +cmake_dependent_option(HUGE_ADDITIONAL_TESTS + "Build additional tests that involve millions of segments" OFF + "NOT NO_TEST" OFF) + ################################################################################ # Check dependencies ################################################################################ @@ -29,7 +35,7 @@ find_package(RSys 0.8.1 REQUIRED) find_package(OpenMP 2.0 REQUIRED) if(NOT NO_TEST) -find_package(StarSP 0.7 REQUIRED) + find_package(StarSP 0.7 REQUIRED) endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) @@ -37,9 +43,20 @@ include(rcmake) include(rcmake_runtime) if(NO_TEST) -rcmake_append_runtime_dirs(_runtime_dirs RSys Star2D) + include_directories( + ${RSys_INCLUDE_DIR} + ${Star2D_INCLUDE_DIR}) + + rcmake_append_runtime_dirs(_runtime_dirs RSys Star2D) else() -rcmake_append_runtime_dirs(_runtime_dirs RSys StarSP Star2D) + include_directories( + ${RSys_INCLUDE_DIR} + ${Star2D_INCLUDE_DIR} + ${StarSP_INCLUDE_DIR}) + +if(NOT NO_TEST) + rcmake_append_runtime_dirs(_runtime_dirs RSys StarSP Star2D) + endif() endif() ################################################################################ @@ -59,16 +76,18 @@ set(SENC2D_FILES_SRC set(SENC2D_FILES_INC_API senc2d.h - senc2d_s2d_wrapper.h) + senc2d_sXd_helper.h + sencX2d.h + sencX2d_undefs.h) set(SENC2D_FILES_INC - senc2d_descriptor_c.h senc2d_device_c.h senc2d_enclosure_c.h senc2d_enclosure_data.h senc2d_internal_types.h senc2d_scene_c.h - senc2d_scene_analyze_c.h) + senc2d_scene_analyze_c.h + senc2d_side_range.h) set(SENC2D_FILES_DOC COPYING README.md) @@ -78,13 +97,19 @@ rcmake_prepend_path(SENC2D_FILES_INC ${SENC2D_SOURCE_DIR}) rcmake_prepend_path(SENC2D_FILES_INC_API ${SENC2D_SOURCE_DIR}) rcmake_prepend_path(SENC2D_FILES_DOC ${PROJECT_SOURCE_DIR}/../) +if(CMAKE_COMPILER_IS_GNUCC) + set(MATH_LIB m) +endif() + add_library(senc2d SHARED ${SENC2D_FILES_SRC} ${SENC2D_FILES_INC} ${SENC2D_FILES_INC_API}) -target_link_libraries(senc2d RSys Star2D) +target_link_libraries(senc2d RSys Star2D ${MATH_LIB}) set_target_properties(senc2d PROPERTIES +# C99 needed in case of printf %zu used +# C_STANDARD 99 DEFINE_SYMBOL SENC2D_SHARED_BUILD VERSION ${VERSION} COMPILE_FLAGS ${OpenMP_C_FLAGS} @@ -106,6 +131,10 @@ if(NOT NO_TEST) add_executable(${_name} ${SENC2D_SOURCE_DIR}/test_senc2d_utils.h ${SENC2D_SOURCE_DIR}/${_name}.c) + foreach(other ${ARGN}) + target_sources(${_name} + PUBLIC ${STAR_GEOM_SOURCE_DIR}/${other}) + endforeach() target_link_libraries(${_name} RSys senc2d) endfunction() @@ -115,27 +144,37 @@ if(NOT NO_TEST) endfunction() function(new_test _name) - build_test(${_name}) + build_test(${_name} ${ARGN}) register_test(${_name} ${_name}) endfunction() - new_test(test_senc2d_add_n_merge) - new_test(test_senc2d_descriptor) + new_test(test_senc2d_square_behind_square) + new_test(test_senc2d_square_in_square) + new_test(test_senc2d_square_on_square) new_test(test_senc2d_device) new_test(test_senc2d_enclosure) new_test(test_senc2d_inconsistant_square) - new_test(test_senc2d_many_enclosures) - new_test(test_senc2d_many_segments) new_test(test_senc2d_sample_enclosure) new_test(test_senc2d_scene) - new_test(test_senc2d_square_behind_square) - new_test(test_senc2d_square_in_square) - new_test(test_senc2d_square_on_square) - new_test(test_senc2d_undefined_medium) - new_test(test_senc2d_undefined_medium_attr) + new_test(test_senc2d_some_enclosures) + new_test(test_senc2d_some_segments) + new_test(test_senc2d_unspecified_medium) - target_link_libraries(test_senc2d_sample_enclosure StarSP) + build_test(test_senc2d_many_enclosures) + build_test(test_senc2d_many_segments) + + target_link_libraries(test_senc2d_enclosure Star2D) + target_link_libraries(test_senc2d_sample_enclosure StarSP Star2D) + + rcmake_copy_runtime_libraries(test_senc2d_many_enclosures test_senc2d_utils2.h) + rcmake_copy_runtime_libraries(test_senc2d_many_segments test_senc2d_utils2.h) + rcmake_copy_runtime_libraries(test_senc2d_sample_enclosure) + + if(HUGE_ADDITIONAL_TESTS) + add_test(test_senc2d_many_enclosures test_senc2d_many_enclosures) + add_test(test_senc2d_many_segments test_senc2d_many_segments) + endif() endif() ################################################################################ @@ -146,4 +185,4 @@ install(TARGETS senc2d LIBRARY DESTINATION lib RUNTIME DESTINATION bin) install(FILES ${SENC2D_FILES_INC_API} DESTINATION include/star) -install(FILES ${SENC2D_FILES_DOC} DESTINATION share/doc/star-enc2d) +install(FILES ${SENC2D_FILES_DOC} DESTINATION share/doc/star-enclosures-2d) diff --git a/src/senc2d.h b/src/senc2d.h @@ -29,7 +29,7 @@ #define SENC2D_API extern IMPORT_SYM #endif -/* Helper macro that asserts if the invocation of the StarEnc2D function `Func' +/* Helper macro that asserts if the invocation of the StarEnc function `Func' * returns an error. One should use this macro on StarEnc function calls for * which no explicit error checking is performed. */ #ifndef NDEBUG @@ -42,51 +42,56 @@ * as CPU cores */ #define SENC2D_NTHREADS_DEFAULT (~0u) -/* A constant to specify an undefined medium */ -#define SENC2D_UNDEFINED_MEDIUM UINT_MAX +/* A constant to denote an unspecified medium */ +#define SENC2D_UNSPECIFIED_MEDIUM UINT_MAX /* Forward declaration of external opaque data types */ struct logger; struct mem_allocator; -/* Forward declaration of StarEnclosures2D opaque data types. These data types - * are ref counted. Once created with the appropriated `senc2d_<TYPE>_create' - * function, the caller implicitly owns the created data, i.e. its reference - * counter is set to 1. The senc2d_<TYPE>_ref_<get|put> functions get or release - * a reference on the data, i.e. they increment or decrement the reference - * counter, respectively. When this counter reaches 0, the object is silently - * destroyed and cannot be used anymore. */ -struct senc2d_descriptor; +/* Forward declaration of star-enclosures-2d opaque data types. These data + * types are ref counted. Once created with the appropriated + * `senc2d_<TYPE>_create' function, the caller implicitly owns the created + * data, i.e. its reference counter is set to 1. + * The senc2d_<TYPE>_ref_<get|put> functions get or release a reference on the + * data, i.e. they increment or decrement the reference counter, respectively. + * When this counter reaches 0, the object is silently destroyed and cannot be + * used anymore. */ struct senc2d_device; struct senc2d_scene; struct senc2d_enclosure; +/****************************************************************************** + * The dimension of the geometry used in the library. + *****************************************************************************/ +#define SENC2D_GEOMETRY_DIMENSION 2 + /* A type to discriminate segment sides */ enum senc2d_side { SENC2D_FRONT, SENC2D_BACK }; -/* Enclosure2D header type */ +/* Enclosure header type */ struct senc2d_enclosure_header { /* The ID of the enclosure; 0, 1, ... */ unsigned enclosure_id; /* Number of segments; a segment can be accounted for twice, once by side */ - unsigned segment_count; + unsigned primitives_count; /* Number of segments; a segment cannot be accounted for twice */ - unsigned unique_segment_count; + unsigned unique_primitives_count; /* Number of vertices */ unsigned vertices_count; /* The number of media inside the enclosure, - * SENC2D_UNDEFINED_MEDIUM included */ + * SENC2D_UNSPECIFIED_MEDIUM included */ unsigned enclosed_media_count; - /* Is the enclosure infinite? + /* Is the enclosure open/infinite? * Only the outermost enclosure is infinite. */ - char is_infinite; + int is_infinite; }; -/* We consider the geometrical normal Ng to a segment V0 V1 - * that verifies "(V0, V0V1, Ng) is a direct system". +/* We consider the geometrical normal Ng to a segment V0 V1 that verifies + * "(V0, V0V1, Ng) is a direct system" (right-handed system). * * The user can set the convention used to determine which side of * a segment is to be considered front/back by using the flags : @@ -98,7 +103,8 @@ struct senc2d_enclosure_header { * (for a closed enclosure Ng points toward the inside or toward the outside) * by using the flags : * SENC2D_CONVENTION_NORMAL_INSIDE => Ng points toward the enclosure, - * SENC2D_CONVENTION_NORMAL_OUTSIDE => Ng points to the opposite of the enclosure. + * SENC2D_CONVENTION_NORMAL_OUTSIDE => Ng points toward the opposite of the + * enclosure. * * Note that normals in output data can be opposite to normals in input data * (vertices are then given in reverse order). @@ -112,7 +118,7 @@ enum senc2d_convention { * Convention regarding FRONT/BACK sides in input data */ - /* Geometrical normals point toward the front side */ + /* Geometrical normals point toward the front side */ SENC2D_CONVENTION_NORMAL_FRONT = BIT(0), /* Geometrical normals point toward the back side */ SENC2D_CONVENTION_NORMAL_BACK = BIT(1), @@ -121,20 +127,20 @@ enum senc2d_convention { * Convention regarding geometrical normals in output data */ - /* Geometrical normals point toward the enclosure */ - SENC2D_CONVENTION_NORMAL_INSIDE = BIT(2), - /* Geometrical normals point to the opposite of the enclosure */ - SENC2D_CONVENTION_NORMAL_OUTSIDE = BIT(3) + /* Geometrical normals point toward the enclosure */ + SENC2D_CONVENTION_NORMAL_INSIDE = BIT(2), + /* Geometrical normals point to the opposite of the enclosure */ + SENC2D_CONVENTION_NORMAL_OUTSIDE = BIT(3) }; BEGIN_DECLS -/******************************************************************************* - * StarEnclosures2D device. It is an handle toward the StarEnc2d library. +/****************************************************************************** + * star-enclosures-2d device. It is an handle toward the StarEnc library. * It manages the lib resources. * If provided, the allocator has to be suitable for parallel high frequency * allocations. As a consequence, a rsys proxy allocator should be avoided. - ******************************************************************************/ + *****************************************************************************/ SENC2D_API res_T senc2d_device_create (struct logger* logger, /* May be NULL <=> use default logger */ @@ -151,87 +157,38 @@ SENC2D_API res_T senc2d_device_ref_put (struct senc2d_device* device); -/******************************************************************************* - * StarEnclosures2D scene. A scene is a collection of segments. Each segment is - * defined with a medium on each side. - ******************************************************************************/ -/* Creates an empty scene */ +/****************************************************************************** + * star-enclosures-2d scene. A scene is a collection of segments. Each segment + * is defined with a medium on each side. + *****************************************************************************/ +/* Creates a scene from some vertices and segments. + * Neither vertices nor segments can include duplicates. + * Segments cannot be degenerated. */ SENC2D_API res_T senc2d_scene_create (struct senc2d_device* device, const int convention, - struct senc2d_scene** scene); - -/* Reserve memory according to anticipated scene size. */ -SENC2D_API res_T -senc2d_scene_reserve - (struct senc2d_scene* scene, - const unsigned vertices_count, - const unsigned segments_count, - const unsigned media_count); - -/* Add a new set of vertices and segments to the scene. - * Vertices can be duplicates and are silently deduplicated on the fly. - * Segments can be duplicates as long as media are compatible on both sides. - * Valid segment duplicates are silently deduplicated, invalid duplicates - * trigger an error (add_geometry returns RES_BAD_ARG). - * The special value SENC2D_UNDEFINED_MEDIUM denotes an undefined medium. - * It can be used to define the 2 sides of a segment at different times. - * Media on duplicate segments are consider compatible if: - * - the merge_segment callback is provided and returns RES_OK, - * - or media are identical or SENC2D_UNDEFINED_MEDIUM. - * When deduplicating segments, the first occurence remains (with its - * original index in user world, regardless of deduplication); the only - * situation where deduplication changes a previously recorded media is from - * SENC2D_UNDEFINED_MEDIUM to any defined medium. - * The add_segment and merge_segment callbacks can be used for attribute - * management (including segment IDs) and to record media incompatibilities for - * a subsequent report; they allow the client app to store its own data. - * By returning an error, they can also stop the add_geometry call. */ -SENC2D_API res_T -senc2d_scene_add_geometry - (struct senc2d_scene* scene, - /* Number of added segments */ + /* Number of segments */ const unsigned segments_count, - /* User function that provides vertices ids for added segments */ - void(*indices)(const unsigned iseg, unsigned ids[2], void* context), - /* User function that provides media ids for added segments */ - void(*media) /* Can be NULL <=> SENC2D_UNDEFINED_MEDIUM medium used */ + /* User function that provides vertices ids for segments */ + void(*get_indices)( + const unsigned iseg, + unsigned ids[SENC2D_GEOMETRY_DIMENSION], + void* context), + /* User function that provides media ids for segments */ + void(*get_media) /* Can be NULL <=> SENC2D_UNSPECIFIED_MEDIUM medium used */ (const unsigned iseg, unsigned med[2], void* context), - /* Number of added vertices */ + /* Number of vertices */ const unsigned vertices_count, - /* User function that provides coordinates for added vertices */ - void(*position)(const unsigned ivert, double pos[2], void* context), - /* Called for each new segment so that the client app can manage its own - * segment data/properties/attributes. - * If return is not RES_OK, add_geometry stops immediately and returns - * whatever value add_segment returned. */ - res_T(*add_segment) /* Can be NULL */ - (const unsigned global_id, const unsigned iseg, void* context), - /* Called if the iseg_th segment of the current add_geometry is equal to - * the global_id_th global segment so that the client app can try to merge - * its own segment data or record a possible media conflict. - * The reversed_segment arg indicates if the segment vertices' order is the - * same it was when the segment was first added. - * segment_media and merge_media contain the involved media. - * If those media are incompatible and merge_segment returns RES_OK the - * process will continue with the next segment and possibly end in success. - * If return is not RES_OK, add_geometry stops immediately and returns - * whatever value merge_segment returned. - * If merge_segment is NULL, a strict media compatibility is required for - * add_geometry to success: add_geometry would stop and return RES_BAD_ARG - * on the first occurence of duplicate segment with incompatible media. */ - res_T(*merge_segment) /* Can be NULL */ - (const unsigned global_id, const unsigned iseg, const int reversed_segment, - const unsigned segment_media[2], const unsigned merge_media[2], - void* context), - void* context); - -/* Returns a descriptor of the scene that holds the analysis' result. */ -SENC2D_API res_T -senc2d_scene_analyze - (struct senc2d_scene* scene, - struct senc2d_descriptor** descriptor); + /* User function that provides coordinates for vertices */ + void(*get_position)( + const unsigned ivert, + double pos[SENC2D_GEOMETRY_DIMENSION], + void* context), + /* Context provided to user callbacks; can be NULL */ + void* context, + /* The created scene */ + struct senc2d_scene** scene); /* Returns the convention flags in use with the scene. */ SENC2D_API res_T @@ -245,33 +202,16 @@ senc2d_scene_get_segments_count (const struct senc2d_scene* scene, unsigned* count); -/* Returns the number of unique segments in the scene (remaining - * segments after deduplication). */ -SENC2D_API res_T -senc2d_scene_get_unique_segments_count - (const struct senc2d_scene* scene, - unsigned* count); - -/* Returns the number of unique sides with SENC2D_UNDEFINED_MEDIUM medium. */ +/* Returns the iseg_th segment vertices' indices. */ SENC2D_API res_T -senc2d_scene_get_unique_sides_without_medium_count - (const struct senc2d_scene* scene, - unsigned* count); - -/* Returns the iseg_th unique segment; the returned indices are - * unique vertex indices. - * Can be called anytime, before or after a call to analyze. */ -SENC2D_API res_T -senc2d_scene_get_unique_segment +senc2d_scene_get_segment (const struct senc2d_scene* scene, const unsigned iseg, - unsigned indices[2]); + unsigned indices[SENC2D_GEOMETRY_DIMENSION]); -/* Returns the iseg_th unique segment; the returned indices are - * unique vertex indices. - * Can be called anytime, before or after a call to analyze. */ +/* Returns the media for the iseg_th segment. */ SENC2D_API res_T -senc2d_scene_get_unique_segment_media +senc2d_scene_get_segment_media (const struct senc2d_scene* scene, const unsigned iseg, unsigned media[2]); @@ -282,159 +222,98 @@ senc2d_scene_get_vertices_count (const struct senc2d_scene* scene, unsigned* count); -/* Returns the number of unique vertices in the scene (remaining - * vertices after deduplication). */ -SENC2D_API res_T -senc2d_scene_get_unique_vertices_count - (const struct senc2d_scene* scene, - unsigned* count); - -/* Returns the coordinates of the ivert_th unique vertex. - * Can be called anytime, before or after a call to analyze. */ +/* Returns the coordinates of the ivert_th vertex. */ SENC2D_API res_T -senc2d_scene_get_unique_vertex +senc2d_scene_get_vertex (const struct senc2d_scene* scene, const unsigned ivert, - double coord[2]); - -SENC2D_API res_T -senc2d_scene_ref_get - (struct senc2d_scene* scene); - -SENC2D_API res_T -senc2d_scene_ref_put - (struct senc2d_scene* scene); + double coord[SENC2D_GEOMETRY_DIMENSION]); -/******************************************************************************* - * StarEnclosures2D descriptor. It is an handle toward an analyze result. - ******************************************************************************/ /* Returns the greater medium id found in added geometry. In API calls using a * medium, any value in the [0 max_medium_id[ range is valid. However there can * be unused ids (no geometry refered to this medium id). */ SENC2D_API res_T -senc2d_descriptor_get_max_medium - (const struct senc2d_descriptor* descriptor, +senc2d_scene_get_max_medium + (const struct senc2d_scene* scene, unsigned* max_medium_id); /* Returns the number of enclosures. */ SENC2D_API res_T -senc2d_descriptor_get_enclosure_count - (const struct senc2d_descriptor* descriptor, +senc2d_scene_get_enclosure_count + (const struct senc2d_scene* scene, unsigned* count); /* Returns the number of enclosures that have some geometry refering to the - * imed_th medium. */ + * imed_th medium or SENC2D_UNSPECIFIED_MEDIUM. */ SENC2D_API res_T -senc2d_descriptor_get_enclosure_count_by_medium - (const struct senc2d_descriptor* descriptor, +senc2d_scene_get_enclosure_count_by_medium + (const struct senc2d_scene* scene, const unsigned imed, unsigned* count); /* Returns the idx_th enclosure. */ SENC2D_API res_T -senc2d_descriptor_get_enclosure - (struct senc2d_descriptor* descriptor, +senc2d_scene_get_enclosure + (struct senc2d_scene* scene, const unsigned idx, struct senc2d_enclosure** enclosure); -/* Returns the idx_th enclosure using the imed_th medium. */ +/* Returns the idx_th enclosure using the imed_th medium or + * SENC2D_UNSPECIFIED_MEDIUM. */ SENC2D_API res_T -senc2d_descriptor_get_enclosure_by_medium - (struct senc2d_descriptor* descriptor, +senc2d_scene_get_enclosure_by_medium + (struct senc2d_scene* scene, const unsigned imed, const unsigned idx, struct senc2d_enclosure** enclosure); -/* Returns the number of unique segments (no duplicates here) in the whole - * geometry. */ -SENC2D_API res_T -senc2d_descriptor_get_global_segments_count - (const struct senc2d_descriptor* descriptor, - unsigned* count); - -/* Returns the number of unique vertices (no duplicates here) in the whole - * geometry. */ +/* Returns the enclosures the iseg_th segment front and back sides are member + * of. */ SENC2D_API res_T -senc2d_descriptor_get_global_vertices_count - (const struct senc2d_descriptor* descriptor, - unsigned* count); - -/* Returns the iseg_th global unique segment; the returned indices are global - * unique vertex indices. */ -SENC2D_API res_T -senc2d_descriptor_get_global_segment - (const struct senc2d_descriptor* descriptor, - const unsigned iseg, - unsigned indices[2]); - -/* Returns the coordinates of the ivert_th global unique vertex. */ -SENC2D_API res_T -senc2d_descriptor_get_global_vertex - (const struct senc2d_descriptor* descriptor, - const unsigned ivert, - double coord[2]); - -/* Returns the front and back media ids of the iseg_th global unique segment. */ -SENC2D_API res_T -senc2d_descriptor_get_global_segment_media - (const struct senc2d_descriptor* descriptor, - const unsigned iseg, - unsigned media[2]); - -/* Returns the enclosures the iseg_th global unique segment front and back - * sides are member of. */ -SENC2D_API res_T -senc2d_descriptor_get_global_segment_enclosures - (const struct senc2d_descriptor* descriptor, +senc2d_scene_get_segment_enclosures + (const struct senc2d_scene* scene, const unsigned iseg, unsigned enclosures[2]); -/* Returns the global id of the iseg_th global unique segment, that is the - * segment index in user world regardless of deduplication. */ -SENC2D_API res_T -senc2d_descriptor_get_global_segment_global_id - (const struct senc2d_descriptor* descriptor, - const unsigned iseg, - unsigned* gid); - /* Returns the number of vertices that are frontier vertices: * - that have arity 1 (single segment using the vertex) * - that connect 2 different media */ SENC2D_API res_T -senc2d_descriptor_get_frontier_vertices_count - (const struct senc2d_descriptor* descriptor, +senc2d_scene_get_frontier_vertice_count + (const struct senc2d_scene* scene, unsigned* count); -/* Returns the iver_th frontier vertex; the returned index is an global unique - * vertex index. */ +/* Returns the iver_th frontier vertex (segment and vertex global IDs). */ SENC2D_API res_T -senc2d_descriptor_get_frontier_vertex - (const struct senc2d_descriptor* descriptor, +senc2d_scene_get_frontier_vertex + (const struct senc2d_scene* scene, const unsigned iver, - unsigned* vrtx_id); + unsigned vrtx_id[SENC2D_GEOMETRY_DIMENSION-1], + unsigned* seg_id); SENC2D_API res_T -senc2d_descriptor_ref_get - (struct senc2d_descriptor* descriptor); +senc2d_scene_ref_get + (struct senc2d_scene* scene); SENC2D_API res_T -senc2d_descriptor_ref_put - (struct senc2d_descriptor* descriptor); +senc2d_scene_ref_put + (struct senc2d_scene* scene); -/******************************************************************************* - * StarEnclosures2D enclosure. It is an handle toward an enclosure. +/****************************************************************************** + * star-enclosures-2d enclosure. It is an handle toward an enclosure. * Counts and other information on enclosures are not individually accessible, * but as a whole through header access. * An enclosure can list the "same" segment twice if both sides are in. In this * case the 2 occurences of the segment have reversed vertices order and - * unique_segment_count and segment_count differ. + * unique_primitives_count and primitives_count differ. * Vertices and segments numbering schemes are specific to each enclosure: * the "same" item appearing in 2 different enclosures has no reason to get the * same index twice or to have the same index in the global numbering scheme. * By-index API accesses of segments (or properties) visit unique segments - * for indices in the [0 unique_segment_count[ range and back-faces of the - * doubly-included segments in the [unique_segment_count segment_count[ range. - ******************************************************************************/ + * for indices in the [0 unique_primitives_count[ range and back-faces of the + * doubly-included segments in the [unique_primitives_count primitives_count[ + * range. + *****************************************************************************/ /* Returns the header of an enclosure. */ SENC2D_API res_T senc2d_enclosure_get_header @@ -447,19 +326,19 @@ SENC2D_API res_T senc2d_enclosure_get_segment (const struct senc2d_enclosure* enclosure, const unsigned iseg, - unsigned indices[2]); + unsigned indices[SENC2D_GEOMETRY_DIMENSION]); /* Returns the coordinates of the ivert_th vertex of an enclosure. */ SENC2D_API res_T senc2d_enclosure_get_vertex (const struct senc2d_enclosure* enclosure, const unsigned ivert, - double coord[2]); + double coord[SENC2D_GEOMETRY_DIMENSION]); /* Returns the global id of the iseg_th segment of an enclosure * and the involved side. */ SENC2D_API res_T -senc2d_enclosure_get_segment_global_id +senc2d_enclosure_get_segment_id (const struct senc2d_enclosure* enclosure, const unsigned iseg, unsigned* gid, diff --git a/src/senc2d_descriptor.c b/src/senc2d_descriptor.c @@ -13,8 +13,6 @@ * 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 "senc2d_descriptor_c.h" -#include "senc2d_device_c.h" #include "senc2d_enclosure_c.h" #include "senc2d_scene_c.h" #include "senc2d.h" @@ -23,310 +21,134 @@ #include <rsys/double2.h> #include <rsys/mem_allocator.h> - /******************************************************************************* - * Helper function - ******************************************************************************/ -static void -descriptor_release(ref_T * ref) -{ - struct senc2d_scene* scn = NULL; - struct senc2d_descriptor* desc = NULL; - ASSERT(ref); - desc = CONTAINER_OF(ref, struct senc2d_descriptor, ref); - scn = desc->scene; - darray_segment_enc_release(&desc->segments_enc); - darray_enclosure_release(&desc->enclosures); - darray_enc_ids_array_release(&desc->enc_ids_array_by_medium); - darray_vrtx_id_release(&desc->frontiers); - - MEM_RM(scn->dev->allocator, desc); - SENC2D(scene_ref_put(scn)); -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -struct senc2d_descriptor* -descriptor_create(struct senc2d_scene* scn) -{ - struct senc2d_descriptor* desc; - res_T res = RES_OK; - ASSERT(scn); - desc = MEM_CALLOC(scn->dev->allocator, 1, sizeof(struct senc2d_descriptor)); - if(desc) { - desc->scene = scn; - SENC2D(scene_ref_get(desc->scene)); - ref_init(&desc->ref); - darray_segment_enc_init(scn->dev->allocator, &desc->segments_enc); - darray_enclosure_init(scn->dev->allocator, &desc->enclosures); - darray_enc_ids_array_init(scn->dev->allocator, - &desc->enc_ids_array_by_medium); - OK(darray_enc_ids_array_resize(&desc->enc_ids_array_by_medium, - 1 + scn->next_medium_idx)); /* +1 is for undef */ - darray_vrtx_id_init(scn->dev->allocator, &desc->frontiers); - /* Enclosure 0 is always defined for infinite */ - OK(darray_enclosure_resize(&desc->enclosures, 1)); - desc->enclosures_count = 1; - desc->segment_count = scn->nusegs; - desc->vertices_count = scn->nuverts; - } -exit: - return desc; -error: - if(desc) SENC2D(descriptor_ref_put(desc)); - goto exit; -} - -struct mem_allocator* - descriptor_get_allocator(struct senc2d_descriptor* desc) -{ - ASSERT(desc); - return desc->scene->dev->allocator; -} - -/******************************************************************************* +/****************************************************************************** * Exported functions - ******************************************************************************/ + *****************************************************************************/ res_T -senc2d_descriptor_get_max_medium - (const struct senc2d_descriptor* desc, unsigned* max_medium_id) +senc2d_scene_get_max_medium + (const struct senc2d_scene* scn, medium_id_t* max_medium_id) { - if(!desc || !max_medium_id) return RES_BAD_ARG; - ASSERT(desc->scene->next_medium_idx < UINT_MAX); /* API type */ - *max_medium_id = (unsigned)desc->scene->next_medium_idx - 1; + if(!scn || !max_medium_id) return RES_BAD_ARG; + *max_medium_id = scn->next_medium_idx - 1; return RES_OK; } res_T -senc2d_descriptor_get_enclosure_count - (const struct senc2d_descriptor* desc, unsigned* count) +senc2d_scene_get_enclosure_count + (const struct senc2d_scene* scn, enclosure_id_t* count) { - size_t tmp; - if(!desc || !count) return RES_BAD_ARG; - tmp = darray_enclosure_size_get(&desc->enclosures); - ASSERT(tmp < UINT_MAX); /* API type */ - ASSERT(desc->enclosures_count == tmp); - *count = (unsigned)tmp; + if(!scn || !count) return RES_BAD_ARG; + ASSERT(scn->analyze.enclosures_count == + darray_enclosure_size_get(&scn->analyze.enclosures)); + *count = scn->analyze.enclosures_count; return RES_OK; } res_T -senc2d_descriptor_get_enclosure_count_by_medium - (const struct senc2d_descriptor* desc, - const unsigned imed, - unsigned* count) +senc2d_scene_get_enclosure_count_by_medium + (const struct senc2d_scene* scn, + const medium_id_t imed, + enclosure_id_t* count) { - size_t tmp, m_idx; + size_t tmp; + size_t m_idx; const struct darray_enc_id* enc_ids; - if(!desc || !count - || (imed != SENC2D_UNDEFINED_MEDIUM && imed >= desc->scene->next_medium_idx)) + if(!scn || !count + || (imed != SENC2D_UNSPECIFIED_MEDIUM && imed >= scn->next_medium_idx)) return RES_BAD_ARG; - ASSERT(darray_enc_ids_array_size_get(&desc->enc_ids_array_by_medium) - == 1 + desc->scene->next_medium_idx); - m_idx = (imed == SENC2D_UNDEFINED_MEDIUM) ? desc->scene->next_medium_idx : imed; - enc_ids = darray_enc_ids_array_cdata_get(&desc->enc_ids_array_by_medium) + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == 1 + scn->next_medium_idx); + m_idx = medium_id_2_medium_idx(imed); + enc_ids = darray_enc_ids_array_cdata_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; tmp = darray_enc_id_size_get(enc_ids); - ASSERT(tmp < UINT_MAX); /* API type */ - *count = (unsigned)tmp; + ASSERT(tmp <= ENCLOSURE_MAX__); /* API type */ + *count = (enclosure_id_t)tmp; return RES_OK; } FINLINE res_T -senc2d_descriptor_get_enclosure - (struct senc2d_descriptor* desc, - const unsigned idx, +senc2d_scene_get_enclosure + (struct senc2d_scene* scn, + const enclosure_id_t idx, struct senc2d_enclosure** out_enc) { struct senc2d_enclosure* enc; - if(!desc || idx >= darray_enclosure_size_get(&desc->enclosures) || !out_enc) + if(!scn || idx >= darray_enclosure_size_get(&scn->analyze.enclosures) + || !out_enc) return RES_BAD_ARG; - enc = enclosure_create(desc, idx); + enc = enclosure_create(scn, idx); if(!enc) return RES_MEM_ERR; *out_enc = enc; return RES_OK; } res_T -senc2d_descriptor_get_enclosure_by_medium - (struct senc2d_descriptor* desc, - const unsigned imed, - const unsigned idx, +senc2d_scene_get_enclosure_by_medium + (struct senc2d_scene* scn, + const medium_id_t imed, + const enclosure_id_t idx, struct senc2d_enclosure** out_enc) { size_t m_idx; const struct darray_enc_id* enc_ids; - unsigned index; - if(!desc || !out_enc - || (imed != SENC2D_UNDEFINED_MEDIUM && imed >= desc->scene->next_medium_idx)) + enclosure_id_t index; + if(!scn || !out_enc + || (imed != SENC2D_UNSPECIFIED_MEDIUM && imed >= scn->next_medium_idx)) return RES_BAD_ARG; - ASSERT(darray_enc_ids_array_size_get(&desc->enc_ids_array_by_medium) - == 1 + desc->scene->next_medium_idx); - m_idx = (imed == SENC2D_UNDEFINED_MEDIUM) ? desc->scene->next_medium_idx : imed; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == 1 + scn->next_medium_idx); + m_idx = medium_id_2_medium_idx(imed); enc_ids = - darray_enc_ids_array_cdata_get(&desc->enc_ids_array_by_medium) + m_idx; + darray_enc_ids_array_cdata_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; if(idx >= darray_enc_id_size_get(enc_ids)) return RES_BAD_ARG; index = darray_enc_id_cdata_get(enc_ids)[idx]; - return senc2d_descriptor_get_enclosure(desc, index, out_enc); -} - -res_T -senc2d_descriptor_get_global_segments_count - (const struct senc2d_descriptor* desc, - unsigned* count) -{ - if(!desc || !count) return RES_BAD_ARG; - ASSERT(desc->segment_count < UINT_MAX); - *count = (unsigned)desc->segment_count; /* Back to API type */ - return RES_OK; -} - -res_T -senc2d_descriptor_get_global_vertices_count - (const struct senc2d_descriptor* desc, - unsigned* count) -{ - if(!desc || !count) return RES_BAD_ARG; - if(desc->vertices_count >= UINT_MAX) - return RES_BAD_ARG; - *count = (unsigned)desc->vertices_count; /* Back to API type */ - return RES_OK; -} - -res_T -senc2d_descriptor_get_global_segment - (const struct senc2d_descriptor* desc, - const unsigned iseg, - unsigned indices[2]) -{ - const struct segment_in* seg; - int i; - if(!indices || ! desc - || iseg >= darray_segment_in_size_get(&desc->scene->segments_in)) - return RES_BAD_ARG; - seg = darray_segment_in_cdata_get(&desc->scene->segments_in) + iseg; - - FOR_EACH(i, 0, 2) { - ASSERT(seg->vertice_id[i] < UINT_MAX); - indices[i] = (unsigned)seg->vertice_id[i]; /* Back to API type */ - } - return RES_OK; + return senc2d_scene_get_enclosure(scn, index, out_enc); } res_T -senc2d_descriptor_get_global_vertex - (const struct senc2d_descriptor* desc, - const unsigned ivert, - double vrtx[2]) -{ - const union double2* v; - if(!vrtx || !desc - || ivert >= darray_position_size_get(&desc->scene->vertices)) - return RES_BAD_ARG; - - v = darray_position_cdata_get(&desc->scene->vertices) + ivert; - d2_set(vrtx, v->vec); - return RES_OK; -} - -res_T -senc2d_descriptor_get_global_segment_media - (const struct senc2d_descriptor* desc, - const unsigned isef, - unsigned media[2]) -{ - const struct segment_in* seg; - int i; - if(!media || !desc - || isef >= darray_segment_in_size_get(&desc->scene->segments_in)) - return RES_BAD_ARG; - seg = darray_segment_in_cdata_get(&desc->scene->segments_in) + isef; - FOR_EACH(i, 0, 2) { -#if (UINT_MAX < MEDIUM_MAX__) - ASSERT(seg->medium[i] < UINT_MAX); -#endif - media[i] = (unsigned)seg->medium[i]; /* Back to API type */ - } - return RES_OK; -} - -res_T -senc2d_descriptor_get_global_segment_enclosures - (const struct senc2d_descriptor* desc, - const unsigned iseg, - unsigned enclosures[2]) +senc2d_scene_get_segment_enclosures + (const struct senc2d_scene* scn, + const seg_id_t iseg, + enclosure_id_t enclosures[2]) { const struct segment_enc* seg; int i; - if(!enclosures || !desc - || iseg >= darray_segment_enc_size_get(&desc->segments_enc)) + if(!enclosures || !scn + || iseg >= darray_segment_enc_size_get(&scn->analyze.segments_enc)) return RES_BAD_ARG; - seg = darray_segment_enc_cdata_get(&desc->segments_enc) + iseg; - FOR_EACH(i, 0, 2) { -#if (UINT_MAX < ENCLOSURE_MAX__) - ASSERT(seg->enclosure[i] < UINT_MAX); -#endif - enclosures[i] = (unsigned)seg->enclosure[i]; /* Back to API type */ - } + seg = darray_segment_enc_cdata_get(&scn->analyze.segments_enc) + iseg; + FOR_EACH(i, 0, 2) enclosures[i] = seg->enclosure[i]; return RES_OK; } res_T -senc2d_descriptor_get_global_segment_global_id - (const struct senc2d_descriptor* desc, - const unsigned iseg, - unsigned* gid) -{ - const struct segment_in* seg; - if(!gid || !desc - || iseg >= darray_segment_in_size_get(&desc->scene->segments_in)) - return RES_BAD_ARG; - seg = darray_segment_in_cdata_get(&desc->scene->segments_in) + iseg; - *gid = seg->global_id; - return RES_OK; -} - -res_T -senc2d_descriptor_get_frontier_vertices_count - (const struct senc2d_descriptor* desc, - unsigned* count) +senc2d_scene_get_frontier_vertice_count + (const struct senc2d_scene* scn, + vrtx_id_t* count) { size_t tmp; - if(!desc || !count) + if(!scn || !count) return RES_BAD_ARG; - tmp = darray_vrtx_id_size_get(&desc->frontiers); - ASSERT(tmp < UINT_MAX); - *count = (unsigned)tmp; + tmp = darray_frontier_vertex_size_get(&scn->analyze.frontiers); + ASSERT(tmp <= VRTX_MAX__); + *count = (vrtx_id_t)tmp; /* Back to API type */ return RES_OK; } res_T -senc2d_descriptor_get_frontier_vertex - (const struct senc2d_descriptor* desc, - const unsigned iver, - unsigned* vrtx_id) -{ - vrtx_id_t vrtx; - if(!vrtx_id || !desc - || iver >= darray_vrtx_id_size_get(&desc->frontiers)) +senc2d_scene_get_frontier_vertex + (const struct senc2d_scene* scn, + const vrtx_id_t iver, + vrtx_id_t* vrtx_id, + unsigned* seg_id) +{ + const struct frontier_vertex* vrtx; + if(!vrtx_id || !scn || !seg_id + || iver >= darray_frontier_vertex_size_get(&scn->analyze.frontiers)) return RES_BAD_ARG; - vrtx = darray_vrtx_id_cdata_get(&desc->frontiers)[iver]; - *vrtx_id = (unsigned)vrtx; /* Back to API type */ - return RES_OK; -} - -res_T -senc2d_descriptor_ref_get(struct senc2d_descriptor* desc) -{ - if(!desc) return RES_BAD_ARG; - ref_get(&desc->ref); - return RES_OK; -} - -res_T -senc2d_descriptor_ref_put(struct senc2d_descriptor* desc) -{ - if(!desc) return RES_BAD_ARG; - ref_put(&desc->ref, descriptor_release); + vrtx = darray_frontier_vertex_cdata_get(&scn->analyze.frontiers) + iver; + *vrtx_id = vrtx->vrtx; + *seg_id = vrtx->seg; return RES_OK; } diff --git a/src/senc2d_descriptor_c.h b/src/senc2d_descriptor_c.h @@ -1,109 +0,0 @@ -/* Copyright (C) |Meso|Star> 2018-2020 (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/>. */ - -#ifndef SENC2D_DESCRIPTOR_C_H -#define SENC2D_DESCRIPTOR_C_H - -#include <rsys/ref_count.h> -#include <rsys/dynamic_array.h> - -#include "senc2d.h" -#include "senc2d_enclosure_data.h" -#include "senc2d_internal_types.h" - -struct senc2d_scene; -struct mem_allocator; - -struct segment_comp { - /* The connex component in which each side is. */ - component_id_t component[2]; -}; - -static void -segment_comp_init(struct mem_allocator* alloc, struct segment_comp* seg) { - int i; - (void)alloc; - ASSERT(seg); - FOR_EACH(i, 0, 2) seg->component[i] = COMPONENT_NULL__; -} - -#define DARRAY_NAME segment_comp -#define DARRAY_DATA struct segment_comp -#define DARRAY_FUNCTOR_INIT segment_comp_init -#include <rsys/dynamic_array.h> - -struct segment_enc { - /* The enclosure in which each side is. */ - enclosure_id_t enclosure[2]; -}; - -#ifndef NDEBUG -static void -segment_enc_init(struct mem_allocator* alloc, struct segment_enc* seg) { - int i; - (void)alloc; - ASSERT(seg); - FOR_EACH(i, 0, 2) seg->enclosure[i] = ENCLOSURE_NULL__; -} -#define DARRAY_FUNCTOR_INIT segment_enc_init -#endif - -#define DARRAY_NAME segment_enc -#define DARRAY_DATA struct segment_enc -#include <rsys/dynamic_array.h> - -#define DARRAY_NAME enclosure -#define DARRAY_DATA struct enclosure_data -#define DARRAY_FUNCTOR_INIT enclosure_data_init -#define DARRAY_FUNCTOR_COPY enclosure_data_copy -#define DARRAY_FUNCTOR_RELEASE enclosure_data_release -#define DARRAY_FUNCTOR_COPY_AND_RELEASE enclosure_data_copy_and_release -#include <rsys/dynamic_array.h> - -#define DARRAY_NAME enc_id -#define DARRAY_DATA enclosure_id_t -#include <rsys/dynamic_array.h> - -#define DARRAY_NAME enc_ids_array -#define DARRAY_DATA struct darray_enc_id -#define DARRAY_FUNCTOR_INIT darray_enc_id_init -#define DARRAY_FUNCTOR_COPY darray_enc_id_copy -#define DARRAY_FUNCTOR_RELEASE darray_enc_id_release -#define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_enc_id_copy_and_release -#include <rsys/dynamic_array.h> - -struct senc2d_descriptor { - struct senc2d_scene* scene; - enclosure_id_t enclosures_count; - /* Store by-segment enclosures */ - struct darray_segment_enc segments_enc; - /* Store enclosures */ - struct darray_enclosure enclosures; - struct darray_enc_ids_array enc_ids_array_by_medium; - seg_id_t segment_count; - vrtx_id_t vertices_count; - /* Store frontiers */ - struct darray_vrtx_id frontiers; - - ref_T ref; -}; - -struct senc2d_descriptor* -descriptor_create(struct senc2d_scene* scn); - -struct mem_allocator* -descriptor_get_allocator(struct senc2d_descriptor* desc); - -#endif /* SENC2D_DESCRIPTOR_C_H */ diff --git a/src/senc2d_device.c b/src/senc2d_device.c @@ -21,9 +21,9 @@ #include <omp.h> -/******************************************************************************* +/****************************************************************************** * Helper functions - ******************************************************************************/ + *****************************************************************************/ static void log_msg (struct senc2d_device* dev, @@ -48,9 +48,9 @@ device_release(ref_T* ref) MEM_RM(dev->allocator, dev); } -/******************************************************************************* +/****************************************************************************** * Local functions - ******************************************************************************/ + *****************************************************************************/ void log_err(struct senc2d_device* dev, const char* msg, ...) { @@ -84,9 +84,9 @@ log_info(struct senc2d_device* dev, const char* msg, ...) va_end(vargs_list); } -/******************************************************************************* +/****************************************************************************** * Exported functions - ******************************************************************************/ + *****************************************************************************/ res_T senc2d_device_create (struct logger* logger, @@ -108,7 +108,7 @@ senc2d_device_create if(verbose) { /* Do not use helper log functions since dev is not initialised */ CHK(logger_print(log, LOG_ERROR, - "%s: could not allocate the StarEnclosures2D device.\n", FUNC_NAME) == RES_OK); + "%s: could not allocate the star-enclosures-2d device.\n", FUNC_NAME) == RES_OK); } res = RES_MEM_ERR; goto error; diff --git a/src/senc2d_enclosure.c b/src/senc2d_enclosure.c @@ -14,8 +14,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "senc2d_enclosure_c.h" -#include "senc2d_descriptor_c.h" +#include "senc2d_enclosure_data.h" #include "senc2d_scene_c.h" +#include "senc2d_device_c.h" #include "senc2d.h" #include <rsys/rsys.h> @@ -23,48 +24,46 @@ #include <rsys/mem_allocator.h> -/******************************************************************************* +/****************************************************************************** * Helper function - ******************************************************************************/ + *****************************************************************************/ static void enclosure_release(ref_T * ref) { struct senc2d_enclosure* enclosure = NULL; - struct senc2d_descriptor* desc = NULL; + struct senc2d_scene* scn = NULL; ASSERT(ref); enclosure = CONTAINER_OF(ref, struct senc2d_enclosure, ref); - desc = enclosure->desc; - - MEM_RM(descriptor_get_allocator(desc), enclosure); - SENC2D(descriptor_ref_put(desc)); + scn = enclosure->scene; + MEM_RM(scn->dev->allocator, enclosure); + SENC2D(scene_ref_put(scn)); } -/******************************************************************************* +/****************************************************************************** * Local functions - ******************************************************************************/ + *****************************************************************************/ struct senc2d_enclosure* enclosure_create - (struct senc2d_descriptor* desc, - const unsigned idx) + (struct senc2d_scene* scn, + const enclosure_id_t idx) { struct senc2d_enclosure* enc; - ASSERT(desc && idx < darray_enclosure_size_get(&desc->enclosures)); - enc = MEM_CALLOC(descriptor_get_allocator(desc), - 1, sizeof(struct senc2d_enclosure)); + ASSERT(scn && idx < darray_enclosure_size_get(&scn->analyze.enclosures)); + enc = MEM_CALLOC(scn->dev->allocator, 1, sizeof(struct senc2d_enclosure)); if(enc) { const struct enclosure_data* data - = darray_enclosure_data_get(&desc->enclosures) + idx; - SENC2D(descriptor_ref_get(desc)); - enc->desc = desc; + = darray_enclosure_data_get(&scn->analyze.enclosures) + idx; + enc->scene = scn; enc->data = data; ref_init(&enc->ref); + SENC2D(scene_ref_get(scn)); } return enc; } -/******************************************************************************* +/****************************************************************************** * Exported functions - ******************************************************************************/ + *****************************************************************************/ res_T senc2d_enclosure_get_header (const struct senc2d_enclosure* enclosure, @@ -78,28 +77,25 @@ senc2d_enclosure_get_header res_T senc2d_enclosure_get_segment (const struct senc2d_enclosure* enclosure, - const unsigned iseg, - unsigned indices[2]) + const seg_id_t iseg, + vrtx_id_t indices[2]) { const struct side_enc* side; int i; if(!enclosure || !indices - || iseg >= enclosure->data->header.segment_count) + || iseg >= enclosure->data->header.primitives_count) return RES_BAD_ARG; ASSERT(darray_sides_enc_size_get(&enclosure->data->sides) - == enclosure->data->header.segment_count); + == enclosure->data->header.primitives_count); side = darray_sides_enc_cdata_get(&enclosure->data->sides) + iseg; - FOR_EACH(i, 0, 2) { - ASSERT(side->vertice_id[i] < UINT_MAX); - indices[i] = (unsigned)side->vertice_id[i]; /* Back to API type */ - } + FOR_EACH(i, 0, 2) indices[i] = side->vertice_id[i]; return RES_OK; } res_T senc2d_enclosure_get_vertex (const struct senc2d_enclosure* enclosure, - const unsigned ivert, + const vrtx_id_t ivert, double coord[2]) { if(!enclosure || !coord @@ -109,7 +105,7 @@ senc2d_enclosure_get_vertex const vrtx_id_t idx = darray_vrtx_id_cdata_get(&enclosure->data->vertices)[ivert]; const union double2* positions - = darray_position_cdata_get(&enclosure->desc->scene->vertices); + = darray_position_cdata_get(&enclosure->scene->vertices); ASSERT(darray_vrtx_id_size_get(&enclosure->data->vertices) == enclosure->data->header.vertices_count); d2_set(coord, positions[idx].vec); @@ -118,20 +114,20 @@ senc2d_enclosure_get_vertex } res_T -senc2d_enclosure_get_segment_global_id +senc2d_enclosure_get_segment_id (const struct senc2d_enclosure* enclosure, - const unsigned iseg, - unsigned* gid, + const seg_id_t iseg, + seg_id_t* gid, enum senc2d_side* sde) { const struct side_enc* side; if(!enclosure || !gid || !sde - || iseg >= enclosure->data->header.segment_count) + || iseg >= enclosure->data->header.primitives_count) return RES_BAD_ARG; ASSERT(darray_sides_enc_size_get(&enclosure->data->sides) - == enclosure->data->header.segment_count); + == enclosure->data->header.primitives_count); side = darray_sides_enc_cdata_get(&enclosure->data->sides) + iseg; - *gid = (unsigned)SEGSIDE_2_SEG(side->side_id); + *gid = SEGSIDE_2_SEG(side->side_id); *sde = SEGSIDE_2_SIDE(side->side_id); return RES_OK; } @@ -139,8 +135,8 @@ senc2d_enclosure_get_segment_global_id res_T senc2d_enclosure_get_medium (const struct senc2d_enclosure* enclosure, - const unsigned imed, - unsigned* medium) + const medium_id_t imed, + medium_id_t* medium) { if(!enclosure || !medium || imed >= enclosure->data->header.enclosed_media_count) diff --git a/src/senc2d_enclosure_c.h b/src/senc2d_enclosure_c.h @@ -19,19 +19,20 @@ #include <rsys/ref_count.h> #include "senc2d.h" +#include "senc2d_internal_types.h" struct enclosure_data; -struct senc2d_descriptor; +struct senc2d_scene; struct senc2d_enclosure { const struct enclosure_data* data; - struct senc2d_descriptor* desc; + struct senc2d_scene* scene; ref_T ref; }; struct senc2d_enclosure* enclosure_create - (struct senc2d_descriptor* desc, - const unsigned idx); + (struct senc2d_scene* scene, + const enclosure_id_t idx); #endif /* SENC2D_ENCLOSURE_C_H */ diff --git a/src/senc2d_enclosure_data.h b/src/senc2d_enclosure_data.h @@ -16,17 +16,27 @@ #ifndef SENC2D_ENCLOSURE_DATA_H #define SENC2D_ENCLOSURE_DATA_H +#include "senc2d.h" +#include "senc2d_internal_types.h" +#include "senc2d_side_range.h" + #include <rsys/rsys.h> #include <rsys/ref_count.h> #include <rsys/hash_table.h> #include <rsys/dynamic_array.h> - -#include "senc2d.h" -#include "senc2d_scene_c.h" -#include "senc2d_internal_types.h" +#include <rsys/hash_table.h> #include <limits.h> +#define DARRAY_NAME vrtx_id +#define DARRAY_DATA vrtx_id_t +#include <rsys/dynamic_array.h> + +#define HTABLE_NAME vrtx_id +#define HTABLE_KEY vrtx_id_t +#define HTABLE_DATA vrtx_id_t +#include <rsys/hash_table.h> + struct side_enc { vrtx_id_t vertice_id[2]; side_id_t side_id; @@ -36,12 +46,13 @@ struct side_enc { #define DARRAY_DATA struct side_enc #include <rsys/dynamic_array.h> -/* unsigned char array with init to zero */ +/* uchar array with init to zero */ static FINLINE void zero_init_uchar - (struct mem_allocator* alloc, unsigned char* data) + (struct mem_allocator* alloc, uchar* data) { - ASSERT(data); (void)alloc; + ASSERT(data); (void) + alloc; *data = 0; } #define DARRAY_FUNCTOR_INIT zero_init_uchar @@ -52,8 +63,8 @@ init_header(struct senc2d_enclosure_header* header) { ASSERT(header); header->enclosure_id = ENCLOSURE_NULL__; - header->segment_count = 0; - header->unique_segment_count = 0; + header->primitives_count = 0; + header->unique_primitives_count = 0; header->vertices_count = 0; header->enclosed_media_count = 0; header->is_infinite = CHAR_MAX; @@ -66,18 +77,17 @@ init_header(struct senc2d_enclosure_header* header) static FINLINE res_T bool_array_of_media_merge (struct darray_uchar* dst, - const unsigned char* src, + const uchar* src, const medium_id_t sz) { res_T res = RES_OK; medium_id_t i; - unsigned char* data_dst; + uchar* data_dst; ASSERT(src && dst); OK(darray_uchar_resize(dst, sz)); data_dst = darray_uchar_data_get(dst); - ASSERT(sz <= MEDIUM_MAX__); if(res != RES_OK) goto error; FOR_EACH(i, 0, sz) { if(!src[i]) continue; @@ -92,24 +102,24 @@ error: static FINLINE res_T bool_array_of_media_to_darray_media (struct darray_media* dst, - struct darray_uchar* src, - const medium_id_t undef_idx) + const struct darray_uchar* src, + const medium_id_t next_medium_idx) { res_T res = RES_OK; - medium_id_t i; - const unsigned char* data; + int64_t m_idx; + const uchar* data; ASSERT(src && dst); data = darray_uchar_cdata_get(src); - ASSERT(undef_idx + 1 == darray_uchar_size_get(src)); - ASSERT(undef_idx < MEDIUM_MAX__); + ASSERT(next_medium_idx + 1 == darray_uchar_size_get(src)); darray_media_clear(dst); if(res != RES_OK) goto error; - FOR_EACH(i, 0, undef_idx + 1) { - medium_id_t v = (i == undef_idx) ? SENC2D_UNDEFINED_MEDIUM : i; - if(!data[i]) continue; - res = darray_media_push_back(dst, &v); + ASSERT(next_medium_idx <= MEDIUM_MAX__ + 1); + FOR_EACH(m_idx, 0, 1 + (int64_t)next_medium_idx) { + medium_id_t medium = medium_idx_2_medium_id(m_idx); + if(!data[m_idx]) continue; + res = darray_media_push_back(dst, &medium); if(res != RES_OK) goto error; } end: @@ -120,7 +130,7 @@ error: struct enclosure_data { struct senc2d_enclosure_header header; - /* Same segment can appear twice if both sides */ + /* Same segments can appear twice if both sides */ struct darray_sides_enc sides; /* Index of vertices in scene's unique vertices */ struct darray_vrtx_id vertices; @@ -202,4 +212,24 @@ error: return res; } +#define DARRAY_NAME enclosure +#define DARRAY_DATA struct enclosure_data +#define DARRAY_FUNCTOR_INIT enclosure_data_init +#define DARRAY_FUNCTOR_COPY enclosure_data_copy +#define DARRAY_FUNCTOR_RELEASE enclosure_data_release +#define DARRAY_FUNCTOR_COPY_AND_RELEASE enclosure_data_copy_and_release +#include <rsys/dynamic_array.h> + +#define DARRAY_NAME enc_id +#define DARRAY_DATA enclosure_id_t +#include <rsys/dynamic_array.h> + +#define DARRAY_NAME enc_ids_array +#define DARRAY_DATA struct darray_enc_id +#define DARRAY_FUNCTOR_INIT darray_enc_id_init +#define DARRAY_FUNCTOR_COPY darray_enc_id_copy +#define DARRAY_FUNCTOR_RELEASE darray_enc_id_release +#define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_enc_id_copy_and_release +#include <rsys/dynamic_array.h> + #endif /* SENC2D_ENCLOSURE_DATA_H */ diff --git a/src/senc2d_internal_types.h b/src/senc2d_internal_types.h @@ -16,8 +16,11 @@ #ifndef SENC2D_INTERNAL_TYPES_H #define SENC2D_INTERNAL_TYPES_H +#include "senc2d.h" + #include <rsys/math.h> +#include <stdio.h> #include <stdint.h> /* Utility macros */ @@ -43,51 +46,72 @@ } #endif -/* Side IDs are uint32_t */ -typedef uint32_t side_id_t; -#define SIDE_MAX__ (UINT32_MAX-1) -#define SIDE_NULL__ UINT32_MAX +/* Helper type */ +typedef unsigned char uchar; + +/* The following types must be defined accordingly with the types + * used in senc2d.h */ + +/* Segment IDs use the same type than Side IDs */ +typedef unsigned seg_id_t; +/* SEG_MAX__ is limited to half the max of the base type to allow to count + * sides */ +#define SEG_MAX__ (UINT_MAX/2) +#define SEG_NULL__ UINT_MAX +#define PRTF_SEG "%u" -/* Seg IDs use internally side_id_t */ -/* Cannot be larger than unsigned, as the API uses it. */ -typedef side_id_t seg_id_t; -/* SEG_MAX__ is limited to allow to count sides */ -#define SEG_MAX__ (SIDE_MAX__ / 2) -#define SEG_NULL__ UINT32_MAX +/* Side IDs type use the same base type than Segment IDs */ +typedef seg_id_t side_id_t; +#define SIDE_MAX__ (2*SEG_MAX__) +#define SIDE_NULL__ SEG_NULL__ -/* Vertex IDs are internally uint32_t */ -/* Cannot be larger than unsigned, as the API uses it. */ -typedef uint32_t vrtx_id_t; -#define VRTX_MAX__ (UINT32_MAX-1) -#define VRTX_NULL__ UINT32_MAX +/* Vertex IDs type */ +typedef unsigned vrtx_id_t; +#define VRTX_MAX__ (UINT_MAX-1) +#define VRTX_NULL__ UINT_MAX +#define PRTF_VRTX "%u" /* Edge IDs use the same type than vertex IDs */ -/* Cannot be larger than unsigned, as the API uses it. */ typedef vrtx_id_t edge_id_t; #define EDGE_MAX__ VRTX_MAX__ #define EDGE_NULL__ VRTX_NULL__ -/* Medium IDs are internally uint32_t */ -/* Should nnot be larger than unsigned, as the API uses it. */ -typedef uint32_t medium_id_t; -#define MEDIUM_MAX__ INT32_MAX -#define MEDIUM_NULL__ UINT32_MAX +/* Medium IDs type */ +typedef unsigned medium_id_t; +#define MEDIUM_MAX__ (UINT_MAX-1) /* MAX is for unspecified medium */ +#define MEDIUM_NULL__ UINT_MAX +#define PRTF_MDM "%u" -/* Enclosure IDs are internally uint32_t */ -/* Cannot be larger than unsigned, as the API uses it. */ -typedef uint32_t enclosure_id_t; -#define ENCLOSURE_MAX__ UINT32_MAX -#define ENCLOSURE_NULL__ UINT32_MAX +static FINLINE medium_id_t +medium_idx_2_medium_id(int64_t m_idx) { + return m_idx ? (medium_id_t)(m_idx - 1) : SENC2D_UNSPECIFIED_MEDIUM; +} + +static FINLINE unsigned +medium_id_2_medium_idx(medium_id_t medium) { + uint64_t tmp = (medium == SENC2D_UNSPECIFIED_MEDIUM) ? 0 : medium + 1; + ASSERT(tmp <= UINT_MAX); + return (unsigned)tmp; +} + +/* Enclosure IDs type */ +typedef unsigned enclosure_id_t; +#define ENCLOSURE_MAX__ (UINT_MAX-1) +#define ENCLOSURE_NULL__ UINT_MAX /* Component IDs use the same type than enclosure IDs */ typedef enclosure_id_t component_id_t; -#define COMPONENT_MAX__ (UINT32_MAX - 2) /* To allow special values */ -#define COMPONENT_NULL__ UINT32_MAX +#define COMPONENT_MAX__ (UINT_MAX-2) /* To allow special values */ +#define COMPONENT_NULL__ UINT_MAX /* Special values */ -#define CC_GROUP_ROOT_NONE UINT32_MAX -#define CC_GROUP_ROOT_INFINITE (UINT32_MAX - 1) -#define CC_GROUP_ID_NONE UINT32_MAX -#define CC_ID_NONE UINT32_MAX +#define CC_GROUP_ROOT_NONE UINT_MAX +#define CC_GROUP_ROOT_INFINITE (UINT_MAX-1) +#define CC_GROUP_ID_NONE UINT_MAX +#define CC_ID_NONE UINT_MAX + +#if (MEDIUM_MAX__+1 != SENC2D_UNSPECIFIED_MEDIUM) +#error "Inconsistant values" +#endif /* This one is used as flag */ enum side_flag { @@ -117,17 +141,19 @@ SEGSIDE_2_SIDEFLAG(side_id_t s) { return (s & 1) ? FLAG_BACK : FLAG_FRONT; } -static FINLINE unsigned char +static FINLINE uchar SIDE_CANCELED_FLAG(enum side_flag f) { - ASSERT((((unsigned)f) << 4) <= UCHAR_MAX); - return (unsigned char)(f << 4); + ASSERT((f << 4) <= UCHAR_MAX); + return (uchar)(f << 4); } static FINLINE side_id_t SEGIDxSIDE_2_SEGSIDE(seg_id_t s, enum senc2d_side i) { - ASSERT((((size_t)s << 1) | (i == SENC2D_BACK)) < SIDE_MAX__); + size_t r; ASSERT(i == SENC2D_FRONT || i == SENC2D_BACK); - return (side_id_t)((s << 1) | (i == SENC2D_BACK)); + r = (s << 1) | (i == SENC2D_BACK); + ASSERT(r <= SIDE_MAX__); + return (side_id_t)r; } static FINLINE side_id_t diff --git a/src/senc2d_s2d_wrapper.h b/src/senc2d_s2d_wrapper.h @@ -1,80 +0,0 @@ -/* Copyright (C) |Meso|Star> 2018-2020 (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/>. */ - -#ifndef SENC2D_S2D_WRAPPER_H -#define SENC2D_S2D_WRAPPER_H - -#include "senc2d.h" - -#include <rsys/rsys.h> -#include <rsys/float2.h> - -static FINLINE void -senc2d_descriptor_get_global_indices__ - (const unsigned iseg, - unsigned indices[2], - void* ctx) -{ - const struct senc2d_descriptor* descriptor = ctx; - res_T r; - ASSERT(indices && ctx); - r = senc2d_descriptor_get_global_segment(descriptor, iseg, indices); - ASSERT(r == RES_OK); (void)r; -} - -static FINLINE void -senc2d_descriptor_get_global_vertices__ - (const unsigned ivert, - float coord[2], - void* ctx) -{ - const struct senc2d_descriptor* descriptor = ctx; - double tmp[2]; - res_T r; - ASSERT(coord && ctx); - r = senc2d_descriptor_get_global_vertex(descriptor, ivert, tmp); - ASSERT(r == RES_OK); (void)r; - f2_set_d2(coord, tmp); -} - -static FINLINE void -senc2d_enclosure_get_segment__ - (const unsigned iseg, - unsigned indices[2], - void* ctx) -{ - const struct senc2d_enclosure* enclosure = ctx; - res_T r; - ASSERT(indices && ctx); - r = senc2d_enclosure_get_segment(enclosure, iseg, indices); - ASSERT(r == RES_OK); (void)r; -} - -static FINLINE void -senc2d_enclosure_get_vertex__ - (const unsigned ivert, - float coord[2], - void* ctx) -{ - const struct senc2d_enclosure* enclosure = ctx; - double tmp[2]; - res_T r; - ASSERT(coord && ctx); - r = senc2d_enclosure_get_vertex(enclosure, ivert, tmp); - ASSERT(r == RES_OK); (void)r; - f2_set_d2(coord, tmp); -} - -#endif /* SENC2D_S2D_WRAPPER_H */ diff --git a/src/senc2d_sXd_helper.h b/src/senc2d_sXd_helper.h @@ -0,0 +1,85 @@ +/* Copyright (C) |Meso|Star> 2018-2020 (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/>. */ + +#ifndef SENC2D_S2D_WRAPPER_H +#define SENC2D_S2D_WRAPPER_H + +#include "senc2d.h" + +#include <rsys/rsys.h> + +/* Get vertex indices for the iseg_th segment. + * Suitable for use as get_indice callback in s2d_mesh_setup_indexed_vertices + * calls. */ +static FINLINE void +senc2d_sXd_scene_get_indices + (const unsigned iseg, + unsigned indices[SENC2D_GEOMETRY_DIMENSION], + void* ctx) +{ + const struct senc2d_scene* scene = ctx; + ASSERT(indices && scene); + SENC2D(scene_get_segment(scene, iseg, indices)); +} + +/* Get coordinates for the ivert_th vertex. + * Suitable for use as s2d_vertex_data getter for S2D_POSITION s2d_attrib_usage + * in s2d_mesh_setup_indexed_vertices calls. */ +static FINLINE void +senc2d_sXd_scene_get_position + (const unsigned ivert, + float coord[SENC2D_GEOMETRY_DIMENSION], + void* ctx) +{ + const struct senc2d_scene* scene = ctx; + double tmp[SENC2D_GEOMETRY_DIMENSION]; + int i; + ASSERT(coord && scene); + SENC2D(scene_get_vertex(scene, ivert, tmp)); + FOR_EACH(i, 0, SENC2D_GEOMETRY_DIMENSION) coord[i] = (float)tmp[i]; +} + +/* Get vertex indices for the iseg_th segment of the enclosure. + * Suitable for use as get_indice callback in s2d_mesh_setup_indexed_vertices + * calls. */ +static FINLINE void +senc2d_sXd_enclosure_get_indices + (const unsigned iseg, + unsigned indices[SENC2D_GEOMETRY_DIMENSION], + void* ctx) +{ + const struct senc2d_enclosure* enclosure = ctx; + ASSERT(indices && ctx); + SENC2D(enclosure_get_segment(enclosure, iseg, indices)); +} + +/* Get coordinates for the ivert_th vertex of the enclosure. + * Suitable for use as s2d_vertex_data getter for S2D_POSITION s2d_attrib_usage + * in s2d_mesh_setup_indexed_vertices calls. */ +static FINLINE void +senc2d_sXd_enclosure_get_position + (const unsigned ivert, + float coord[SENC2D_GEOMETRY_DIMENSION], + void* ctx) +{ + const struct senc2d_enclosure* enclosure = ctx; + double tmp[SENC2D_GEOMETRY_DIMENSION]; + int i; + ASSERT(coord && ctx); + SENC2D(enclosure_get_vertex(enclosure, ivert, tmp)); + FOR_EACH(i, 0, SENC2D_GEOMETRY_DIMENSION) coord[i] = (float)tmp[i]; +} + +#endif /* SENC2D_S2D_WRAPPER_H */ diff --git a/src/senc2d_scene.c b/src/senc2d_scene.c @@ -16,6 +16,7 @@ #include "senc2d.h" #include "senc2d_device_c.h" #include "senc2d_scene_c.h" +#include "senc2d_scene_analyze_c.h" #include <rsys/rsys.h> #include <rsys/double2.h> @@ -23,9 +24,9 @@ #include <limits.h> -/******************************************************************************* +/****************************************************************************** * Helper function - ******************************************************************************/ + *****************************************************************************/ static void scene_release(ref_T * ref) { @@ -36,9 +37,13 @@ scene_release(ref_T * ref) dev = scn->dev; darray_segment_in_release(&scn->segments_in); darray_position_release(&scn->vertices); - htable_vrtx_release(&scn->unique_vertices); - htable_seg_release(&scn->unique_segments); darray_side_range_release(&scn->media_use); + + darray_segment_enc_release(&scn->analyze.segments_enc); + darray_enclosure_release(&scn->analyze.enclosures); + darray_enc_ids_array_release(&scn->analyze.enc_ids_array_by_medium); + darray_frontier_vertex_release(&scn->analyze.frontiers); + MEM_RM(dev->allocator, scn); SENC2D(device_ref_put(dev)); } @@ -48,23 +53,35 @@ compatible_medium (const medium_id_t m1, const medium_id_t m2) { - if(m1 == SENC2D_UNDEFINED_MEDIUM || m2 == SENC2D_UNDEFINED_MEDIUM) return 1; + if(m1 == SENC2D_UNSPECIFIED_MEDIUM || m2 == SENC2D_UNSPECIFIED_MEDIUM) + return 1; return (m1 == m2); } -/******************************************************************************* +/****************************************************************************** * Exported functions - ******************************************************************************/ + *****************************************************************************/ res_T senc2d_scene_create (struct senc2d_device* dev, const int conv, + const seg_id_t nsegs, + void(*indices)(const seg_id_t, vrtx_id_t*, void*), + void(*media)(const seg_id_t, medium_id_t*, void*), + const vrtx_id_t nverts, + void(*position)(const vrtx_id_t, double*, void* ctx), + void* ctx, struct senc2d_scene** out_scn) { struct senc2d_scene* scn = NULL; + /* Tables to detect duplicates */ + struct htable_vrtx unique_vertices; + struct htable_seg unique_segments; + vrtx_id_t nv; + seg_id_t ns; res_T res = RES_OK; - if(!dev || !out_scn + if(!dev || !out_scn || !indices || !position || !nverts || !nsegs /* Convention must be set both regarding FRONT/BACK and INSIDE/OUTSIDE */ || !(conv & (SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_BACK)) || !(conv & (SENC2D_CONVENTION_NORMAL_INSIDE | SENC2D_CONVENTION_NORMAL_OUTSIDE))) @@ -72,7 +89,7 @@ senc2d_scene_create scn = MEM_CALLOC(dev->allocator, 1, sizeof(struct senc2d_scene)); if(!scn) { - log_err(dev, "%s: could not allocate the StarEnclosures2D scene.\n", FUNC_NAME); + log_err(dev, "%s: could not allocate the star-enclosures-2d scene.\n", FUNC_NAME); res = RES_MEM_ERR; goto error; } @@ -80,240 +97,136 @@ senc2d_scene_create SENC2D(device_ref_get(dev)); scn->dev = dev; scn->convention = conv; - scn->nsegs = 0; - scn->nusegs = 0; + scn->nsegs = nsegs; scn->next_medium_idx = 0; - scn->nverts = 0; - scn->nuverts = 0; - scn->sides_with_defined_medium_count = 0; + scn->nverts = nverts; darray_segment_in_init(dev->allocator, &scn->segments_in); darray_position_init(dev->allocator, &scn->vertices); - htable_vrtx_init(dev->allocator, &scn->unique_vertices); - htable_seg_init(dev->allocator, &scn->unique_segments); + htable_vrtx_init(dev->allocator, &unique_vertices); + htable_seg_init(dev->allocator, &unique_segments); darray_side_range_init(dev->allocator, &scn->media_use); -exit: - if(scn) *out_scn = scn; - return res; -error: - if(scn) { - SENC2D(scene_ref_put(scn)); - scn = NULL; - } - goto exit; -} - -res_T -senc2d_scene_reserve - (struct senc2d_scene* scn, - const unsigned vertices_count, - const unsigned segments_count, - const unsigned media_count) -{ - res_T res = RES_OK; - if(!scn) return RES_BAD_ARG; - - OK(darray_position_reserve(&scn->vertices, vertices_count)); - OK(darray_segment_in_reserve(&scn->segments_in, segments_count)); - OK(htable_vrtx_reserve(&scn->unique_vertices, vertices_count)); - OK(htable_seg_reserve(&scn->unique_segments, segments_count)); - OK(darray_side_range_reserve(&scn->media_use, media_count)); - -end: - return res; -error: - goto end; -} - -res_T -senc2d_scene_add_geometry - (struct senc2d_scene* scn, - const unsigned nsegs, - void(*indices)(const unsigned, unsigned* ids, void*), - void(*media)(const unsigned, unsigned* med, void*), - const unsigned nverts, - void(*position)(const unsigned, double* pos, void*), - res_T(*add_segment)(const unsigned, const unsigned, void*), - res_T(*merge_segment)(const unsigned, const unsigned, const int, - const unsigned*, const unsigned*, void*), - void* ctx) -{ - struct darray_vrtx_id unique_vertice_ids; - unsigned i; - vrtx_id_t actual_nverts = 0; - vrtx_id_t actual_nuverts = 0; - seg_id_t actual_nsegs = 0; - seg_id_t actual_nusegs = 0; - const struct segment_in* seg; - res_T res = RES_OK; - - if(!scn - || !indices || !position - || !nverts || ((size_t)scn->nverts + (size_t)nverts) > VRTX_MAX__ - || !nsegs || ((size_t)scn->nsegs + (size_t)nsegs) > SEG_MAX__) - return RES_BAD_ARG; - - /* Make room for new geometry; suppose no more duplicates. */ - darray_vrtx_id_init(scn->dev->allocator, &unique_vertice_ids); - OK(darray_vrtx_id_reserve(&unique_vertice_ids, nverts)); - OK(darray_position_reserve(&scn->vertices, scn->nuverts + nverts)); - OK(darray_segment_in_reserve(&scn->segments_in, scn->nusegs + nsegs)); - OK(htable_vrtx_reserve(&scn->unique_vertices, scn->nuverts + nverts)); - OK(htable_seg_reserve(&scn->unique_segments, scn->nusegs + nsegs)); - - seg = darray_segment_in_cdata_get(&scn->segments_in); - - /* Get geometry */ - FOR_EACH(i, 0, nverts) { + darray_segment_enc_init(scn->dev->allocator, &scn->analyze.segments_enc); + darray_enclosure_init(scn->dev->allocator, &scn->analyze.enclosures); + darray_enc_ids_array_init(scn->dev->allocator, + &scn->analyze.enc_ids_array_by_medium); + darray_frontier_vertex_init(scn->dev->allocator, &scn->analyze.frontiers); + /* Enclosure 0 is always defined for infinite */ + OK(darray_enclosure_resize(&scn->analyze.enclosures, 1)); + scn->analyze.enclosures_count = 1; + + OK(darray_position_reserve(&scn->vertices, scn->nverts)); + OK(darray_segment_in_reserve(&scn->segments_in, scn->nsegs)); + OK(htable_vrtx_reserve(&unique_vertices, scn->nverts)); + OK(htable_seg_reserve(&unique_segments, scn->nsegs)); + + /* Get vertices */ + FOR_EACH(nv, 0, nverts) { vrtx_id_t* p_vrtx; union double2 tmp; - vrtx_id_t unique_v; - /* API: position needs an unsigned */ - position(i, tmp.vec, ctx); - p_vrtx = htable_vrtx_find(&scn->unique_vertices, &tmp); + position(nv, tmp.vec, ctx); + p_vrtx = htable_vrtx_find(&unique_vertices, &tmp); if(p_vrtx) { /* Duplicate vertex */ - unique_v = *p_vrtx; - } else { - /* New vertex */ - unique_v = scn->nuverts + actual_nuverts; - ASSERT(unique_v == htable_vrtx_size_get(&scn->unique_vertices)); - OK(darray_position_push_back(&scn->vertices, &tmp)); - OK(htable_vrtx_set(&scn->unique_vertices, &tmp, &unique_v)); - ++actual_nuverts; + log_err(scn->dev, "%s: vertex "PRTF_VRTX" is a duplicate.\n", + FUNC_NAME, nv); + res = RES_BAD_ARG; + goto error; } - /* The unique ID for vertex i is unique_v */ - ASSERT(i == darray_vrtx_id_size_get(&unique_vertice_ids)); - OK(darray_vrtx_id_push_back(&unique_vertice_ids, &unique_v)); - ++actual_nverts; + /* New vertex */ + ASSERT(nv == htable_vrtx_size_get(&unique_vertices)); + OK(darray_position_push_back(&scn->vertices, &tmp)); + OK(htable_vrtx_set(&unique_vertices, &tmp, &nv)); } - - FOR_EACH(i, 0, nsegs) { + /* Get segments */ + FOR_EACH(ns, 0, nsegs) { int j; - unsigned med[2] = { SENC2D_UNDEFINED_MEDIUM, SENC2D_UNDEFINED_MEDIUM }; - unsigned ind[2]; + seg_id_t s; + medium_id_t med[2] + = { SENC2D_UNSPECIFIED_MEDIUM, SENC2D_UNSPECIFIED_MEDIUM }; + vrtx_id_t ind[2]; union vrtx_id2 seg_key; - struct segment_in tmp, *range_adjust_ptr = NULL; + struct segment_in tmp; seg_id_t* p_seg; - char reversed; - /* Segment index in user world regardless of deduplication. */ - tmp.global_id = (unsigned)(scn->nsegs + i); - indices(i, ind, ctx); /* API: indices needs an unsigned */ + indices(ns, ind, ctx); FOR_EACH(j, 0, 2) { if(ind[j] >= nverts) { + log_err(scn->dev, + "%s: segment "PRTF_SEG" uses invalid vertex id "PRTF_VRTX".\n", + FUNC_NAME, ns, ind[j]); res = RES_BAD_ARG; goto error; } - ASSERT(ind[j] < darray_vrtx_id_size_get(&unique_vertice_ids)); - /* Find the unique ID for this vertex */ - tmp.vertice_id[j] = darray_vrtx_id_cdata_get(&unique_vertice_ids)[ind[j]]; + ASSERT(ind[j] <= VRTX_MAX__); + tmp.vertice_id[j] = ind[j]; } if(tmp.vertice_id[0] == tmp.vertice_id[1]) { - const union double2* positions - = darray_position_cdata_get(&scn->vertices); - log_err(scn->dev, "%s: segment %lu is degenerate.\n", - FUNC_NAME, (unsigned long)tmp.global_id); - log_err(scn->dev, " (%g %g) (%g %g)\n", - SPLIT2(positions[seg[i].vertice_id[0]].vec), - SPLIT2(positions[seg[i].vertice_id[1]].vec)); + log_err(scn->dev, "%s: segment "PRTF_SEG" is degenerated.\n", + FUNC_NAME, ns); res = RES_BAD_ARG; goto error; } /* Get media */ - if(media) media(i, med, ctx); /* API: media need unsigneds */ - FOR_EACH(j, 0, 2) { - if(med[j] != SENC2D_UNDEFINED_MEDIUM && med[j] >= scn->next_medium_idx) { - ASSERT(med[j] < MEDIUM_MAX__); - scn->next_medium_idx = 1 + med[j]; - darray_side_range_resize(&scn->media_use, scn->next_medium_idx); + if(media) { + media(ns, med, ctx); + for(s = SENC2D_FRONT; s <= SENC2D_BACK; s += SENC2D_BACK - SENC2D_FRONT) { + if(med[s] == SENC2D_UNSPECIFIED_MEDIUM || med[s] <= MEDIUM_MAX__) + continue; + res = RES_BAD_ARG; + goto error; } - tmp.medium[j] = (medium_id_t)med[j]; } - /* Find duplicate segments */ - reversed = seg_make_key(&seg_key, tmp.vertice_id); - p_seg = htable_seg_find(&scn->unique_segments, &seg_key); + seg_make_key(&seg_key, tmp.vertice_id); + p_seg = htable_seg_find(&unique_segments, &seg_key); if(p_seg) { - /* Duplicate segment. Need to check duplicate validity */ - union vrtx_id2 useg_key; - char ureversed = seg_make_key(&useg_key, seg[*p_seg].vertice_id); - int same = (reversed == ureversed); - const medium_id_t* umed; - ASSERT(seg_key_eq(&seg_key, &useg_key)); - if(!same) SWAP(unsigned, tmp.medium[0], tmp.medium[1]); - umed = seg[*p_seg].medium; - if(merge_segment) { - /* Let the client app rule. */ - unsigned smed[2], mmed[2]; - FOR_EACH(j, 0, 2) { - smed[j] = (unsigned)umed[j]; - mmed[j] = (unsigned)tmp.medium[j]; - } - OK(merge_segment(seg[*p_seg].global_id, i, same, smed, mmed, ctx)); - /* If merge_segment returns OK its OK even if media are incompatible. */ - } else { - if(!compatible_medium(umed[0], tmp.medium[0]) - || !compatible_medium(umed[1], tmp.medium[1])) - { - res = RES_BAD_ARG; - goto error; - } - } - /* Legit duplicate (or accepted by merge_segment): replace undef media. */ - range_adjust_ptr = darray_segment_in_data_get(&scn->segments_in) + *p_seg; - /* Replace possible undefined media */ - FOR_EACH(j, 0, 2) { - if(range_adjust_ptr->medium[j] == SENC2D_UNDEFINED_MEDIUM - && tmp.medium[j] != SENC2D_UNDEFINED_MEDIUM) { - range_adjust_ptr->medium[j] = tmp.medium[j]; - scn->sides_with_defined_medium_count++; - } - } - } else { - /* New segment */ - seg_id_t u = scn->nusegs + actual_nusegs; - if(add_segment) - OK(add_segment(tmp.global_id, i, ctx)); - OK(darray_segment_in_push_back(&scn->segments_in, &tmp)); - range_adjust_ptr = darray_segment_in_data_get(&scn->segments_in) + u; - FOR_EACH(j, 0, 2) { - if(tmp.medium[j] != SENC2D_UNDEFINED_MEDIUM) - scn->sides_with_defined_medium_count++; - } - ASSERT(u == htable_seg_size_get(&scn->unique_segments)); - OK(htable_seg_set(&scn->unique_segments, &seg_key, &u)); - ++actual_nusegs; + /* Duplicate segment */ + log_err(scn->dev, "%s: segment "PRTF_SEG" is a duplicate.\n", + FUNC_NAME, ns); + res = RES_BAD_ARG; + goto error; } - if(range_adjust_ptr) { - ptrdiff_t u = range_adjust_ptr - seg; - ASSERT(u < scn->nusegs + actual_nusegs && u < SEG_MAX__); - FOR_EACH(j, 0, 2) { - struct side_range* media_use; - if(tmp.medium[j] == SENC2D_UNDEFINED_MEDIUM) continue; - ASSERT(tmp.medium[j] < scn->next_medium_idx); - media_use = darray_side_range_data_get(&scn->media_use) + tmp.medium[j]; - media_use->first = - MMIN(media_use->first, SEGIDxSIDE_2_SEGSIDE((seg_id_t)u, j)); - ASSERT(media_use->first < 2 * (scn->nusegs + actual_nusegs + 1)); - media_use->last = - MMAX(media_use->last, SEGIDxSIDE_2_SEGSIDE((seg_id_t)u, j)); - ASSERT(media_use->last < 2 * (scn->nusegs + actual_nusegs + 1)); - ASSERT(media_use->first <= media_use->last); + /* New segment */ + ASSERT(ns == htable_seg_size_get(&unique_segments)); + OK(htable_seg_set(&unique_segments, &seg_key, &ns)); + for(s = SENC2D_FRONT; s <= SENC2D_BACK; s += SENC2D_BACK - SENC2D_FRONT) { + struct side_range* media_use; + size_t m_idx = medium_id_2_medium_idx(med[s]); + tmp.medium[s] = med[s]; + if(m_idx >= scn->next_medium_idx) { + medium_id_t medium; + medium = (medium_id_t)m_idx; + scn->next_medium_idx = medium; + OK(darray_side_range_resize(&scn->media_use, 1 + m_idx)); } + /* media_use 0 is for SENC2D_UNSPECIFIED_MEDIUM */ + media_use = darray_side_range_data_get(&scn->media_use) + m_idx; + media_use->first = + MMIN(media_use->first, SEGIDxSIDE_2_SEGSIDE(ns, s)); + ASSERT(media_use->first < 2 * (scn->nsegs + 1)); + media_use->last = + MMAX(media_use->last, SEGIDxSIDE_2_SEGSIDE(ns, s)); + ASSERT(media_use->last < 2 * (scn->nsegs + 1)); + ASSERT(media_use->first <= media_use->last); } - ++actual_nsegs; + OK(darray_segment_in_push_back(&scn->segments_in, &tmp)); } + OK(darray_enc_ids_array_resize(&scn->analyze.enc_ids_array_by_medium, + 1 + scn->next_medium_idx)); /* +1 is for undef */ + /* Proceed to the analyze */ + OK(scene_analyze(scn)); + exit: - darray_vrtx_id_release(&unique_vertice_ids); - /* Update sizes */ - scn->nuverts += actual_nuverts; - scn->nverts += actual_nverts; - scn->nusegs += actual_nusegs; - scn->nsegs += actual_nsegs; - ASSERT(scn->nuverts == htable_vrtx_size_get(&scn->unique_vertices)); - ASSERT(scn->nusegs == htable_seg_size_get(&scn->unique_segments)); + htable_vrtx_release(&unique_vertices); + htable_seg_release(&unique_segments); + if(scn) *out_scn = scn; return res; + error: + if(scn) { + SENC2D(scene_ref_put(scn)); + scn = NULL; + } goto exit; } @@ -325,13 +238,12 @@ senc2d_scene_get_convention if(!scn || !convention) return RES_BAD_ARG; *convention = scn->convention; return RES_OK; - } res_T senc2d_scene_get_segments_count (const struct senc2d_scene* scn, - unsigned* count) + seg_id_t* count) { if(!scn || !count) return RES_BAD_ARG; *count = scn->nsegs; @@ -339,31 +251,10 @@ senc2d_scene_get_segments_count } res_T -senc2d_scene_get_unique_segments_count - (const struct senc2d_scene* scn, - unsigned* count) -{ - if(!scn || !count) return RES_BAD_ARG; - *count = scn->nusegs; - return RES_OK; -} - -res_T -senc2d_scene_get_unique_sides_without_medium_count +senc2d_scene_get_segment (const struct senc2d_scene* scn, - unsigned* count) -{ - if(!scn || !count) return RES_BAD_ARG; - ASSERT(2 * scn->nusegs >= scn->sides_with_defined_medium_count); - *count = 2 * scn->nusegs - scn->sides_with_defined_medium_count; - return RES_OK; -} - -res_T -senc2d_scene_get_unique_segment - (const struct senc2d_scene* scn, - const unsigned iseg, - unsigned indices[2]) + const seg_id_t iseg, + vrtx_id_t indices[2]) { const struct segment_in* seg; int i; @@ -371,19 +262,15 @@ senc2d_scene_get_unique_segment || iseg >= darray_segment_in_size_get(&scn->segments_in)) return RES_BAD_ARG; seg = darray_segment_in_cdata_get(&scn->segments_in) + iseg; - - FOR_EACH(i, 0, 2) { - ASSERT(seg->vertice_id[i] < UINT_MAX); - indices[i] = (unsigned)seg->vertice_id[i]; /* Back to API type */ - } + FOR_EACH(i, 0, 2) indices[i] = seg->vertice_id[i]; return RES_OK; } res_T -senc2d_scene_get_unique_segment_media +senc2d_scene_get_segment_media (const struct senc2d_scene* scn, - const unsigned iseg, - unsigned media[2]) + const seg_id_t iseg, + medium_id_t media[2]) { const struct segment_in* seg; int i; @@ -391,18 +278,14 @@ senc2d_scene_get_unique_segment_media || iseg >= darray_segment_in_size_get(&scn->segments_in)) return RES_BAD_ARG; seg = darray_segment_in_cdata_get(&scn->segments_in) + iseg; - - FOR_EACH(i, 0, 2) { - ASSERT(seg->vertice_id[i] < UINT_MAX); - media[i] = (unsigned)seg->medium[i]; /* Back to API type */ - } + FOR_EACH(i, 0, 2) media[i] = seg->medium[i]; return RES_OK; } res_T senc2d_scene_get_vertices_count (const struct senc2d_scene* scn, - unsigned* count) + vrtx_id_t* count) { if(!scn || !count) return RES_BAD_ARG; *count = scn->nverts; @@ -410,27 +293,15 @@ senc2d_scene_get_vertices_count } res_T -senc2d_scene_get_unique_vertices_count +senc2d_scene_get_vertex (const struct senc2d_scene* scn, - unsigned* count) -{ - if(!scn || !count) return RES_BAD_ARG; - *count = scn->nuverts; - return RES_OK; -} - -res_T -senc2d_scene_get_unique_vertex - (const struct senc2d_scene* scn, - const unsigned ivert, + const vrtx_id_t ivert, double coord[2]) { - const union double2* v; if(!scn || !coord || ivert >= darray_position_size_get(&scn->vertices)) return RES_BAD_ARG; - v = darray_position_cdata_get(&scn->vertices) + ivert; d2_set(coord, v->vec); return RES_OK; diff --git a/src/senc2d_scene_analyze.c b/src/senc2d_scene_analyze.c @@ -14,14 +14,15 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "senc2d.h" -#include "senc2d_descriptor_c.h" #include "senc2d_device_c.h" #include "senc2d_scene_c.h" +#include "senc2d_enclosure_data.h" #include "senc2d_scene_analyze_c.h" #include "senc2d_internal_types.h" #include <rsys/rsys.h> #include <rsys/float2.h> +#include <rsys/double22.h> #include <rsys/mem_allocator.h> #include <rsys/hash_table.h> #include <rsys/dynamic_array.h> @@ -41,21 +42,21 @@ NULL\ } #ifdef COMPILER_GCC - #pragma GCC diagnostic push + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif const struct cc_descriptor CC_DESCRIPTOR_NULL = CC_DESCRIPTOR_NULL__; #ifdef COMPILER_GCC - #pragma GCC diagnostic pop + #pragma GCC diagnostic pop #endif #define DARRAY_NAME component_id #define DARRAY_DATA component_id_t #include <rsys/dynamic_array.h> -/******************************************************************************* +/****************************************************************************** * Helper function - ******************************************************************************/ + *****************************************************************************/ static INLINE int neighbour_cmp(const void* w1, const void* w2) { @@ -68,7 +69,7 @@ static side_id_t get_side_not_in_connex_component (const side_id_t last_side, const struct segside* segsides, - const unsigned char* processed, + const uchar* processed, side_id_t* first_side_not_in_component, const medium_id_t medium) { @@ -79,12 +80,14 @@ get_side_not_in_connex_component && (segsides[i].medium != medium || (processed[SEGSIDE_2_SEG(i)] & SEGSIDE_2_SIDEFLAG(i)))) ++i; + *first_side_not_in_component = i + 1; if(i > last_side) return SIDE_NULL__; return i; } } +/* Here unsigned are required by s2d API */ static void get_scn_indices(const unsigned iseg, unsigned ids[2], void* ctx) { int i; @@ -93,10 +96,12 @@ get_scn_indices(const unsigned iseg, unsigned ids[2], void* ctx) { darray_segment_in_cdata_get(&scene->segments_in) + iseg; FOR_EACH(i, 0, 2) { ASSERT(seg->vertice_id[i] < scene->nverts); - ids[i] = (unsigned)seg->vertice_id[i]; /* Back to API type */ + ASSERT(seg->vertice_id[i] <= UINT_MAX); + ids[i] = (unsigned)seg->vertice_id[i]; /* Back to s2d API type */ } } +/* Here unsigned are required by s2d API */ static void get_scn_position(const unsigned ivert, float pos[2], void* ctx) { const struct senc2d_scene* scene = ctx; @@ -128,7 +133,7 @@ self_hit_filter static void extract_connex_components - (struct senc2d_descriptor* desc, + (struct senc2d_scene* scn, struct segside* segsides, struct darray_ptr_component_descriptor* connex_components, const struct darray_segment_tmp* segments_tmp_array, @@ -141,67 +146,53 @@ extract_connex_components { /* This function is called from an omp parallel block and executed * concurrently. */ - struct senc2d_scene* scn; struct mem_allocator* alloc; - int64_t mm, undefs; + int64_t m_idx; /* OpenMP requires a signed type for the for loop variable */ struct darray_side_id stack; struct darray_side_id ids_of_sides_around_max_y_vertex; const union double2* positions; const struct segment_tmp* segments_tmp; struct segment_comp* segments_comp; /* An array to flag sides when processed */ - unsigned char* processed; + uchar* processed; /* An array to store the component being processed */ struct darray_side_id current_component; /* A bool array to store media of the component being processed */ - unsigned char* current_media = NULL; - size_t ii, sz; + uchar* current_media = NULL; + size_t sz, ii; - ASSERT(segsides && desc && connex_components && segments_tmp_array + ASSERT(scn && segsides && connex_components && segments_tmp_array && segments_comp_array && s2d_view && component_count && p_res); - alloc = descriptor_get_allocator(desc); - scn = desc->scene; + alloc = scn->dev->allocator; positions = darray_position_cdata_get(&scn->vertices); segments_tmp = darray_segment_tmp_cdata_get(segments_tmp_array); segments_comp = darray_segment_comp_data_get(segments_comp_array); darray_side_id_init(alloc, &stack); darray_side_id_init(alloc, &ids_of_sides_around_max_y_vertex); darray_side_id_init(alloc, &current_component); - processed = MEM_CALLOC(alloc, scn->nusegs, sizeof(unsigned char)); + processed = MEM_CALLOC(alloc, scn->nsegs, sizeof(uchar)); if(!processed) { *p_res = RES_MEM_ERR; return; } - /* If there are sides with undefined medium, its like another medium */ - undefs = (scn->sides_with_defined_medium_count < 2 * scn->nsegs) ? 1 : 0; - #pragma omp single - { - if(undefs) { - /* Range is unknown, process each side */ - struct side_range und; - und.first = 0; - und.last = 2 * scn->nsegs - 1; - darray_side_range_push_back(&scn->media_use, &und); - } - } /* Implicit barrier here */ - #ifndef NDEBUG #pragma omp single { seg_id_t s_; + int s; ASSERT(darray_ptr_component_descriptor_size_get(connex_components) == 0); - FOR_EACH(s_, 0, scn->nusegs) { + FOR_EACH(s_, 0, scn->nsegs) { const struct segment_in* seg_in = darray_segment_in_cdata_get(&scn->segments_in) + s_; const struct side_range* media_use = darray_side_range_cdata_get(&scn->media_use); - FOR_EACH(mm, 0, 2) { - const side_id_t side = SEGIDxSIDE_2_SEGSIDE(s_, mm); - medium_id_t medium = seg_in->medium[mm]; - if(medium == SENC2D_UNDEFINED_MEDIUM) medium = scn->next_medium_idx; - ASSERT(media_use[medium].first <= side && side - <= media_use[medium].last); + FOR_EACH(s, 0, 2) { + const side_id_t side = SEGIDxSIDE_2_SEGSIDE(s_, s); + medium_id_t medium = seg_in->medium[s]; + m_idx = medium_id_2_medium_idx(medium); + ASSERT(media_use[m_idx].first <= side && side + <= media_use[m_idx].last); } } } /* Implicit barrier here */ @@ -210,13 +201,12 @@ extract_connex_components /* We loop on sides to build connex components. */ #pragma omp for schedule(dynamic) nowait /* Process all media, including undef */ - for(mm = 0; mm < undefs + (int64_t)scn->next_medium_idx; mm++) { - const medium_id_t m_idx = (medium_id_t)mm; - const medium_id_t m = (mm == scn->next_medium_idx) - ? SENC2D_UNDEFINED_MEDIUM : (medium_id_t)mm; - /* Any not-already-used side is used as a starting point */ + for(m_idx = 0; m_idx < 1 + (int64_t)scn->next_medium_idx; m_idx++) { + const medium_id_t medium = medium_idx_2_medium_id(m_idx); + /* media_use 0 is for SENC2D_UNSPECIFIED_MEDIUM, n+1 is for n */ const struct side_range* media_use = darray_side_range_cdata_get(&scn->media_use) + m_idx; + /* Any not-already-used side is used as a starting point */ side_id_t first_side_not_in_component = media_use->first; double max_ny; side_id_t max_ny_side_id = SIDE_NULL__; @@ -228,20 +218,19 @@ extract_connex_components if(*p_res != RES_OK) continue; if(first_side_not_in_component == SIDE_NULL__) continue; /* Unused medium */ - ASSERT(first_side_not_in_component < 2 * scn->nusegs); + ASSERT(first_side_not_in_component < 2 * scn->nsegs); ASSERT(darray_side_id_size_get(&stack) == 0); ASSERT(darray_side_id_size_get(&current_component) == 0); for(;;) { /* Process all components for this medium */ const side_id_t start_side_id = get_side_not_in_connex_component - (last_side, segsides, processed, &first_side_not_in_component, m); + (last_side, segsides, processed, &first_side_not_in_component, medium); side_id_t crt_side_id = start_side_id; side_id_t last_side_id = start_side_id; vrtx_id_t max_y_vrtx_id = VRTX_NULL__; struct cc_descriptor *cc; double max_y = -DBL_MAX; component_canceled = 0; - - ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->nusegs); + ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->nsegs); darray_side_id_clear(&current_component); if(*p_res != RES_OK) break; @@ -253,16 +242,18 @@ extract_connex_components seg_id_t sid = SEGSIDE_2_SEG(start_side_id); enum senc2d_side s = SEGSIDE_2_SIDE(start_side_id); medium_id_t side_med - = darray_segment_in_data_get(&desc->scene->segments_in)[sid].medium[s]; - ASSERT(side_med == m); + = darray_segment_in_data_get(&scn->segments_in)[sid].medium[s]; + ASSERT(side_med == medium); } #endif /* Reuse array if possible, or create a new one */ if(current_media) { - memset(current_media, 0, scn->next_medium_idx); + /* current_media 0 is for SENC2D_UNSPECIFIED_MEDIUM, n+1 is for n */ + memset(current_media, 0, 1 + scn->next_medium_idx); } else { - current_media = MEM_CALLOC(alloc, 1 + scn->next_medium_idx, sizeof(unsigned char)); + current_media = MEM_CALLOC(alloc, 1 + scn->next_medium_idx, + sizeof(*current_media)); if(!current_media) { *p_res = RES_MEM_ERR; continue; @@ -276,11 +267,12 @@ extract_connex_components const seg_id_t crt_seg_id = SEGSIDE_2_SEG(crt_side_id); const struct segment_in* seg_in = darray_segment_in_cdata_get(&scn->segments_in) + crt_seg_id; - unsigned char* seg_used = processed + crt_seg_id; + uchar* seg_used = processed + crt_seg_id; const struct segment_tmp* const seg_tmp = segments_tmp + crt_seg_id; - ASSERT(crt_seg_id < scn->nusegs); + ASSERT(crt_seg_id < scn->nsegs); if(*p_res != RES_OK) break; + /* Record Ymax information * Keep track of the appropriate vertex of the component in order * to cast a ray at the component grouping step of the algorithm. @@ -293,12 +285,13 @@ extract_connex_components darray_side_id_clear(&ids_of_sides_around_max_y_vertex); /* Select a vertex with y == max_y */ - if(max_y == positions[seg_in->vertice_id[0]].pos.y) { - max_y_vrtx_id = seg_in->vertice_id[0]; - } else { - ASSERT(max_y == positions[seg_in->vertice_id[1]].pos.y); - max_y_vrtx_id = seg_in->vertice_id[1]; + FOR_EACH(i, 0, 2) { + if(max_y == positions[seg_in->vertice_id[i]].pos.y) { + max_y_vrtx_id = seg_in->vertice_id[i]; + break; + } } + ASSERT(i < 2); /* Found one */ /* List of sides using the vertex */ OK2(darray_side_id_push_back(&ids_of_sides_around_max_y_vertex, &crt_side_id)); @@ -317,42 +310,41 @@ extract_connex_components /* Record crt_side both as component and segment level */ if((*seg_used & crt_side_flag) == 0) { OK2(darray_side_id_push_back(&current_component, &crt_side_id)); - *seg_used = *seg_used |(unsigned char)crt_side_flag; + *seg_used = *seg_used | (uchar)crt_side_flag; } - /* Store neighbours' sides in a stack */ + /* Store neighbour's sides in a waiting stack */ FOR_EACH(i, 0, 2) { side_id_t neighbour_id = crt_side->facing_side_id[i]; seg_id_t nbour_seg_id = SEGSIDE_2_SEG(neighbour_id); enum side_flag nbour_side_id = SEGSIDE_2_SIDEFLAG(neighbour_id); - unsigned char* nbour_used = processed + nbour_seg_id; + uchar* nbour_used = processed + nbour_seg_id; const struct segside* neighbour = segsides + neighbour_id; - medium_id_t nbour_med_idx = (neighbour->medium == SENC2D_UNDEFINED_MEDIUM) - ? scn->next_medium_idx : neighbour->medium; - if(neighbour->medium < m + medium_id_t nbour_med_idx = medium_id_2_medium_idx(neighbour->medium); + if((int64_t)nbour_med_idx < m_idx || (*nbour_used & SIDE_CANCELED_FLAG(nbour_side_id))) { /* 1) Not the same medium. - * Neighbour's medium id is less than current medium: the whole + * Neighbour's medium idx is less than current medium: the whole * component is to be processed by another thread (possibly the one * associated with neighbour's medium). * 2) Neighbour was canceled: no need to replay the component * again as it will eventually rediscover the side with low medium - * id and recancel all the work in progress. */ + * id and recancel all the work in progress */ component_canceled = 1; darray_side_id_clear(&stack); - /* Don't cancel used flags as all these sides will get us back to + /* Don't cancel used flags as all these sides will get us back to * (at least) the neighbour side we have just discovered, that will * cancel them again and again */ sz = darray_side_id_size_get(&current_component); FOR_EACH(ii, 0, sz) { side_id_t used_side = darray_side_id_cdata_get(&current_component)[ii]; - seg_id_t used_trg_id = SEGSIDE_2_SEG(used_side); + seg_id_t used_seg_id = SEGSIDE_2_SEG(used_side); enum side_flag used_side_flag = SEGSIDE_2_SIDEFLAG(used_side); - unsigned char* used = processed + used_trg_id; - ASSERT(*used & (unsigned char)used_side_flag); + uchar* used = processed + used_seg_id; + ASSERT(*used & (uchar)used_side_flag); /* Set the used flag for sides in cancelled component as leading * to further cancellations */ *used |= SIDE_CANCELED_FLAG(used_side_flag); @@ -362,7 +354,7 @@ extract_connex_components } if(*nbour_used & nbour_side_id) continue; /* Already processed */ /* Mark neighbour as processed and stack it */ - *nbour_used |= (unsigned char)nbour_side_id; + *nbour_used |= (uchar)nbour_side_id; OK2(darray_side_id_push_back(&stack, &neighbour_id)); OK2(darray_side_id_push_back(&current_component, &neighbour_id)); current_media[nbour_med_idx] = 1; @@ -373,7 +365,7 @@ extract_connex_components darray_side_id_pop_back(&stack); last_side_id = MMAX(last_side_id, crt_side_id); } -canceled: + canceled: if(component_canceled) continue; /* Register the new component and get it initialized */ @@ -381,14 +373,14 @@ canceled: if(!cc) *p_res = RES_MEM_ERR; if(*p_res != RES_OK) break; - ASSERT(m == segsides[start_side_id].medium); + ASSERT(medium == segsides[start_side_id].medium); ASSERT(max_y_vrtx_id != VRTX_NULL__); cc_descriptor_init(alloc, cc); id = ATOMIC_INCR(component_count) - 1; ASSERT(id <= COMPONENT_MAX__); cc->cc_id = (component_id_t)id; sz = darray_side_id_size_get(&current_component); - ASSERT(sz <= SIDE_MAX__); + ASSERT(sz > 0 && sz <= SIDE_MAX__); cc->side_count = (side_id_t)sz; cc->side_range.first = start_side_id; cc->side_range.last = last_side_id; @@ -408,7 +400,8 @@ canceled: enum senc2d_side sid = SEGSIDE_2_SIDE(s); component_id_t* cmp = segments_comp[segid].component; ASSERT(cmp[sid] == COMPONENT_NULL__); - ASSERT(segsides[s].medium >= m); + ASSERT(medium_id_2_medium_idx(segsides[s].medium) + >= medium_id_2_medium_idx(medium)); cmp[sid] = cc->cc_id; } @@ -423,7 +416,7 @@ canceled: enum senc2d_side s = SEGSIDE_2_SIDE(side_id); const struct segment_in* seg_in = darray_segment_in_cdata_get(&scn->segments_in) + seg_id; - struct segment_comp* seg_comp = segments_comp + seg_id; + const struct segment_comp* seg_comp = segments_comp + seg_id; const union double2* vertices = darray_position_cdata_get(&scn->vertices); double edge[2], normal[2], norm; @@ -502,16 +495,16 @@ canceled: attribs.get = get_scn_position; /* Put geometry in a 2D view */ - OK(s2d_device_create(desc->scene->dev->logger, alloc, 0, &s2d)); + OK(s2d_device_create(scn->dev->logger, alloc, 0, &s2d)); OK(s2d_scene_create(s2d, &s2d_scn)); OK(s2d_shape_create_line_segments(s2d, &s2d_shp)); - /* Back to API type for nsegs and nverts */ - ASSERT(desc->scene->nusegs < UINT_MAX); - ASSERT(desc->scene->nuverts < UINT_MAX); + /* Back to s2d API type for nsegs and nverts */ + ASSERT(scn->nsegs <= UINT_MAX); + ASSERT(scn->nverts <= UINT_MAX); OK(s2d_line_segments_setup_indexed_vertices(s2d_shp, - (unsigned)desc->scene->nusegs, get_scn_indices, - (unsigned)desc->scene->nuverts, &attribs, 1, scn)); + (unsigned)scn->nsegs, get_scn_indices, + (unsigned)scn->nverts, &attribs, 1, scn)); s2d_line_segments_set_hit_filter_function(s2d_shp, self_hit_filter, segments_comp_array); OK(s2d_scene_attach_shape(s2d_scn, s2d_shp)); @@ -533,26 +526,24 @@ canceled: component_id_t c; ASSERT(ATOMIC_GET(component_count) == (int)darray_ptr_component_descriptor_size_get(connex_components)); - FOR_EACH(s_, 0, scn->nusegs) { - struct segment_comp* seg_comp = + FOR_EACH(s_, 0, scn->nsegs) { + struct segment_comp* seg_comp = darray_segment_comp_data_get(segments_comp_array) + s_; ASSERT(seg_comp->component[SENC2D_FRONT] != COMPONENT_NULL__); ASSERT(seg_comp->component[SENC2D_BACK] != COMPONENT_NULL__); } - FOR_EACH(c, 0, ATOMIC_GET(component_count)) { + FOR_EACH(c, 0, (component_id_t)ATOMIC_GET(component_count)) { struct cc_descriptor** components = darray_ptr_component_descriptor_data_get(connex_components); ASSERT(components[c] != NULL && components[c]->cc_id == c); } - ASSERT(desc->segment_count == scn->nusegs); } /* Implicit barrier here */ #endif } static void group_connex_components - (struct senc2d_descriptor* desc, - struct segside* segsides, + (struct senc2d_scene* scn, struct darray_segment_comp* segments_comp, struct darray_ptr_component_descriptor* connex_components, struct s2d_scene_view* s2d_view, @@ -569,16 +560,15 @@ group_connex_components component_id_t cc_count; int64_t ccc; - (void)segsides; - ASSERT(desc && segsides && segments_comp && connex_components - && s2d_view && next_enclosure_id && res); - ASSERT(desc->enclosures_count == 1); + ASSERT(scn && segments_comp && connex_components && s2d_view + && next_enclosure_id && res); + ASSERT(scn->analyze.enclosures_count == 1); descriptors = darray_ptr_component_descriptor_data_get(connex_components); tmp = darray_ptr_component_descriptor_size_get(connex_components); ASSERT(tmp <= COMPONENT_MAX__); cc_count = (component_id_t)tmp; - positions = darray_position_cdata_get(&desc->scene->vertices); + positions = darray_position_cdata_get(&scn->vertices); /* Cast rays to find links between connex components */ #pragma omp for schedule(dynamic) @@ -596,7 +586,7 @@ group_connex_components if(*res != RES_OK) continue; ASSERT(cc->cc_id == c); ASSERT(cc->cc_group_root == CC_GROUP_ID_NONE); - ASSERT(cc->max_y_vrtx_id < desc->scene->nverts); + ASSERT(cc->max_y_vrtx_id < scn->nverts); max_vrtx = positions[cc->max_y_vrtx_id].vec; if(cc->is_outer_border) { @@ -628,13 +618,13 @@ group_connex_components darray_segment_comp_cdata_get(segments_comp) + hit_seg_id; enum senc2d_side hit_side = ((hit.normal[1] < 0) /* Facing geometrical normal of hit */ - == ((desc->scene->convention & SENC2D_CONVENTION_NORMAL_FRONT) != 0)) + == ((scn->convention & SENC2D_CONVENTION_NORMAL_FRONT) != 0)) /* Warning: following Embree 2 convention for geometrical normals, - * the Star2D hit normal is left-handed while star-enclosure2D uses + * the Star2D hit normal is left-handed while star-enclosure uses * right-handed convention */ ? SENC2D_BACK : SENC2D_FRONT; ASSERT(hit.normal[1] != 0); - ASSERT(hit_seg_id < desc->scene->nusegs); + ASSERT(hit_seg_id < scn->nsegs); /* Not really the root until following links */ cc->cc_group_root = hit_seg_comp->component[hit_side]; @@ -642,29 +632,36 @@ group_connex_components } } /* Implicit barrier here */ - ASSERT(ATOMIC_GET(next_enclosure_id) < ENCLOSURE_MAX__); if(*res != RES_OK) return; /* One thread post-processes links to group connex components */ #pragma omp single { res_T tmp_res = RES_OK; - desc->enclosures_count = (enclosure_id_t)ATOMIC_GET(next_enclosure_id); - tmp_res = darray_enclosure_resize(&desc->enclosures, desc->enclosures_count); + size_t ec = (size_t)ATOMIC_GET(next_enclosure_id); + ASSERT(ec <= ENCLOSURE_MAX__); + scn->analyze.enclosures_count = (enclosure_id_t)ec; + tmp_res = darray_enclosure_resize(&scn->analyze.enclosures, + scn->analyze.enclosures_count); if(tmp_res != RES_OK) { *res = tmp_res; } else { struct enclosure_data* enclosures - = darray_enclosure_data_get(&desc->enclosures); - FOR_EACH(ccc, 0, cc_count) { + = darray_enclosure_data_get(&scn->analyze.enclosures); + FOR_EACH(ccc, 0, (int64_t)cc_count) { component_id_t c = (component_id_t)ccc; struct cc_descriptor* const cc = descriptors[c]; const struct cc_descriptor* other_desc = cc; struct enclosure_data* enc; +#ifndef NDEBUG + component_id_t cc_cpt = 0; +#endif while(other_desc->enclosure_id == CC_GROUP_ID_NONE) { - other_desc = *(darray_ptr_component_descriptor_cdata_get(connex_components) - + other_desc->cc_group_root); + ASSERT(other_desc->cc_group_root < cc_count); + other_desc = descriptors[other_desc->cc_group_root]; + /* Cannot have more components in cc than cc_count! */ + ASSERT(++cc_cpt <= cc_count); } ASSERT(other_desc->cc_group_root != CC_GROUP_ROOT_NONE); ASSERT(other_desc->enclosure_id != CC_GROUP_ID_NONE); @@ -678,7 +675,7 @@ group_connex_components enc->side_range.last = MMAX(enc->side_range.last, cc->side_range.last); enc->side_count += cc->side_count; tmp_res = bool_array_of_media_merge(&enc->tmp_enclosed_media, cc->media, - desc->scene->next_medium_idx + 1); + scn->next_medium_idx + 1); if(tmp_res != RES_OK) { *res = tmp_res; break; @@ -694,52 +691,54 @@ collect_and_link_neighbours (struct senc2d_scene* scn, struct segside* segsides, struct darray_segment_tmp* segments_tmp_array, - struct darray_neighbourhood* neighbourhood_by_vertex, - struct darray_vrtx_id* frontiers, + struct darray_frontier_vertex* frontiers, /* Shared error status. * We accept to overwrite an error with a different error */ res_T* res) { /* This function is called from an omp parallel block and executed - * concurrently. - * Resize / Push operations on neighbourhood_by_vertex are valid - * because each neighbourhood is processes by an unique thread */ + * concurrently. */ const struct segment_in* segments_in; struct segment_tmp* segments_tmp; const union double2* vertices; const int thread_count = omp_get_num_threads(); const int rank = omp_get_thread_num(); + /* Array to keep neighbourhood of vertices + * Resize/Push operations on neighbourhood_by_vertex are valid in the + * openmp block because a given neighbourhood is only processed + * by a single thread */ + struct darray_neighbourhood neighbourhood_by_vertex; vrtx_id_t v; seg_id_t s; + res_T tmp_res; - ASSERT(scn && segsides && segments_tmp_array - && neighbourhood_by_vertex && frontiers && res); - ASSERT((size_t)scn->nuverts + (size_t)scn->nusegs + 2 <= EDGE_MAX__); + ASSERT(scn && segsides && segments_tmp_array && frontiers && res); + ASSERT((size_t)scn->nverts + (size_t)scn->nsegs + 2 <= EDGE_MAX__); + + darray_neighbourhood_init(scn->dev->allocator, &neighbourhood_by_vertex); + OK2(darray_neighbourhood_resize(&neighbourhood_by_vertex, scn->nverts)); segments_in = darray_segment_in_cdata_get(&scn->segments_in); segments_tmp = darray_segment_tmp_data_get(segments_tmp_array); vertices = darray_position_cdata_get(&scn->vertices); - ASSERT(scn->nusegs == darray_segment_tmp_size_get(segments_tmp_array)); + ASSERT(scn->nsegs == darray_segment_tmp_size_get(segments_tmp_array)); /* Loop on segments to collect edges' neighbours. * All threads considering all the vertices and processing some */ - FOR_EACH(s, 0, scn->nusegs) { - unsigned char vv; + FOR_EACH(s, 0, scn->nsegs) { + uchar vv; FOR_EACH(vv, 0, 2) { struct darray_neighbour* neighbourhood; struct neighbour_info* info; const vrtx_id_t vertex = segments_in[s].vertice_id[vv]; size_t sz; - res_T tmp_res = RES_OK; - ASSERT(vertex < scn->nuverts); - if(*res != RES_OK) continue; /* Process only "my" vertices! */ if((int64_t)vertex % thread_count != rank) continue; /* Find neighbourhood */ - ASSERT(vertex < darray_neighbourhood_size_get(neighbourhood_by_vertex)); + ASSERT(vertex < darray_neighbourhood_size_get(&neighbourhood_by_vertex)); neighbourhood = - darray_neighbourhood_data_get(neighbourhood_by_vertex) + vertex; + darray_neighbourhood_data_get(&neighbourhood_by_vertex) + vertex; sz = darray_neighbour_size_get(neighbourhood); /* Make room for this neighbour */ if(darray_neighbour_capacity(neighbourhood) == sz) { @@ -771,7 +770,7 @@ collect_and_link_neighbours /* For each of "my" vertices sort segments sides by rotation angle * and connect neighbours. * All threads considering all the vertices and processing some */ - FOR_EACH(v, 0, scn->nuverts) { + FOR_EACH(v, 0, scn->nverts) { const vrtx_id_t common_vrtx = v; vrtx_id_t other_vrtx; struct darray_neighbour* neighbourhood; @@ -781,7 +780,7 @@ collect_and_link_neighbours /* Process only "my" neighbourhoods! */ if((int64_t)v % thread_count != rank) continue; neighbourhood - = darray_neighbourhood_data_get(neighbourhood_by_vertex) + v; + = darray_neighbourhood_data_get(&neighbourhood_by_vertex) + v; sz = darray_neighbour_size_get(neighbourhood); /* sz can be 0 as a vertex can be unused */ if(!sz) continue; @@ -793,7 +792,6 @@ collect_and_link_neighbours = darray_neighbour_data_get(neighbourhood) + i; const struct segment_in* seg_in = segments_in + neighbour_info->seg_id; struct segment_tmp* neighbour = segments_tmp + neighbour_info->seg_id; - union double2 n; /* Geometrical normal to neighbour segment */ const int is_reversed = neighbour_info->common_vertex_rank; @@ -833,8 +831,8 @@ collect_and_link_neighbours /* Sort segments by rotation angle */ qsort(darray_neighbour_data_get(neighbourhood), neighbour_count, sizeof(struct neighbour_info), neighbour_cmp); - /* Link sides. - * Create cycles of sides by neighbourhood around common vertex. */ + /* Link sides. + * Create cycles of sides by neighbourhood around common vertex. */ a = -DBL_MAX; FOR_EACH(i, 0, neighbour_count) { /* Neighbourhood info for current pair of segments */ @@ -843,11 +841,11 @@ collect_and_link_neighbours const struct neighbour_info* ccw_neighbour = darray_neighbour_cdata_get(neighbourhood) + (i + 1) % neighbour_count; /* Rank of the end of interest in segments */ - const unsigned char crt_end = current->common_vertex_rank; + const uchar crt_end = current->common_vertex_rank; /* Here ccw refers to the rotation around the common vertex * and has nothing to do with vertices order in segment definition * nor Front/Back side convention */ - const unsigned char ccw_end = ccw_neighbour->common_vertex_rank; + const uchar ccw_end = ccw_neighbour->common_vertex_rank; /* User id of current segments */ const seg_id_t crt_id = current->seg_id; const seg_id_t ccw_id = ccw_neighbour->seg_id; @@ -857,7 +855,7 @@ collect_and_link_neighbours = current->normal_toward_next_neighbour == front ? SENC2D_FRONT : SENC2D_BACK; const enum senc2d_side ccw_side = ccw_neighbour->normal_toward_next_neighbour == front ? - SENC2D_BACK : SENC2D_FRONT; + SENC2D_BACK : SENC2D_FRONT; /* Index of sides in segsides */ const side_id_t crt_side_idx = SEGIDxSIDE_2_SEGSIDE(crt_id, crt_side); const side_id_t ccw_side_idx = SEGIDxSIDE_2_SEGSIDE(ccw_id, ccw_side); @@ -874,11 +872,10 @@ collect_and_link_neighbours previous = darray_neighbour_cdata_get(neighbourhood) + i - 1; prev_id = previous->seg_id; log_err(scn->dev, - "%s: found 2 overlying segments (%lu & %lu).\n", FUNC_NAME, - (unsigned long)segments_in[crt_id].global_id, - (unsigned long)segments_in[prev_id].global_id); - *res = RES_BAD_OP; - return; + "%s: found 2 overlying segments ("PRTF_SEG" & "PRTF_SEG").\n", + FUNC_NAME, crt_id, prev_id); + tmp_res = RES_BAD_OP; + goto tmp_error; } a = current->angle; /* Link sides */ @@ -893,25 +890,28 @@ collect_and_link_neighbours || p_ccw_side->medium == segments_in[ccw_id].medium[ccw_side]); p_crt_side->medium = segments_in[crt_id].medium[crt_side]; p_ccw_side->medium = segments_in[ccw_id].medium[ccw_side]; - ASSERT(p_crt_side->medium == SENC2D_UNDEFINED_MEDIUM + ASSERT(p_crt_side->medium == SENC2D_UNSPECIFIED_MEDIUM || p_crt_side->medium < scn->next_medium_idx); - ASSERT(p_ccw_side->medium == SENC2D_UNDEFINED_MEDIUM + ASSERT(p_ccw_side->medium == SENC2D_UNSPECIFIED_MEDIUM || p_ccw_side->medium < scn->next_medium_idx); /* Detect segments that could surround a hole: - * - single segments on (one of) its end + * - single segment on (one of) its end * - different media on its sides */ if(neighbour_count == 1 && p_crt_side->medium != p_ccw_side->medium) #pragma omp critical { - log_warn(scn->dev, - "%s: found possible frontier involving segment %lu.\n", - FUNC_NAME, (unsigned long)segments_in[crt_id].global_id); - darray_vrtx_id_push_back(frontiers, &v); + struct frontier_vertex frontier_vertex; + frontier_vertex.seg = crt_id; + frontier_vertex.vrtx = v; + darray_frontier_vertex_push_back(frontiers, &frontier_vertex); } } } +tmp_error: + if(tmp_res != RES_OK) *res = tmp_res; /* Threads are allowed to return whitout sync. */ + darray_neighbourhood_release(&neighbourhood_by_vertex); } static int @@ -926,10 +926,10 @@ compare_enclosures static void build_result - (struct senc2d_descriptor* desc, + (struct senc2d_scene* scn, const struct darray_ptr_component_descriptor* connex_components, const struct darray_segment_comp* segments_comp_array, - struct darray_vrtx_id* frontiers, + struct darray_frontier_vertex* frontiers, enclosure_id_t* ordered_ids, /* Shared error status. * We accept to overwrite an error with a different error */ @@ -944,46 +944,45 @@ build_result struct segment_enc* segments_enc; const struct segment_comp* segments_comp; struct htable_vrtx_id vtable; - struct senc2d_scene* scn; int output_normal_in, normals_front, normals_back; int64_t sg; int64_t ee; - ASSERT(desc && connex_components && segments_comp_array && frontiers && res); + ASSERT(scn && connex_components && segments_comp_array && frontiers && res); - alloc = descriptor_get_allocator(desc); - scn = desc->scene; + alloc = scn->dev->allocator; output_normal_in = (scn->convention & SENC2D_CONVENTION_NORMAL_INSIDE) != 0; normals_front = (scn->convention & SENC2D_CONVENTION_NORMAL_FRONT) != 0; normals_back = (scn->convention & SENC2D_CONVENTION_NORMAL_BACK) != 0; ASSERT(normals_back != normals_front); - ASSERT(output_normal_in != - ((scn->convention & SENC2D_CONVENTION_NORMAL_OUTSIDE) != 0)); + ASSERT(output_normal_in + != ((scn->convention & SENC2D_CONVENTION_NORMAL_OUTSIDE) != 0)); ASSERT(darray_ptr_component_descriptor_size_get(connex_components) <= COMPONENT_MAX__); cc_descriptors = darray_ptr_component_descriptor_cdata_get(connex_components); - enclosures = darray_enclosure_data_get(&desc->enclosures); + enclosures = darray_enclosure_data_get(&scn->analyze.enclosures); segments_in = darray_segment_in_cdata_get(&scn->segments_in); segments_comp = darray_segment_comp_cdata_get(segments_comp_array); + #pragma omp single { enclosure_id_t e; size_t d; res_T tmp_res = - darray_segment_enc_resize(&desc->segments_enc, scn->nusegs); + darray_segment_enc_resize(&scn->analyze.segments_enc, scn->nsegs); if(tmp_res != RES_OK) { *res = tmp_res; goto single_err; } /* Store initial enclosure order */ - FOR_EACH(e, 0, desc->enclosures_count) + FOR_EACH(e, 0, scn->analyze.enclosures_count) enclosures[e].header.enclosure_id = e; /* Move enclosures by first side while keeping enclosure 0 * at rank 0 (its a convention) */ - qsort(enclosures + 1, desc->enclosures_count - 1, + qsort(enclosures + 1, scn->analyze.enclosures_count - 1, sizeof(*enclosures), compare_enclosures); /* Make conversion table */ - FOR_EACH(e, 0, desc->enclosures_count) { + FOR_EACH(e, 0, scn->analyze.enclosures_count) { enclosure_id_t rank = enclosures[e].header.enclosure_id; ordered_ids[rank] = e; } @@ -994,11 +993,11 @@ build_result single_err: (void)0; }/* Implicit barrier here. */ if(*res != RES_OK) goto exit; - segments_enc = darray_segment_enc_data_get(&desc->segments_enc); + segments_enc = darray_segment_enc_data_get(&scn->analyze.segments_enc); /* Build global enclosure information */ #pragma omp for - for(sg = 0; sg < (int64_t)scn->nusegs; sg++) { + for(sg = 0; sg < (int64_t)scn->nsegs; sg++) { seg_id_t s = (seg_id_t)sg; const component_id_t cf_id = segments_comp[s].component[SENC2D_FRONT]; const component_id_t cb_id = segments_comp[s].component[SENC2D_BACK]; @@ -1017,9 +1016,9 @@ build_result * openmp block as a given enclosure is processed by a single thread */ htable_vrtx_id_init(alloc, &vtable); - ASSERT(desc->enclosures_count <= ENCLOSURE_MAX__); + ASSERT(scn->analyze.enclosures_count <= ENCLOSURE_MAX__); #pragma omp for schedule(dynamic) nowait - for(ee = 0; ee < (int64_t)desc->enclosures_count; ee++) { + for(ee = 0; ee < (int64_t)scn->analyze.enclosures_count; ee++) { const enclosure_id_t e = (enclosure_id_t)ee; struct enclosure_data* enc = enclosures + e; seg_id_t fst_idx = 0; @@ -1035,32 +1034,31 @@ build_result if(*res != RES_OK) continue; ASSERT(e <= ENCLOSURE_MAX__); enc->header.enclosure_id = (unsigned)ee; /* Back to API type */ - ASSERT(cc_descriptors[enc->first_component]->enclosure_id + ASSERT(cc_descriptors[enc->first_component]->enclosure_id == enc->header.enclosure_id); enc->header.is_infinite = (e == 0); - ASSERT(darray_uchar_size_get(&enc->tmp_enclosed_media) <= UINT_MAX); ASSERT(enc->header.enclosed_media_count < 1 + scn->next_medium_idx); OK2(bool_array_of_media_to_darray_media (&enc->enclosed_media, &enc->tmp_enclosed_media, scn->next_medium_idx)); + ASSERT(darray_media_size_get(&enc->enclosed_media) <= MEDIUM_MAX__); enc->header.enclosed_media_count - = (unsigned)darray_media_size_get(&enc->enclosed_media); + = (medium_id_t)darray_media_size_get(&enc->enclosed_media); darray_uchar_purge(&enc->tmp_enclosed_media); /* Add this enclosure in relevant by-medium lists */ FOR_EACH(m, 0, enc->header.enclosed_media_count) { - medium_id_t medium = darray_media_data_get(&enc->enclosed_media)[m]; - size_t m_idx = (medium == SENC2D_UNDEFINED_MEDIUM) - ? scn->next_medium_idx : medium; - struct darray_enc_id* enc_ids_by_medium; - ASSERT(medium == SENC2D_UNDEFINED_MEDIUM || medium < scn->next_medium_idx); - ASSERT(darray_enc_ids_array_size_get(&desc->enc_ids_array_by_medium) + medium_id_t medium = darray_media_cdata_get(&enc->enclosed_media)[m]; + size_t m_idx = medium_id_2_medium_idx(medium); + struct darray_enc_id* enc_ids_array_by_medium; + ASSERT(medium == SENC2D_UNSPECIFIED_MEDIUM || medium < scn->next_medium_idx); + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) == 1 + scn->next_medium_idx); - enc_ids_by_medium = - darray_enc_ids_array_data_get(&desc->enc_ids_array_by_medium) + m_idx; + enc_ids_array_by_medium = + darray_enc_ids_array_data_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; #pragma omp critical { - tmp_res = darray_enc_id_push_back(enc_ids_by_medium, &e); + tmp_res = darray_enc_id_push_back(enc_ids_array_by_medium, &e); } if(tmp_res != RES_OK) { *res = tmp_res; @@ -1072,10 +1070,11 @@ build_result /* Build side and vertex lists. */ OK2(darray_sides_enc_resize(&enc->sides, enc->side_count)); /* Size is just a int */ - OK2(darray_vrtx_id_reserve(&enc->vertices, enc->side_count + 1)); + OK2(darray_vrtx_id_reserve(&enc->vertices, + (size_t)(enc->side_count * 0.6))); /* New vertex numbering scheme local to the enclosure */ htable_vrtx_id_clear(&vtable); - ASSERT(scn->nusegs == darray_segment_in_size_get(&scn->segments_in)); + ASSERT(scn->nsegs == darray_segment_in_size_get(&scn->segments_in)); /* Put at the end the back-faces of segments that also have their * front-face in the list. */ for(s = SEGSIDE_2_SEG(enc->side_range.first); @@ -1084,12 +1083,12 @@ build_result { const struct segment_in* seg_in = segments_in + s; struct side_enc* side_enc; - unsigned vertice_id[2]; + vrtx_id_t vertice_id[2]; int i; if(segments_enc[s].enclosure[SENC2D_FRONT] != e && segments_enc[s].enclosure[SENC2D_BACK] != e) continue; - ++enc->header.unique_segment_count; + ++enc->header.unique_primitives_count; FOR_EACH(i, 0, 2) { vrtx_id_t* p_id = htable_vrtx_id_find(&vtable, seg_in->vertice_id + i); @@ -1113,19 +1112,19 @@ build_result /* Front side of the original segment is member of the enclosure */ int input_normal_in = normals_front; int revert_segment = (input_normal_in != output_normal_in); - ++enc->header.segment_count; + ++enc->header.primitives_count; side_enc = darray_sides_enc_data_get(&enc->sides) + fst_idx++; FOR_EACH(i, 0, 2) { int ii = revert_segment ? 1 - i : i; side_enc->vertice_id[i] = vertice_id[ii]; } - side_enc->side_id = SEGIDxSIDE_2_SEGSIDE(seg_in->global_id, SENC2D_FRONT); + side_enc->side_id = SEGIDxSIDE_2_SEGSIDE(s, SENC2D_FRONT); } if(segments_enc[s].enclosure[SENC2D_BACK] == e) { /* Back side of the original segment is member of the enclosure */ int input_normal_in = normals_back; int revert_segment = (input_normal_in != output_normal_in); - ++enc->header.segment_count; + ++enc->header.primitives_count; /* If both sides are in the enclosure, put the second side at the end */ side_enc = darray_sides_enc_data_get(&enc->sides) + ((segments_enc[s].enclosure[SENC2D_FRONT] == e) ? --sgd_idx : fst_idx++); @@ -1133,7 +1132,7 @@ build_result int ii = revert_segment ? 1 - i : i; side_enc->vertice_id[i] = vertice_id[ii]; } - side_enc->side_id = SEGIDxSIDE_2_SEGSIDE(seg_in->global_id, SENC2D_BACK); + side_enc->side_id = SEGIDxSIDE_2_SEGSIDE(s, SENC2D_BACK); } if(fst_idx == sgd_idx) break; } @@ -1145,21 +1144,19 @@ build_result htable_vrtx_id_release(&vtable); /* The first thread here copies frontiers into descriptor */ #pragma omp single nowait - darray_vrtx_id_copy_and_clear(&desc->frontiers, frontiers); + darray_frontier_vertex_copy_and_clear(&scn->analyze.frontiers, frontiers); /* No barrier here */ exit: return; } -/******************************************************************************* +/****************************************************************************** * Exported functions - ******************************************************************************/ + *****************************************************************************/ res_T -senc2d_scene_analyze - (struct senc2d_scene* scn, - struct senc2d_descriptor** out_desc) +scene_analyze + (struct senc2d_scene* scn) { - struct senc2d_descriptor* desc = NULL; /* By segment tmp data */ struct darray_segment_tmp segments_tmp; char segments_tmp_initialized = 0; @@ -1167,72 +1164,54 @@ senc2d_scene_analyze * They are refered to by arrays of ids. */ struct darray_ptr_component_descriptor connex_components; char connex_components_initialized = 0; - /* Array of frontiers vertices */ - struct darray_vrtx_id frontiers; + /* Array of frontier vertices */ + struct darray_frontier_vertex frontiers; char frontiers_initialized = 0; /* Store by-segment components */ struct darray_segment_comp segments_comp; char segments_comp_initialized = 0; - /* Array of vertices (segment ends). */ + /* Array of segment ends. */ struct segside* segsides = NULL; struct s2d_scene_view* s2d_view = NULL; - /* Array to keep neighbourhood of vertices */ - struct darray_neighbourhood neighbourhood_by_vertex; - char neighbourhood_by_vertex_initialized = 0; /* Atomic counters to share beetwen threads */ ATOMIC component_count = 0; ATOMIC next_enclosure_id = 1; enclosure_id_t* ordered_ids = NULL; res_T res = RES_OK; res_T res2 = RES_OK; + + if(!scn) return RES_BAD_ARG; - if(!scn || !out_desc) return RES_BAD_ARG; - - /* The first part of the analyze is single threaded */ - desc = descriptor_create(scn); - if(!desc) { - res = RES_MEM_ERR; - goto error; - } - - if(!scn->nusegs) goto exit; + if(!scn->nsegs) goto exit; darray_segment_tmp_init(scn->dev->allocator, &segments_tmp); segments_tmp_initialized = 1; - darray_vrtx_id_init(scn->dev->allocator, &frontiers); + darray_frontier_vertex_init(scn->dev->allocator, &frontiers); frontiers_initialized = 1; - OK(darray_segment_tmp_resize(&segments_tmp, scn->nusegs)); + OK(darray_segment_tmp_resize(&segments_tmp, scn->nsegs)); segsides - = MEM_CALLOC(scn->dev->allocator, 2 * scn->nusegs, sizeof(struct segside)); + = MEM_CALLOC(scn->dev->allocator, 2 * scn->nsegs, sizeof(struct segside)); if(!segsides) { res = RES_MEM_ERR; goto error; } #ifndef NDEBUG else { - /* Initialise trgsides to allow assert code */ + /* Initialise segsides to allow assert code */ size_t i; - FOR_EACH(i, 0, 2 * scn->nusegs) - init_segside(scn->dev->allocator, segsides + i); + FOR_EACH(i, 0, 2 * scn->nsegs) + init_segside(scn->dev->allocator, segsides + i); } #endif - - /* We create a neighbourhood for every single unique vertex, - * regardless the fact it is used by a segment. - * This allows threads to use these neighbourhoods whithout sync. */ - darray_neighbourhood_init(scn->dev->allocator, &neighbourhood_by_vertex); - neighbourhood_by_vertex_initialized = 1; - OK(darray_neighbourhood_resize(&neighbourhood_by_vertex, scn->nuverts)); - /* The end of the analyze is multithreaded */ ASSERT(scn->dev->nthreads > 0); #pragma omp parallel num_threads(scn->dev->nthreads) { /* Step 1: build neighbourhoods */ - collect_and_link_neighbours(scn, segsides, &segments_tmp, - &neighbourhood_by_vertex, &frontiers, &res); + collect_and_link_neighbours(scn, segsides, &segments_tmp, &frontiers, + &res); /* No barrier at the end of step 1: data used in step 1 cannot be * released / data produced by step 1 cannot be used * until next sync point */ @@ -1242,7 +1221,6 @@ senc2d_scene_analyze #pragma omp single { res_T tmp_res = RES_OK; - darray_ptr_component_descriptor_init(scn->dev->allocator, &connex_components); connex_components_initialized = 1; @@ -1251,14 +1229,14 @@ senc2d_scene_analyze 2 + 2 * scn->next_medium_idx)); darray_segment_comp_init(scn->dev->allocator, &segments_comp); segments_comp_initialized = 1; - OK2(darray_segment_comp_resize(&segments_comp, scn->nusegs)); + OK2(darray_segment_comp_resize(&segments_comp, scn->nsegs)); tmp_error: if(tmp_res != RES_OK) res2 = tmp_res; } /* Implicit barrier here: constraints on step 1 data are now met */ if(res != RES_OK || res2 != RES_OK) { - #pragma omp single nowait + #pragma omp single nowait { if(res != RES_OK) { log_err(scn->dev, @@ -1270,16 +1248,8 @@ senc2d_scene_analyze goto error_; } - /* One thread releases some data before going to step 2, - * the others go to step 2 without sync */ - #pragma omp single nowait - { - darray_neighbourhood_release(&neighbourhood_by_vertex); - neighbourhood_by_vertex_initialized = 0; - } /* No barrier here */ - /* Step 2: extract segment connex components */ - extract_connex_components(desc, segsides, &connex_components, + extract_connex_components(scn, segsides, &connex_components, &segments_tmp, &segments_comp, &s2d_view, &component_count, &res); /* No barrier at the end of step 2: data used in step 2 cannot be * released / data produced by step 2 cannot be used @@ -1287,7 +1257,7 @@ senc2d_scene_analyze #pragma omp barrier /* Constraints on step 2 data are now met */ - + if(res != RES_OK) { #pragma omp single nowait { @@ -1306,8 +1276,8 @@ senc2d_scene_analyze } /* No barrier here */ /* Step 3: group components */ - group_connex_components(desc, segsides, &segments_comp, &connex_components, - s2d_view, &next_enclosure_id, &res); + group_connex_components(scn, &segments_comp, &connex_components, s2d_view, + &next_enclosure_id, &res); /* Barrier at the end of step 3: data used in step 3 can be released / * data produced by step 3 can be used */ @@ -1327,20 +1297,20 @@ senc2d_scene_analyze if(s2d_view) S2D(scene_view_ref_put(s2d_view)); s2d_view = NULL; ordered_ids = MEM_ALLOC(scn->dev->allocator, - sizeof(*ordered_ids) * desc->enclosures_count); + sizeof(*ordered_ids) * scn->analyze.enclosures_count); if(!ordered_ids) res = RES_MEM_ERR; } /* Implicit barrier here */ if(res != RES_OK) goto error_; /* Step 4: Build result */ - build_result(desc, &connex_components, &segments_comp, &frontiers, + build_result(scn, &connex_components, &segments_comp, &frontiers, ordered_ids, &res); /* No barrier at the end of step 4: data used in step 4 cannot be * released / data produced by step 4 cannot be used * until next sync point */ #pragma omp barrier - /* Constraints on step 4 data are now met */ + /* Constraints on step 4 data are now met */ if(res != RES_OK) { #pragma omp single nowait @@ -1370,22 +1340,18 @@ error_: ; } /* Implicit barrier here */ -if(res != RES_OK) goto error; + if(res != RES_OK) goto error; exit: if(connex_components_initialized) custom_darray_ptr_component_descriptor_release(&connex_components); if(s2d_view) S2D(scene_view_ref_put(s2d_view)); - if(neighbourhood_by_vertex_initialized) - darray_neighbourhood_release(&neighbourhood_by_vertex); if(segments_tmp_initialized) darray_segment_tmp_release(&segments_tmp); if(segments_comp_initialized) darray_segment_comp_release(&segments_comp); - if(frontiers_initialized) darray_vrtx_id_release(&frontiers); + if(frontiers_initialized) + darray_frontier_vertex_release(&frontiers); if(segsides) MEM_RM(scn->dev->allocator, segsides); - if(desc) *out_desc = desc; return res; error: - if(desc) SENC2D(descriptor_ref_put(desc)); - desc = NULL; goto exit; } diff --git a/src/senc2d_scene_analyze.c.save b/src/senc2d_scene_analyze.c.save @@ -1,1254 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2018 (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 "senc2d.h" -#include "senc2d_descriptor_c.h" -#include "senc2d_device_c.h" -#include "senc2d_scene_c.h" -#include "senc2d_scene_analyze_c.h" -#include "senc2d_internal_types.h" - -#include <rsys/rsys.h> -#include <rsys/float2.h> -#include <rsys/mem_allocator.h> -#include <rsys/hash_table.h> -#include <rsys/dynamic_array.h> - -#if defined(COMPILER_GCC) -#define ATOMIC_CAS_PTR(Atom, NewVal, Comparand) /* Return the initial value */ \ - ATOMIC_CAS((Atom), (NewVal), (Comparand)) -#elif defined(COMPILER_CL) -#define ATOMIC_CAS_PTR(Atom, NewVal, Comparand) /* Return the initial value */ \ - (InterlockedCompareExchangePointer(Atom, NewVal, Comparand)) -#else -#error "Undefined atomic operations" -#endif - -#include <star/s2d.h> - -#include <omp.h> -#include <limits.h> -#include <stdlib.h> - -#define CC_DESCRIPTOR_NULL__ {\ - {0,-DBL_MAX}, -1, SIDE_NULL__, VRTX_NULL__, 0, MEDIUM_NULL__,\ - CC_ID_NONE, CC_GROUP_ROOT_NONE, CC_GROUP_ID_NONE, CC_ID_NONE,\ - { SEG_NULL__, 0}\ -} -const struct cc_descriptor CC_DESCRIPTOR_NULL = CC_DESCRIPTOR_NULL__; - -#define DARRAY_NAME component_id -#define DARRAY_DATA component_id_t -#include <rsys/dynamic_array.h> - -#define DARRAY_NAME side_id -#define DARRAY_DATA side_id_t -#include <rsys/dynamic_array.h> - -/******************************************************************************* - * Helper function - ******************************************************************************/ -static INLINE int -find_side_in_list - (const struct segside* segsides, - const struct darray_side_id* side_ids, - const side_id_t side_id, - const enum list_id list_id) -{ - side_id_t i; - size_t tmp; - (void)list_id; - (void)segsides; - ASSERT(segsides && side_ids); - tmp = darray_side_id_size_get(side_ids); - ASSERT(tmp <= SIDE_MAX__); - FOR_EACH(i, 0, (side_id_t)tmp) { - const side_id_t id = darray_side_id_cdata_get(side_ids)[i]; - ASSERT(segsides[id].list_id & list_id); - if(id == side_id) return 1; - } - return 0; -} - -static INLINE int -neighbour_cmp(const void* w1, const void* w2) -{ - const double a1 = ((struct neighbour_info*)w1)->angle; - const double a2 = ((struct neighbour_info*)w2)->angle; - return (a1 > a2) - (a1 < a2); -} - -static FINLINE void -add_side_to_stack - (const struct senc2d_scene* scn, - struct darray_side_id* stack, - struct segside* segsides, - const side_id_t side_id) -{ - (void)scn; - ASSERT(scn && segsides && stack - && side_id < SIDE_MAX__ && side_id < 2 * scn->nusegs); - ASSERT((darray_side_id_size_get(stack) > 128) - || !find_side_in_list(segsides, stack, side_id, FLAG_WAITING_STACK)); - darray_side_id_push_back(stack, &side_id); - segsides[side_id].list_id = FLAG_WAITING_STACK; -} - -static side_id_t -get_side_not_in_connex_component - (const struct senc2d_scene* scn, - const struct segside* segsides, - side_id_t* first_side_not_in_component, - const medium_id_t medium) -{ - side_id_t i; - const seg_id_t last_side - = darray_side_range_cdata_get(&scn->media_use)[medium].last; - ASSERT(scn && segsides && first_side_not_in_component); - i = *first_side_not_in_component; - while(i <= last_side - && (segsides[i].medium != medium - || segsides[i].list_id != FLAG_LIST_SIDE_LIST)) { - ++i; - } - - *first_side_not_in_component = i+1; - if(i > last_side) return SIDE_NULL__; - return i; -} - -static FINLINE side_id_t -get_side_from_stack - (const struct segside* segsides, - struct darray_side_id* stack) -{ - side_id_t id; - size_t sz; - (void)segsides; - ASSERT(segsides && stack); - sz = darray_side_id_size_get(stack); - ASSERT(sz); - id = darray_side_id_cdata_get(stack)[sz - 1]; - ASSERT(segsides[id].list_id == FLAG_WAITING_STACK); - darray_side_id_pop_back(stack); - return id; -} - -static void -get_scn_indices(const unsigned iseg, unsigned ids[2], void* ctx) { - int i; - const struct senc2d_scene* scene = ctx; - const struct segment_in* seg = - darray_segment_in_cdata_get(&scene->segments_in) + iseg; - FOR_EACH(i, 0, 2) { - ASSERT(seg->vertice_id[i] < scene->nverts); - ids[i] = (unsigned)seg->vertice_id[i]; /* Back to API type */ - } -} - -static void -get_scn_position(const unsigned ivert, float pos[2], void* ctx) { - const struct senc2d_scene* scene = ctx; - const union double2* pt = - darray_position_cdata_get(&scene->vertices) + ivert; - f2_set_d2(pos, pt->vec); -} - -static int -self_hit_filter - (const struct s2d_hit* hit, - const float ray_org[2], - const float ray_dir[2], - void* ray_data, - void* filter_data) -{ - const struct darray_segment_comp* segments_comp = filter_data; - const component_id_t* origin_component = ray_data; - const struct segment_comp* hit_seg_comp; - enum side_id hit_side; - component_id_t hit_component; - - (void) ray_org; (void) ray_dir; - ASSERT(hit && segments_comp && origin_component); - ASSERT(hit->prim.prim_id < darray_segment_comp_size_get(segments_comp)); - hit_seg_comp = darray_segment_comp_cdata_get(segments_comp) - + hit->prim.prim_id; - hit_side = (hit->normal[1] > 0) ? SIDE_FRONT : SIDE_BACK; - hit_component = hit_seg_comp->component[hit_side]; - - /* Not self hit or distance should be small */ - ASSERT(hit_component != *origin_component || hit->distance < 1e-6); - return (hit_component == *origin_component); -} - -static res_T -extract_connex_components - (struct senc2d_descriptor* desc, - struct segside* segsides, - struct darray_ptr_component_descriptor* connex_components, - const struct darray_segment_tmp* segments_tmp_array, - struct darray_segment_comp* segments_comp, - struct s2d_scene_view** s2d_view) -{ - res_T res = RES_OK; - const struct senc2d_scene* scn; - struct mem_allocator* alloc; - static ATOMIC component_count = 0; - static volatile int exit_for = 0; - int64_t mm; -#ifndef NDEBUG - seg_id_t s_; - component_id_t c; -#endif - - ASSERT(segsides && desc && connex_components && segments_tmp_array); - ASSERT(darray_ptr_component_descriptor_size_get(connex_components) == 0); - alloc = descriptor_get_allocator(desc); - scn = desc->scene; - -#ifndef NDEBUG - #pragma omp single - { - FOR_EACH(s_, 0, scn->nusegs) { - const struct segment_in* seg_in = - darray_segment_in_cdata_get(&scn->segments_in) + s_; - const struct side_range* media_use - = darray_side_range_cdata_get(&scn->media_use); - FOR_EACH(mm, 0, 2) { - const side_id_t side = SEGIDxSIDE_2_SEGSIDE(s_, mm); - const medium_id_t medium = seg_in->medium[mm]; - ASSERT(media_use[medium].first <= side && side <= media_use[medium].last); - } - } - } /* Implicit barrier here */ -#endif - - /* #pragma omp parallel */ - { - struct darray_side_id stack; - darray_side_id_init(alloc, &stack); - - #pragma omp for schedule(dynamic) nowait - for(mm = 0; mm < (int64_t)scn->nmeds; mm++) { /* Process all media */ - const medium_id_t m = (medium_id_t)mm; - struct cc_descriptor* cc; - /* Any not-already-used side is used as a starting point */ - side_id_t first_side_not_in_component; - - if(exit_for) continue; - first_side_not_in_component - = darray_side_range_cdata_get(&scn->media_use)[m].first; - if(first_side_not_in_component == SIDE_NULL__) - continue; /* Unused medium */ - ASSERT(first_side_not_in_component < 2 * scn->nusegs); - ASSERT(darray_side_id_size_get(&stack) == 0); - for(;;) { /* Process all components for this medium */ - const side_id_t start_side_id = get_side_not_in_connex_component(scn, - segsides, &first_side_not_in_component, m); - side_id_t crt_side_id = start_side_id; - side_id_t last_side_id = start_side_id; - ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->nusegs); - if(start_side_id == SIDE_NULL__) - break; /* start_side_id=SIDE_NULL__ => done! */ - ASSERT(segsides[start_side_id].list_id == FLAG_LIST_SIDE_LIST); - -#ifndef NDEBUG - { - seg_id_t tid = SEGSIDE_2_SEG(start_side_id); - enum side_flag s = SEGSIDE_2_SIDE(start_side_id); - medium_id_t side_med - = darray_segment_in_data_get(&desc->scene->segments_in)[tid].medium[s]; - ASSERT(side_med == m); - } -#endif - - /* Create and init a new component */ - cc = MEM_ALLOC(alloc, sizeof(struct cc_descriptor)); - if(!cc) { - res = RES_MEM_ERR; - goto error1; - } - cc_descriptor_init(alloc, cc); - ASSERT(m == segsides[start_side_id].medium); - cc->cc_id = (component_id_t)(ATOMIC_INCR(&component_count) - 1); - cc->medium = m; - cc->side_range.first = start_side_id; - - for(;;) { /* Process all sides of this component */ - int i; - enum side_flag crt_side_flag = SEGSIDE_2_SIDE(crt_side_id); - struct segside* crt_side = segsides + crt_side_id; - const seg_id_t crt_seg_id = SEGSIDE_2_SEG(crt_side_id); - const struct segment_in* seg_in = - darray_segment_in_cdata_get(&scn->segments_in) + crt_seg_id; - struct segment_comp* seg_comp = - darray_segment_comp_data_get(segments_comp) + crt_seg_id; - const struct segment_tmp* const seg_tmp = - darray_segment_tmp_cdata_get(segments_tmp_array) + crt_seg_id; - const union double2* vertices = - darray_position_cdata_get(&scn->vertices); - ASSERT(crt_seg_id < scn->nusegs); - ASSERT(segsides[crt_side_id].medium == m); - - /* Record Ymax information - * Keep track of the appropriate vertex/side of the connex component - * in order to cast a ray at the component grouping step of the - * algorithm. - * The most appropriate vertex is (the) one with the greater Y - * coordinate. - * If more than one vertex/side has the same Y, we want the side that - * most faces Y (that is the one with the greater ny). - * This is mandatory to select the correct side when both sides of a - * segment are candidate. */ - if(cc->max_vrtx[1] <= seg_tmp->max_y) { - /* Can either improve y or ny */ - - if(cc->max_y_side_id == SEGSIDE_OPPOSITE(crt_side_id)) { - /* Both sides are in cc and the opposite side is currently selected - * Just keep the side with ny>0 */ - if(cc->max_y_ny < 0) { - /* Change side! */ - cc->max_y_ny = -cc->max_y_ny; - cc->max_y_side_id = crt_side_id; - } - } else { - double edge[2], normal[2], norm, side_ny; - int process = 0; - - d2_sub(edge, vertices[seg_in->vertice_id[1]].vec, - vertices[seg_in->vertice_id[0]].vec); - d2(normal, edge[1], -edge[0]); - norm = d2_normalize(normal, normal); - ASSERT(norm); (void) norm; - - /* Geometrical normal points toward the right */ - if(SEGSIDE_IS_FRONT(crt_side_id)) { - side_ny = -normal[1]; - process = 1; - } else { - side_ny = normal[1]; - process = 1; - } - - if(process) { - int change = 0; - if(cc->max_vrtx[1] < seg_tmp->max_y) { - change = 1; /* Try first to improve y */ - } else if(cc->max_y_ny <= 0 && fabs(cc->max_y_ny) < fabs(side_ny)) { - change = 1; /* If ny <= 0, the more negative the better */ - } else if(cc->max_y_ny > 0 && cc->max_y_ny < side_ny) { - change = 1; /* If ny > 0, the more positive the better */ - } - - if(change) { - cc->max_y_ny = side_ny; - cc->max_y_side_id = crt_side_id; - ASSERT(seg_tmp->max_y_vrtx_rank < 2); - ASSERT(seg_in->vertice_id[seg_tmp->max_y_vrtx_rank] < scn->nverts); - cc->max_y_vrtx_id = seg_in->vertice_id[seg_tmp->max_y_vrtx_rank]; - ASSERT(seg_tmp->max_y == vertices[cc->max_y_vrtx_id].pos.y); - d2_set(cc->max_vrtx, vertices[cc->max_y_vrtx_id].vec); - } - } - } - } - - /* Record crt_side both as component and segment level */ - cc->side_count++; - segsides[crt_side_id].list_id = FLAG_LIST_COMPONENT; - ASSERT(seg_comp->component[crt_side_flag] == COMPONENT_NULL__); - seg_comp->component[crt_side_flag] = cc->cc_id; -#ifndef NDEBUG - crt_side->member_of_cc = cc->cc_id; -#endif - - /* Store neighbour sides in a waiting stack */ - FOR_EACH(i, 0, 2) { - side_id_t neighbour_id = crt_side->facing_side_id[i]; - seg_id_t nbour_seg_id = SEGSIDE_2_SEG(neighbour_id); - const struct segside* neighbour = segsides + neighbour_id; - ASSERT(m == crt_side->medium); - if(neighbour->medium != crt_side->medium) { - /* Found medium discontinuity! Model topology is broken. */ - const struct segment_in* segments_in - = darray_segment_in_cdata_get(&scn->segments_in); - const union double2* positions - = darray_position_cdata_get(&scn->vertices); - log_err(scn->dev, - "Medium mismatch found between neighbour segments %lu %s" - " side and %u %s side.\n", - (unsigned long) segments_in[crt_seg_id].global_id, - SEGSIDE_IS_FRONT(crt_side_id) ? "front" : "back", - segments_in[nbour_seg_id].global_id, - SEGSIDE_IS_FRONT(neighbour_id) ? "front" : "back"); - log_err(scn->dev, - "Segment %lu:\n (%g %g) (%g %g))\n", - (unsigned long) segments_in[crt_seg_id].global_id, - SPLIT2(positions[segments_in[crt_seg_id].vertice_id[0]].vec), - SPLIT2(positions[segments_in[crt_seg_id].vertice_id[1]].vec)); - log_err(scn->dev, - "Segment %lu:\n (%g %g) (%g %g)\n", - (unsigned long) segments_in[nbour_seg_id].global_id, - SPLIT2(positions[segments_in[nbour_seg_id].vertice_id[0]].vec), - SPLIT2(positions[segments_in[nbour_seg_id].vertice_id[1]].vec)); - log_err(desc->scene->dev, "Media: %lu VS %lu\n", - (unsigned long)neighbour->medium, (unsigned long)crt_side->medium); - res = RES_BAD_ARG; - goto error1; - } - if(neighbour->list_id == FLAG_LIST_COMPONENT) { - /* Already processed */ -#ifndef NDEBUG - ASSERT(neighbour->member_of_cc == cc->cc_id); -#endif - continue; - } - if(neighbour->list_id == FLAG_WAITING_STACK) { - continue; /* Already processed */ - } - add_side_to_stack(scn, &stack, segsides, neighbour_id); - } - if(darray_side_id_size_get(&stack) == 0) - break; /* Empty stack => connex component is done! */ - crt_side_id = get_side_from_stack(segsides, &stack); - last_side_id = MMAX(last_side_id, crt_side_id); - } - /* Keep track of this new connex component */ - cc->side_range.last = last_side_id; - /* Need to synchronize connex_components growth as this global structure - * is accessed by multipe threads */ - #pragma omp critical - { - struct cc_descriptor** components; - size_t sz = darray_ptr_component_descriptor_size_get(connex_components); - if(sz <= cc->cc_id) { - res_T tmp_res = darray_ptr_component_descriptor_resize(connex_components, - 1 + cc->cc_id); - if(tmp_res != RES_OK) res = tmp_res; - } - if(res == RES_OK) { - /* Don't set the pointer before resize as this can lead to move data */ - components = - darray_ptr_component_descriptor_data_get(connex_components); - ASSERT(components[cc->cc_id] == NULL); - components[cc->cc_id] = cc; - } - } - OK2(res, error1); - } - continue; - error1: - /* Cannot goto out of openmp block */ - exit_for = 1; - continue; - } - /* No barrier here (nowait clause). - * The first thread executes the single block */ - darray_side_id_release(&stack); - #pragma omp single nowait - if(res == RES_OK) { - struct s2d_device* s2d = NULL; - struct s2d_scene* s2d_scn = NULL; - struct s2d_shape* s2d_shp = NULL; - struct s2d_vertex_data attribs; - - attribs.type = S2D_FLOAT2; - attribs.usage = S2D_POSITION; - attribs.get = get_scn_position; - - /* Put geometry in a 2D view */ - OK(s2d_device_create(desc->scene->dev->logger, alloc, 0, &s2d)); - OK(s2d_scene_create(s2d, &s2d_scn)); - OK(s2d_shape_create_line_segments(s2d, &s2d_shp)); - - /* Back to API type for ntris and nverts */ - ASSERT(desc->scene->nusegs < UINT_MAX); - ASSERT(desc->scene->nuverts < UINT_MAX); - OK(s2d_line_segments_setup_indexed_vertices(s2d_shp, (unsigned)desc->scene->nusegs, - get_scn_indices, (unsigned)desc->scene->nuverts, &attribs, 1, desc->scene)); - s2d_line_segments_set_hit_filter_function(s2d_shp, self_hit_filter, segments_comp); - OK(s2d_scene_attach_shape(s2d_scn, s2d_shp)); - OK(s2d_scene_view_create(s2d_scn, S2D_TRACE, s2d_view)); - error: - if(s2d) S2D(device_ref_put(s2d)); - if(s2d_scn) S2D(scene_ref_put(s2d_scn)); - if(s2d_shp) S2D(shape_ref_put(s2d_shp)); - } - }/* No barrier here */ - OK2(res, error_); - -#ifndef NDEBUG - #pragma omp barrier - ASSERT(component_count == - (int)darray_ptr_component_descriptor_size_get(connex_components)); - FOR_EACH(s_, 0, scn->nusegs) { - struct segment_comp* seg_comp = - darray_segment_comp_data_get(segments_comp) + s_; - ASSERT(seg_comp->component[SIDE_FRONT] != COMPONENT_NULL__); - ASSERT(seg_comp->component[SIDE_BACK] != COMPONENT_NULL__); - } - FOR_EACH(c, 0, component_count) { - struct cc_descriptor** components = - darray_ptr_component_descriptor_data_get(connex_components); - ASSERT(components[c] != NULL && - components[c]->cc_id == c); - } - ASSERT(desc->segment_count - == darray_segment_comp_size_get(segments_comp)); -#endif - -exit: - /* segments_enc is still unused: no size to assert */ - return res; -error_: - goto exit; -} - -static res_T -group_connex_components - (struct senc2d_descriptor* desc, - struct segside* segsides, - struct darray_segment_comp* segments_comp, - struct darray_ptr_component_descriptor* connex_components, - struct s2d_scene_view* s2d_view) -{ - res_T res = RES_OK; - struct cc_descriptor** descriptors; - size_t tmp; - component_id_t cc_count; - int64_t ccc; - static volatile int exit_for = 0; - static ATOMIC next_enclosure_id = 1; - struct cc_descriptor* infinity_first_cc = NULL; - (void)segsides; - ASSERT(desc && segsides && segments_comp && connex_components); - ASSERT(desc->enclosures_count == 1); - - descriptors = darray_ptr_component_descriptor_data_get(connex_components); - tmp = darray_ptr_component_descriptor_size_get(connex_components); - ASSERT(tmp <= COMPONENT_MAX__); - cc_count = (component_id_t)tmp; - - /* Cast rays to find links between connex components */ - #pragma omp /* parallel */ for - for(ccc = 0; ccc < (int64_t)cc_count; ccc++) { - component_id_t c = (component_id_t)ccc; - struct s2d_hit hit = S2D_HIT_NULL; - float origin[2]; - const float dir[2] = { 0, 1 }; - const float range[2] = { 0, FLT_MAX }; - struct cc_descriptor* const cc = descriptors[c]; - const struct segment_comp* origin_seg = - darray_segment_comp_cdata_get(segments_comp) + cc->max_y_vrtx_id; - component_id_t self_hit_component - = origin_seg->component[1 - SEGSIDE_2_SIDE(cc->max_y_side_id)]; - - if(exit_for) continue; - ASSERT(cc->cc_id == c); - ASSERT(cc->cc_group_root == CC_GROUP_ID_NONE); - - if(cc->max_y_ny < 0) { - int64_t id; - /* Don't need to cast a ray */ - cc->cc_group_root = cc->cc_id; /* New group with self as root */ - id = ATOMIC_INCR(&next_enclosure_id) - 1; - ASSERT(id < ENCLOSURE_MAX__); - cc->enclosure_id = (enclosure_id_t)id; - continue; - } - - ASSERT(cc->max_y_ny != 0 - /* The only situation with ny==0 we can think of is this one: */ - || (segsides[cc->max_y_side_id].medium - == segsides[SEGSIDE_OPPOSITE(cc->max_y_side_id)].medium - && (segsides[cc->max_y_side_id].facing_side_id[0] - == SEGSIDE_OPPOSITE(cc->max_y_side_id) - || segsides[cc->max_y_side_id].facing_side_id[1] - == SEGSIDE_OPPOSITE(cc->max_y_side_id)))); - f2_set_d2(origin, cc->max_vrtx); - /* Self-hit data: self hit if hit this component "on the other side" */ - OK2(s2d_scene_view_trace_ray(s2d_view, origin, dir, range, - &self_hit_component, &hit), error_); - /* If no hit, the component is facing an infinite medium */ - if(S2D_HIT_NONE(&hit)) { - cc->cc_group_root = CC_GROUP_ROOT_INFINITE; - cc->enclosure_id = 0; - /* Keep track of the first component facing infinity */ - ATOMIC_CAS_PTR(&infinity_first_cc, cc, NULL); - if(infinity_first_cc->medium != cc->medium) { - const side_id_t infinity_first_side = infinity_first_cc->max_y_side_id; - const medium_id_t infinity_medium = infinity_first_cc->medium; - /* Medium mismatch! Model topology is broken. */ - const seg_id_t t1 = SEGSIDE_2_SEG(infinity_first_side); - const seg_id_t t2 = SEGSIDE_2_SEG(cc->max_y_side_id); - const struct segment_in* segments_in - = darray_segment_in_cdata_get(&desc->scene->segments_in); - const union double2* positions - = darray_position_cdata_get(&desc->scene->vertices); - log_err(desc->scene->dev, - "Medium mismatch found between segment %lu %s side and segment" - " %lu %s side, both facing infinity.\n", - (unsigned long)segments_in[t1].global_id, - SEGSIDE_IS_FRONT(infinity_first_side) ? "front" : "back", - (unsigned long) segments_in[t2].global_id, - SEGSIDE_IS_FRONT(cc->max_y_side_id) ? "front" : "back"); - log_err(desc->scene->dev, - "Segment %lu:\n (%g %g) (%g %g)\n", - (unsigned long)segments_in[t1].global_id, - SPLIT2(positions[segments_in[t1].vertice_id[0]].vec), - SPLIT2(positions[segments_in[t1].vertice_id[1]].vec)); - log_err(desc->scene->dev, - "Segment %lu:\n (%g %g) (%g %g)\n", - (unsigned long)segments_in[t2].global_id, - SPLIT2(positions[segments_in[t2].vertice_id[0]].vec), - SPLIT2(positions[segments_in[t2].vertice_id[1]].vec)); - log_err(desc->scene->dev, "Media: %lu VS %lu\n", - (unsigned long)infinity_medium, (unsigned long)cc->medium); - res = RES_BAD_ARG; - goto error_; - } - /* Same medium as previous members of the group: OK */ - continue; - } else { - /* If hit, group this component */ - const seg_id_t hit_seg_id = (seg_id_t)hit.prim.prim_id; - const struct segment_in* hit_seg_in = - darray_segment_in_cdata_get(&desc->scene->segments_in) + hit_seg_id; - const struct segment_comp* hit_seg_comp = - darray_segment_comp_cdata_get(segments_comp) + hit_seg_id; - enum side_id hit_side = (hit.normal[1] > 0) ? SIDE_FRONT : SIDE_BACK; - const side_id_t hit_side_id = SEGIDxSIDE_2_SEGSIDE(hit_seg_id, hit_side); - - ASSERT(hit_seg_id < desc->scene->nusegs); - - /* Not really the root until following links */ - cc->cc_group_root = hit_seg_comp->component[hit_side]; -#ifndef NDEBUG - { - const struct cc_descriptor* hit_desc; - ASSERT(cc->cc_group_root - < darray_ptr_component_descriptor_size_get(connex_components)); - hit_desc = *(darray_ptr_component_descriptor_cdata_get(connex_components) - + cc->cc_group_root); - ASSERT(hit_desc->medium == hit_seg_in->medium[hit_side]); - } -#endif - if(hit_seg_in->medium[hit_side] != cc->medium) { - /* Medium mismatch! Model topology is broken. */ - const seg_id_t t1 = SEGSIDE_2_SEG(hit_side_id); - const seg_id_t t2 = SEGSIDE_2_SEG(cc->max_y_side_id); - const struct segment_in* segments_in - = darray_segment_in_cdata_get(&desc->scene->segments_in); - const union double2* positions - = darray_position_cdata_get(&desc->scene->vertices); - log_err(desc->scene->dev, - "Medium mismatch found between segment %lu %s side and segment" - " %lu %s side facing each other.\n", - (unsigned long)segments_in[t1].global_id, - SEGSIDE_IS_FRONT(hit_side) ? "front" : "back", - (unsigned long)segments_in[t2].global_id, - SEGSIDE_IS_FRONT(cc->max_y_side_id) ? "front" : "back"); - log_err(desc->scene->dev, - "Segment %lu:\n (%g %g) (%g %g)\n", - (unsigned long)segments_in[t1].global_id, - SPLIT2(positions[segments_in[t1].vertice_id[0]].vec), - SPLIT2(positions[segments_in[t1].vertice_id[1]].vec)); - log_err(desc->scene->dev, - "Segment %lu:\n (%g %g) (%g %g)\n", - (unsigned long)segments_in[t2].global_id, - SPLIT2(positions[segments_in[t2].vertice_id[0]].vec), - SPLIT2(positions[segments_in[t2].vertice_id[1]].vec)); - log_err(desc->scene->dev, "Media: %lu VS %lu\n", - (unsigned long)hit_seg_in->medium[hit_side], - (unsigned long)cc->medium); - - res = RES_BAD_ARG; - goto error_; - } - } - continue; - error_: - /* Cannot goto out of openmp block */ - exit_for = 1; - continue; - } /* Implicit barrier here */ - ASSERT(next_enclosure_id < ENCLOSURE_MAX__); - OK(res); - - /* Post-process links to group connex components */ - #pragma omp single - { - desc->enclosures_count = (enclosure_id_t)next_enclosure_id; - res = darray_enclosure_resize(&desc->enclosures, desc->enclosures_count); - if(res == RES_OK) { - FOR_EACH(ccc, 0, cc_count) { - component_id_t c = (component_id_t) ccc; - struct cc_descriptor* const cc = descriptors[c]; - const struct cc_descriptor* other_desc = cc; - struct enclosure_data* enclosures - = darray_enclosure_data_get(&desc->enclosures); - component_id_t fst; - - while(other_desc->enclosure_id == CC_GROUP_ID_NONE) { - other_desc = *(darray_ptr_component_descriptor_cdata_get(connex_components) - + other_desc->cc_group_root); - } - ASSERT(other_desc->cc_group_root != CC_GROUP_ROOT_NONE); - ASSERT(other_desc->enclosure_id != CC_GROUP_ID_NONE); - ASSERT(cc->medium == other_desc->medium); - cc->cc_group_root = other_desc->cc_group_root; - cc->enclosure_id = other_desc->enclosure_id; - ++enclosures[cc->enclosure_id].cc_count; - /* Linked list of componnents */ - fst = enclosures[cc->enclosure_id].first_component; - cc->enclosure_next_component = fst; - enclosures[cc->enclosure_id].first_component = cc->cc_id; - enclosures[cc->enclosure_id].side_range.first - = MMIN(enclosures[cc->enclosure_id].side_range.first, cc->side_range.first); - enclosures[cc->enclosure_id].side_range.last - = MMAX(enclosures[cc->enclosure_id].side_range.last, cc->side_range.last); - enclosures[cc->enclosure_id].side_count += cc->side_count; - } - } - } /* Implicit barrier here */ - OK(res); - -exit: - return res; -error: - goto exit; -} - -static res_T -collect_and_link_neighbours - (struct senc2d_scene* scn, - struct segside* segsides, - struct darray_segment_tmp* segments_tmp_array, - struct darray_neighbourhood* neighbourhood_by_vertex) -{ - res_T res = RES_OK; - const struct segment_in *segments_in; - struct segment_tmp *segments_tmp; - const union double2* vertices; - static volatile int exit_for = 0; - - ASSERT(scn && segsides && segments_tmp_array); - ASSERT((size_t)scn->nuverts + (size_t)scn->nusegs + 2 <= EDGE_MAX__); - - segments_in = darray_segment_in_cdata_get(&scn->segments_in); - segments_tmp = darray_segment_tmp_data_get(segments_tmp_array); - vertices = darray_position_cdata_get(&scn->vertices); - - ASSERT(scn->nusegs == darray_segment_tmp_size_get(segments_tmp_array)); - - /* Resize / Push operations on neighbourhood_by_vertex are valid in the - * openmp block because each neighbourhood is processes by an unique thread */ - /* #pragma omp parallel */ - { - const int thread_count = omp_get_num_threads(); - const int rank = omp_get_thread_num(); - /* Array to keep neighbourhood of vertices - * Resize/Push operations on neighbourhood_by_vertex are valid in the - * openmp block because it is thread local data */ - vrtx_id_t v; - seg_id_t s; - /* Loop on segments to collect edges' neighbours. - * All threads considering all the vertices and processing some */ - FOR_EACH(s, 0, scn->nusegs) { - unsigned char vv; - FOR_EACH(vv, 0, 2) { - struct darray_neighbour* neighbourhood; - struct neighbour_info* info; - const vrtx_id_t vertex = segments_in[s].vertice_id[vv]; - size_t sz; - ASSERT(vertex < scn->nuverts); - if(exit_for) continue; - /* Process only "my" vertices! */ - if((int64_t)vertex % thread_count != rank) continue; - /* Find neighbourhood */ - ASSERT(vertex < darray_neighbourhood_size_get(neighbourhood_by_vertex)); - neighbourhood = - darray_neighbourhood_data_get(neighbourhood_by_vertex) + vertex; - sz = darray_neighbour_size_get(neighbourhood); - /* Make room for this neighbour */ - if(darray_neighbour_capacity(neighbourhood) == sz) { - /* 2 seems to be a good guess for initial capacity */ - size_t new_sz = sz ? sz + 1 : 2; - OK(darray_neighbour_reserve(neighbourhood, new_sz)); - } - OK(darray_neighbour_resize(neighbourhood, 1 + sz)); - /* Add neighbour info to vertex's neighbour list */ - info = darray_neighbour_data_get(neighbourhood) + sz; - info->seg_id = s; - info->common_vertex_rank = vv; - } - } /* No barrier here. */ - - /* For each of "my" vertices sort segments sides by rotation angle - * and connect neighbours. - * All threads considering all the vertices and processing some */ - FOR_EACH(v, 0, scn->nuverts) { - const vrtx_id_t common_vrtx = v; - vrtx_id_t other_vrtx; - struct darray_neighbour* neighbourhood; - side_id_t i, neighbour_count; - size_t sz; - /* Process only "my" vertices! */ - if((int64_t)v % thread_count != rank) continue; - neighbourhood - = darray_neighbourhood_data_get(neighbourhood_by_vertex) + v; - sz = darray_neighbour_size_get(neighbourhood); - /* sz can be 0 as a vertex can be unused */ - if(!sz) continue; - ASSERT(sz <= SIDE_MAX__); - neighbour_count = (side_id_t)sz; - FOR_EACH(i, 0, neighbour_count) { - double max_y, disp[2]; - unsigned char max_y_vrank; - struct neighbour_info* neighbour_info - = darray_neighbour_data_get(neighbourhood) + i; - const struct segment_in* seg_in = segments_in + neighbour_info->seg_id; - struct segment_tmp* neighbour = segments_tmp + neighbour_info->seg_id; - other_vrtx = - seg_in->vertice_id[(neighbour_info->common_vertex_rank + 1) % 2]; - if(vertices[other_vrtx].pos.y > vertices[common_vrtx].pos.y) { - max_y = vertices[other_vrtx].pos.y; - max_y_vrank = 1 - neighbour_info->common_vertex_rank; - } else { - max_y = vertices[common_vrtx].pos.y; - max_y_vrank = neighbour_info->common_vertex_rank; - } - ASSERT(neighbour->max_y <= max_y); - neighbour->max_y = max_y; - neighbour->max_y_vrtx_rank = max_y_vrank; - /* Compute rotation angle around common vertex (in world system) */ - d2_sub(disp, vertices[other_vrtx].vec, vertices[common_vrtx].vec); - ASSERT(disp[0] || disp[1]); - neighbour_info->angle = atan2(disp[1], disp[0]); - if(neighbour_info->angle < 0) neighbour_info->angle += 2 * PI; - /* Due to catastrophic cancelation, -eps+2pi translates to 2pi */ - ASSERT(0 <= neighbour_info->angle && neighbour_info->angle <= 2 * PI); - } - /* Sort segments by rotation angle */ - qsort(darray_neighbour_data_get(neighbourhood), neighbour_count, - sizeof(struct neighbour_info), neighbour_cmp); - /* Link sides. - * Create cycles of sides by neighbourhood around common vertex. */ - FOR_EACH(i, 0, neighbour_count) { - /* Neighbourhood info for current pair of segments */ - const struct neighbour_info* current - = darray_neighbour_cdata_get(neighbourhood) + i; - const struct neighbour_info* ccw_neighbour - = darray_neighbour_cdata_get(neighbourhood) + (i+1) % neighbour_count; - /* Rank of the end of interest in segments */ - const unsigned char crt_end = current->common_vertex_rank; - const unsigned char ccw_end = ccw_neighbour->common_vertex_rank; - /* User id of current segments */ - const seg_id_t crt_id = current->seg_id; - const seg_id_t ccw_id = ccw_neighbour->seg_id; - /* Facing sides of segments */ - const enum side_id crt_side = crt_end ? SIDE_BACK : SIDE_FRONT; - const enum side_id ccw_side = ccw_end ? SIDE_FRONT : SIDE_BACK; - /* Index of sides in segsides */ - const side_id_t crt_side_idx = SEGIDxSIDE_2_SEGSIDE(crt_id, crt_side); - const side_id_t ccw_side_idx = SEGIDxSIDE_2_SEGSIDE(ccw_id, ccw_side); - /* Side ptrs */ - struct segside* const p_crt_side = segsides + crt_side_idx; - struct segside* const p_ccw_side = segsides + ccw_side_idx; - /* Link sides */ - p_crt_side->facing_side_id[crt_end] = ccw_side_idx; - p_ccw_side->facing_side_id[ccw_end] = crt_side_idx; - /* Record media */ - p_crt_side->medium = segments_in[crt_id].medium[crt_side]; - p_ccw_side->medium = segments_in[ccw_id].medium[ccw_side]; - ASSERT(p_crt_side->medium < scn->nmeds); - ASSERT(p_ccw_side->medium < scn->nmeds); - p_crt_side->list_id = FLAG_LIST_SIDE_LIST; - p_ccw_side->list_id = FLAG_LIST_SIDE_LIST; - } - } /* No barrier here. */ - /* jump error block */ - goto after_error; -error: - /* Cannot goto out of openmp block */ - exit_for = 1; -after_error: - ; - } - return res; -} - -static res_T -build_result - (struct senc2d_descriptor* desc, - const struct darray_ptr_component_descriptor* connex_components, - const struct darray_segment_comp* segments_comp_array) -{ - res_T res = RES_OK; - struct mem_allocator* alloc; - struct cc_descriptor* const* cc_descriptors; - struct enclosure_data* enclosures; - const struct segment_in* segments_in; - struct segment_enc* segments_enc; - const struct segment_comp* segments_comp; - static volatile int exit_for = 0; - - ASSERT(desc && connex_components && segments_comp_array); - - alloc = descriptor_get_allocator(desc); - ASSERT(darray_ptr_component_descriptor_size_get(connex_components) < COMPONENT_MAX__); - cc_descriptors = darray_ptr_component_descriptor_cdata_get(connex_components); - enclosures = darray_enclosure_data_get(&desc->enclosures); - segments_in = darray_segment_in_cdata_get(&desc->scene->segments_in); - segments_comp = darray_segment_comp_cdata_get(segments_comp_array); - #pragma omp single - { - res = darray_segment_enc_resize(&desc->segments_enc, desc->scene->nusegs); - }/* Implicit barrier here. */ - OK2(res, error_); - segments_enc = darray_segment_enc_data_get(&desc->segments_enc); - - /* #pragma omp parallel */ - { - struct htable_vrtx_id vtable; - int64_t sg; - int64_t ee; - - /* Build global enclosure information */ - #pragma omp for - for(sg = 0; sg < (int64_t) desc->scene->nusegs; sg++) { - seg_id_t s = (seg_id_t) sg; - const component_id_t cf_id = segments_comp[s].component[SIDE_FRONT]; - const component_id_t cb_id = segments_comp[s].component[SIDE_BACK]; - const struct cc_descriptor* cf = cc_descriptors[cf_id]; - const struct cc_descriptor* cb = cc_descriptors[cb_id]; - const enclosure_id_t ef_id = cf->enclosure_id; - const enclosure_id_t eb_id = cb->enclosure_id; - ASSERT(segments_enc[s].enclosure[SIDE_FRONT] == ENCLOSURE_NULL__); - segments_enc[s].enclosure[SIDE_FRONT] = ef_id; - ASSERT(segments_enc[s].enclosure[SIDE_BACK] == ENCLOSURE_NULL__); - segments_enc[s].enclosure[SIDE_BACK] = eb_id; - } - /* Implicit barrier here */ - - /* Resize/push operations on enclosure's fields are valid in the - * openmp block as a given enclosure is processed by a single thread */ - htable_vrtx_id_init(alloc, &vtable); - - ASSERT(desc->enclosures_count <= ENCLOSURE_MAX__); - #pragma omp for schedule(dynamic) nowait - for(ee = 0; ee < (int64_t)desc->enclosures_count; ee++) { - const enclosure_id_t e = (enclosure_id_t)ee; - struct enclosure_data* enc = enclosures + e; - const struct cc_descriptor* current = cc_descriptors[enc->first_component]; - seg_id_t fst_idx = 0; - seg_id_t sgd_idx = enc->side_count; - seg_id_t s; - ASSERT(enc->first_component - < darray_ptr_component_descriptor_size_get(connex_components)); - ASSERT(current->cc_id == enc->first_component); - - if(exit_for) continue; - ASSERT(e <= UINT_MAX); - enc->header.enclosure_id = (unsigned)e; /* Back to API type */ - ASSERT(current->enclosure_id == enc->header.enclosure_id); - enc->header.is_infinite = (e == 0); - enc->header.enclosed_medium - = (unsigned)current->medium; /* Back to API type */ - ASSERT(enc->header.enclosed_medium < desc->scene->nmeds); - - /* Build side and vertex lists. */ - OK(darray_segment_in_resize(&enc->sides, enc->side_count)); - /* Size is just a int */ - OK(darray_vrtx_id_reserve(&enc->vertices, enc->side_count + 1)); - /* New vertex numbering scheme local to the enclosure */ - htable_vrtx_id_clear(&vtable); - ASSERT(desc->scene->nusegs - == darray_segment_in_size_get(&desc->scene->segments_in)); - /* Put at the end the back-faces of segments that also have their - * front-face in the list. */ - for(s = SEGSIDE_2_SEG(enc->side_range.first); - s <= SEGSIDE_2_SEG(enc->side_range.last); - s++) - { - const struct segment_in* seg_in = segments_in + s; - struct segment_in* seg; - unsigned vertice_id[2]; - int i; - if(segments_enc[s].enclosure[SIDE_FRONT] != e - && segments_enc[s].enclosure[SIDE_BACK] != e) - continue; - ++enc->header.unique_segment_count; - - FOR_EACH(i, 0, 2) { - vrtx_id_t* id = htable_vrtx_id_find(&vtable, seg_in->vertice_id + i); - if(id) { - vertice_id[i] = *id; /* Known vertex */ - } else { - /* Create new association */ - size_t tmp = htable_vrtx_id_size_get(&vtable); - ASSERT(tmp == darray_vrtx_id_size_get(&enc->vertices)); - ASSERT(tmp < VRTX_MAX__); - vertice_id[i] = (vrtx_id_t)tmp; - OK(htable_vrtx_id_set(&vtable, seg_in->vertice_id + i, - vertice_id + i)); - OK(darray_vrtx_id_push_back(&enc->vertices, seg_in->vertice_id + i)); - ++enc->header.vertices_count; - } - } - ASSERT(segments_enc[s].enclosure[SIDE_FRONT] == e - || segments_enc[s].enclosure[SIDE_BACK] == e); - if(segments_enc[s].enclosure[SIDE_FRONT] == e) { - ++enc->header.segment_count; - seg = darray_segment_in_data_get(&enc->sides) + fst_idx++; - - FOR_EACH(i, 0, 2) seg->medium[i] = seg_in->medium[i]; - seg->global_id = seg_in->global_id; - FOR_EACH(i, 0, 2) seg->vertice_id[i] = vertice_id[i]; - } - if(segments_enc[s].enclosure[SIDE_BACK] == e) { - ++enc->header.segment_count; - seg = darray_segment_in_data_get(&enc->sides) + - ((segments_enc[s].enclosure[SIDE_FRONT] == e) ? --sgd_idx : fst_idx++); - - FOR_EACH(i, 0, 2) seg->medium[i] = seg_in->medium[1 - i]; - seg->global_id = seg_in->global_id; - FOR_EACH(i, 0, 2) seg->vertice_id[i] = vertice_id[1 - i]; - } - if(fst_idx == sgd_idx) break; - } - continue; - error: - /* Cannot goto out of openmp block */ - exit_for = 1; - } /* No barrier here */ - htable_vrtx_id_release(&vtable); - } - OK2(res, error_); - -exit: - return res; -error_: - goto exit; -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -senc2d_scene_analyze(struct senc2d_scene* scn, struct senc2d_descriptor** out_desc) -{ - res_T res = RES_OK; - struct senc2d_descriptor* desc = NULL; - /* By segment tmp data */ - struct darray_segment_tmp segments_tmp; - char segments_tmp_initialized = 0; - /* Array of connex components. - * They are refered to by arrays of ids. */ - struct darray_ptr_component_descriptor connex_components; - char connex_components_initialized = 0; - /* Store by-segment components */ - struct darray_segment_comp segments_comp; - char segments_comp_initialized = 0; - /* Array of vertices (segment ends). */ - struct segside* segsides = NULL; - struct s2d_scene_view* s2d_view = NULL; - /* Array to keep neighbourhood of vertices */ - struct darray_neighbourhood neighbourhood_by_vertex; - char neighbourhood_by_vertex_initialized = 0; - - if(!scn || !out_desc) return RES_BAD_ARG; - - desc = descriptor_create(scn); - if(!desc) { - res = RES_MEM_ERR; - goto error; - } - - if(!scn->nusegs) goto exit; - - darray_segment_tmp_init(scn->dev->allocator, &segments_tmp); - segments_tmp_initialized = 1; - - OK(darray_segment_tmp_resize(&segments_tmp, scn->nusegs)); - segsides - = MEM_CALLOC(scn->dev->allocator, 2 * scn->nusegs, sizeof(struct segside)); - if(!segsides) { - res = RES_MEM_ERR; - goto error; - } - - /* We create a neighbourhood for every single unique vertex, - * regardless the fact it is used by a segment */ - darray_neighbourhood_init(scn->dev->allocator, &neighbourhood_by_vertex); - neighbourhood_by_vertex_initialized = 1; - OK(darray_neighbourhood_resize(&neighbourhood_by_vertex, scn->nuverts)); - - #pragma omp parallel - { - res_T tmpres = RES_OK; - - /* Step 1: build neighbourhoods */ - tmpres = collect_and_link_neighbours(scn, segsides, &segments_tmp, - &neighbourhood_by_vertex); - /* No barrier at the end of step 1 */ - - if(tmpres != RES_OK) { - res = tmpres; - #pragma omp single nowait - { - log_err(scn->dev, - "%s: could not build neighbourhoods from scene.\n", FUNC_NAME); - } /* No barrier here */ - } - OK2(res, error_); - - /* The first thread here allocates some data */ - #pragma omp single - { - darray_ptr_component_descriptor_init(scn->dev->allocator, - &connex_components); - connex_components_initialized = 1; - /* Just a hint; to limit contention */ - tmpres = darray_ptr_component_descriptor_reserve(&connex_components, - 2 * scn->nmeds); - if(tmpres != RES_OK) res = tmpres; - darray_segment_comp_init(scn->dev->allocator, &segments_comp); - segments_comp_initialized = 1; - tmpres = darray_segment_comp_resize(&segments_comp, scn->nusegs); - if(tmpres != RES_OK) res = tmpres; - } /* Implicit barrier here */ - OK2(res, error_); - - /* One thread releases some data, the others go to step 2 */ - #pragma omp single nowait - { - darray_neighbourhood_release(&neighbourhood_by_vertex); - neighbourhood_by_vertex_initialized = 0; - } /* No implicit barrier here */ - - - /* Step 2: extract segment connex components */ - tmpres = extract_connex_components(desc, segsides, &connex_components, - &segments_tmp, &segments_comp, &s2d_view); - /* No barrier at the end of step 2 */ - - if(tmpres != RES_OK) { - res = tmpres; - #pragma omp single nowait - { - log_err(scn->dev, - "%s: could not extract connex components from scene.\n", FUNC_NAME); - } /* No implicit barrier here */ - } - OK2(res, error_); - - #pragma omp barrier - /* One thread releases some data, the others go to step 3 */ - #pragma omp single nowait - { - darray_segment_tmp_release(&segments_tmp); - segments_tmp_initialized = 0; - } /* No implicit barrier here */ - - /* Step 3: group components */ - tmpres = group_connex_components(desc, segsides, &segments_comp, - &connex_components, s2d_view); - /* Barrier at the end of step 3 */ - - /* The first thread here releases some data */ - #pragma omp single nowait - { - if(s2d_view) S2D(scene_view_ref_put(s2d_view)); - s2d_view = NULL; - } /* No implicit barrier here */ - - if(res != RES_OK) { - res = tmpres; - #pragma omp single nowait - { - log_err(scn->dev, - "%s: could not group connex components from scene.\n", FUNC_NAME); - } /* No implicit barrier here */ - } - OK2(res, error_); - - /* Build result. */ - tmpres = build_result(desc, &connex_components, &segments_comp); - /* No barrier at the end of build step */ - - if(tmpres != RES_OK) { - res = tmpres; - #pragma omp single nowait - { - log_err(scn->dev, "%s: could not build result.\n", FUNC_NAME); - } /* No implicit barrier here */ - } - OK2(res, error_); - - #pragma omp barrier - /* Some threads release data */ - #pragma omp sections nowait - { - #pragma omp section - { - darray_segment_comp_release(&segments_comp); - segments_comp_initialized = 0; - } - #pragma omp section - { - if(connex_components_initialized) { - size_t c, cc_count = - darray_ptr_component_descriptor_size_get(&connex_components); - struct cc_descriptor** components = - darray_ptr_component_descriptor_data_get(&connex_components); - FOR_EACH(c, 0, cc_count) { - ptr_component_descriptor_release(scn->dev->allocator, components + c); - } - darray_ptr_component_descriptor_release(&connex_components); - connex_components_initialized = 0; - } - } - } /* No implicit barrier here */ -error_: - ; - } /* Implicit barrier here */ - -if(res != RES_OK) goto error; -exit: - if(connex_components_initialized) { - size_t c, cc_count = - darray_ptr_component_descriptor_size_get(&connex_components); - struct cc_descriptor** components = - darray_ptr_component_descriptor_data_get(&connex_components); - FOR_EACH(c, 0, cc_count) { - ptr_component_descriptor_release(scn->dev->allocator, components + c); - } - darray_ptr_component_descriptor_release(&connex_components); - } - if(s2d_view) S2D(scene_view_ref_put(s2d_view)); - if(neighbourhood_by_vertex_initialized) - darray_neighbourhood_release(&neighbourhood_by_vertex); - if(segments_tmp_initialized) darray_segment_tmp_release(&segments_tmp); - if(segments_comp_initialized) darray_segment_comp_release(&segments_comp); - if(segsides) MEM_RM(scn->dev->allocator, segsides); - if(desc) *out_desc = desc; - - return res; -error: - if(desc) SENC2D(descriptor_ref_put(desc)); - desc = NULL; - goto exit; -} diff --git a/src/senc2d_scene_analyze_c.h b/src/senc2d_scene_analyze_c.h @@ -16,33 +16,21 @@ #ifndef SENC2D_SCNENE_ANALYZE_C_H #define SENC2D_SCNENE_ANALYZE_C_H -#include "senc2d_scene_c.h" #include "senc2d_internal_types.h" +#include "senc2d.h" #include <rsys/mem_allocator.h> #include <rsys/hash_table.h> #include <rsys/double2.h> -/* Information kept during the building side groups. */ -struct segside { - /* Rank of the segside facing this segside through its vertices */ - side_id_t facing_side_id[2]; - /* Id of this segside's medium */ - medium_id_t medium; - - /* Implicit information that we don't need to store: - * - segment_id - * - side - * This is due to the memory layout of the elt darray: - * front(seg_0), back(seg_0), front(seg_1), back(seg_1), ... */ -}; +struct senc2d_scene; static FINLINE void init_segside(struct mem_allocator* alloc, struct segside* data) { int i; ASSERT(data); (void)alloc; - FOR_EACH(i, 0, 2) data->facing_side_id[i] = SIDE_NULL__; + FOR_EACH(i, 0, 3) data->facing_side_id[i] = SIDE_NULL__; data->medium = MEDIUM_NULL__; } @@ -50,15 +38,14 @@ init_segside(struct mem_allocator* alloc, struct segside* data) #define DARRAY_DATA side_id_t #include <rsys/dynamic_array.h> -/* Descriptors for connex components. +/* Descriptors for connex component. * Define lists of seg sides starting from a given head. - * Also keeps the maximum y info of the component - * along with the associated segment and vertex ids + * Also keeps the maximum z info of the component * and the list of media found */ struct cc_descriptor { /* Does this component is an outer border of an enclosure or an inner one? */ char is_outer_border; - vrtx_id_t max_y_vrtx_id; /* id of the vrtx with max y value */ + vrtx_id_t max_y_vrtx_id; /* id of the vrtx with max z value */ side_id_t side_count; /* Used when grouping components to form enclosures */ component_id_t cc_id; @@ -67,7 +54,7 @@ struct cc_descriptor { /* Range of sides member of this component */ struct side_range side_range; /* Media used by this component */ - unsigned char* media; + uchar* media; }; extern const struct cc_descriptor CC_DESCRIPTOR_NULL; @@ -122,7 +109,7 @@ custom_darray_ptr_component_descriptor_release * - segment_comp for information describing components (kept until * segment_enc is ready) * - segment_enc for information describing enclosures (kept in - * senc2d_descriptor). */ + * struct descriptor). */ struct segment_tmp { double max_y; }; @@ -145,10 +132,10 @@ struct neighbour_info { double angle; seg_id_t seg_id; /* Rank of the vertex in the segment (in [0 1]) */ - unsigned char common_vertex_rank; + uchar common_vertex_rank; /* Does the geometrical normal point towards the next neighbour * (if not, it points towards the previous one)? */ - unsigned char normal_toward_next_neighbour; + uchar normal_toward_next_neighbour; }; #define DARRAY_NAME neighbour #define DARRAY_DATA struct neighbour_info @@ -162,4 +149,7 @@ struct neighbour_info { #define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_neighbour_copy_and_release #include <rsys/dynamic_array.h> +extern LOCAL_SYM res_T +scene_analyze(struct senc2d_scene* scene); + #endif /* SENC2D_SCNENE_ANALYZE_C_H */ diff --git a/src/senc2d_scene_c.h b/src/senc2d_scene_c.h @@ -13,21 +13,123 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef SENC2D_SCNENE_C_H -#define SENC2D_SCNENE_C_H +#ifndef SENC2D_SCENE_C_H +#define SENC2D_SCENE_C_H #include "senc2d_internal_types.h" +#include "senc2d_enclosure_data.h" +#include "senc2d_side_range.h" +#include "senc2d.h" #include <rsys/ref_count.h> #include <rsys/dynamic_array.h> #include <rsys/hash_table.h> struct mem_allocator; +struct senc2d_scene; -#define HTABLE_NAME vrtx_id -#define HTABLE_KEY vrtx_id_t -#define HTABLE_DATA vrtx_id_t -#include <rsys/hash_table.h> +struct segment_comp { + /* The connex component in which each side is. */ + component_id_t component[2]; +}; + +static void +segment_comp_init(struct mem_allocator* alloc, struct segment_comp* seg) { + int i; + (void)alloc; + ASSERT(seg); + FOR_EACH(i, 0, 2) seg->component[i] = COMPONENT_NULL__; +} + +#define DARRAY_NAME segment_comp +#define DARRAY_DATA struct segment_comp +#define DARRAY_FUNCTOR_INIT segment_comp_init +#include <rsys/dynamic_array.h> + +struct segment_enc { + /* The enclosure in which each side is. */ + enclosure_id_t enclosure[2]; +}; + +#ifndef NDEBUG +static void +segment_enc_init(struct mem_allocator* alloc, struct segment_enc* seg) { + int i; + (void)alloc; + ASSERT(seg); + FOR_EACH(i, 0, 2) seg->enclosure[i] = ENCLOSURE_NULL__; +} +#define DARRAY_FUNCTOR_INIT segment_enc_init +#endif + +#define DARRAY_NAME segment_enc +#define DARRAY_DATA struct segment_enc +#include <rsys/dynamic_array.h> + +/* Segment edge struct and basic functions */ +struct seg_edge { + vrtx_id_t vrtx0, vrtx1; +}; + +static FINLINE int +edge_ok(const struct seg_edge* edge) { + return(edge + && edge->vrtx0 <= VRTX_MAX__ + && edge->vrtx1 <= VRTX_MAX__ + && edge->vrtx0 < edge->vrtx1); +} + +static FINLINE void +set_edge + (const vrtx_id_t vrtx0, + const vrtx_id_t vrtx1, + struct seg_edge* edge, + uchar* reversed) +{ + ASSERT(edge && reversed && vrtx0 != vrtx1); + ASSERT(*reversed == UCHAR_MAX); /* Should not be already set. */ + if(vrtx0 < vrtx1) { + edge->vrtx0 = vrtx0; + edge->vrtx1 = vrtx1; + *reversed = 0; /* Non reversed edge */ + } else { + edge->vrtx0 = vrtx1; + edge->vrtx1 = vrtx0; + *reversed = 1; /* Reversed edge */ + } + ASSERT(edge_ok(edge)); +} + +static FINLINE int +edge_eq(const struct seg_edge* e1, const struct seg_edge* e2) +{ + ASSERT(edge_ok(e1) && edge_ok(e2)); + return e1->vrtx0 == e2->vrtx0 && e1->vrtx1 == e2->vrtx1; +} + +/* Information kept during the building of side groups. */ +struct segside { + /* Rank of the segside facing this segside through its edges */ + side_id_t facing_side_id[2]; + /* Id of this segside's medium */ + medium_id_t medium; + + /* Implicit information that we don't need to store: + * - segment_id + * - side + * This is due to the memory layout of the elt darray: + * front(seg_0), back(seg_0), front(seg_1), back(seg_1), ... */ +}; + +/* Frontier vertex type */ +struct frontier_vertex { + seg_id_t seg; + vrtx_id_t vrtx; +}; + +#define DARRAY_NAME frontier_vertex +#define DARRAY_DATA struct frontier_vertex +#include <rsys/dynamic_array.h> union double2 { struct { @@ -41,15 +143,13 @@ union double2 { /* Segment information. * Depending on lifespan, information is kept in different places: * - segment_in for user provided information (kept in scene) - * - segment_comp for information describing components (kept in senc2d_descriptor) - * - segment_cmp for tmp information (kept until segment_comp is ready) */ + * - segment_comp for information describing components (kept in struct descriptor) + * - segment_tmp for tmp information (kept until segment_comp is ready) */ struct segment_in { /* Ids of the segment's vertices */ vrtx_id_t vertice_id[2]; /* Ids of this segment's media */ medium_id_t medium[2]; - /* Segment index in user world regardless of deduplication. */ - unsigned global_id; }; static FINLINE void @@ -58,8 +158,7 @@ segment_in_init(struct mem_allocator* alloc, struct segment_in* seg) { (void)alloc; ASSERT(seg); FOR_EACH(i, 0, 2) seg->vertice_id[i] = VRTX_NULL__; - FOR_EACH(i, 0, 2) seg->medium[i] = SENC2D_UNDEFINED_MEDIUM; - seg->global_id = 0; + FOR_EACH(i, 0, 2) seg->medium[i] = SENC2D_UNSPECIFIED_MEDIUM; } #define DARRAY_NAME segment_in @@ -67,19 +166,6 @@ segment_in_init(struct mem_allocator* alloc, struct segment_in* seg) { #define DARRAY_FUNCTOR_INIT segment_in_init #include <rsys/dynamic_array.h> -static FINLINE void -segment_in_flip(struct segment_in* seg) { - vrtx_id_t v; - medium_id_t m; - ASSERT(seg); - v = seg->vertice_id[1]; - seg->vertice_id[1] = seg->vertice_id[2]; - seg->vertice_id[2] = v; - m = seg->medium[0]; - seg->medium[0] = seg->medium[1]; - seg->medium[1] = m; -} - static FINLINE int vrtx_eq(const union double2* v1, const union double2* v2) { @@ -93,10 +179,6 @@ vrtx_eq(const union double2* v1, const union double2* v2) #define HTABLE_KEY_FUNCTOR_EQ vrtx_eq #include <rsys/hash_table.h> -#define DARRAY_NAME vrtx_id -#define DARRAY_DATA vrtx_id_t -#include <rsys/dynamic_array.h> - union vrtx_id2 { struct { vrtx_id_t v0, v1; @@ -135,51 +217,37 @@ seg_key_eq(const union vrtx_id2* k1, const union vrtx_id2* k2) #define HTABLE_KEY_FUNCTOR_EQ seg_key_eq #include <rsys/hash_table.h> -struct side_range { - side_id_t first, last; +struct descriptor { + enclosure_id_t enclosures_count; + /* Store by-segment enclosures */ + struct darray_segment_enc segments_enc; + /* Store enclosures */ + struct darray_enclosure enclosures; + struct darray_enc_ids_array enc_ids_array_by_medium; + /* Store frontiers */ + struct darray_frontier_vertex frontiers; }; -static FINLINE void -side_range_init(struct mem_allocator* alloc, struct side_range* data) -{ - ASSERT(data); - (void)alloc; - data->first = SIDE_NULL__; - data->last = 0; -} -#define DARRAY_NAME side_range -#define DARRAY_DATA struct side_range -#define DARRAY_FUNCTOR_INIT side_range_init -#include <rsys/dynamic_array.h> struct senc2d_scene { /* Front / Back sides convention */ int convention; - - /* Segment information as given by user; no duplicates here */ + /* Segment information as given by user */ struct darray_segment_in segments_in; - - /* Vertex information as given by user; no duplicates here */ + /* Vertex information as given by user */ struct darray_position vertices; - - /* Htables used to detect duplicate vertices. - * As we rely on edges (i.e. vertice IDs) to build - * neighbourhoods, we need vertice unicity. */ - /* Keep each unique vertex; no duplicates here. */ - struct htable_vrtx unique_vertices; - - /* Htables used to detect duplicate segments. */ - /* Keep each unique segment; no duplicates here. */ - struct htable_seg unique_segments; /* Keep sizes */ - seg_id_t nsegs, nusegs; /* Segment count, unique segment count */ - vrtx_id_t nverts, nuverts; /* Vrtx count, unique vrtx count */ + seg_id_t nsegs; /* Seg count */ + vrtx_id_t nverts; /* Vrtx count */ medium_id_t next_medium_idx; + /* media_use 0 is for SENC2D_UNSPECIFIED_MEDIUM, n+1 is for n */ struct darray_side_range media_use; - side_id_t sides_with_defined_medium_count; + + /* The descriptor of the analyze */ + struct descriptor analyze; ref_T ref; struct senc2d_device* dev; }; -#endif /* SENC2D_SCNENE_C_H */ +#endif /* SENC2D_SCENE_C_H */ diff --git a/src/senc2d_side_range.h b/src/senc2d_side_range.h @@ -0,0 +1,44 @@ +/* Copyright (C) |Meso|Star> 2018-2020 (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/>. */ + +#ifndef SENC2D_SIDE_RANGE_H +#define SENC2D_SIDE_RANGE_H + +#include "senc2d_internal_types.h" + +#include <rsys/dynamic_array.h> + +struct mem_allocator; + +struct side_range { + side_id_t first, last; +}; + +static FINLINE void +side_range_init(struct mem_allocator* alloc, struct side_range* data) +{ + ASSERT(data); + (void)alloc; + data->first = SIDE_NULL__; + data->last = 0; +} + +#define DARRAY_NAME side_range +#define DARRAY_DATA struct side_range +#define DARRAY_FUNCTOR_INIT side_range_init +#include <rsys/dynamic_array.h> + + +#endif /* SENC2D_SCENE_C_H */ diff --git a/src/sencX2d.h b/src/sencX2d.h @@ -0,0 +1,44 @@ +/* Copyright (C) |Meso|Star> 2018-2020 (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/>. */ + +#ifndef SENC_X_2D_H +#define SENC_X_2D_H + +#if !defined(SENCXD_DIM) || (SENCXD_DIM != 2 && SENCXD_DIM != 3) +#error "SENCXD_DIM must be defined; admissible values are 2 and 3" +#endif + +#include <star/senc2d.h> + +/* Star-enclosures-XD macros generic to the SENCXD_DIM */ +#ifndef SENCXD +#define SENCXD CONCAT(CONCAT(SENC, SENCXD_DIM), D) +#endif +#ifndef sencXd +#define sencXd(Name) CONCAT(CONCAT(CONCAT(senc, SENCXD_DIM), d_), Name) +#endif +#ifndef SENCXD_ +#define SENCXD_(Name) CONCAT(CONCAT(CONCAT(SENC, SENCXD_DIM), D_), Name) +#endif + +/* Function names that require additional dedicated macros */ +#define senc2d_scene_get_primitives_count senc2d_scene_get_segments_count +#define senc2d_scene_get_primitive senc2d_scene_get_segment +#define senc2d_scene_get_primitive_media senc2d_scene_get_segment_media +#define senc2d_scene_get_primitive_enclosures senc2d_scene_get_segment_enclosures +#define senc2d_enclosure_get_primitive senc2d_enclosure_get_segment +#define senc2d_enclosure_get_primitive_id senc2d_enclosure_get_segment_id + +#endif /* SENC_X_2D_H */ diff --git a/src/sencX2d_undefs.h b/src/sencX2d_undefs.h @@ -0,0 +1,33 @@ +/* Copyright (C) |Meso|Star> 2018-2020 (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/>. */ + +#ifndef SENC_X_2D_H +#error "The sencX2d.h file must be included priorly to this file." +#endif + +/* Star-enclosures-XD macros generic to the SENCXD_DIM */ +#undef SENCXD +#undef sencXd +#undef SENCXD_ + +/* Function names that require additional dedicated macros */ +#undef senc2d_scene_get_primitives_count +#undef senc2d_scene_get_primitive +#undef senc2d_scene_get_primitive_media +#undef senc2d_scene_get_primitive_enclosures +#undef senc2d_enclosure_get_primitive +#undef senc2d_enclosure_get_primitive_id + +#undef SENC_X_2D_H diff --git a/src/test_senc2d_add_n_merge.c b/src/test_senc2d_add_n_merge.c @@ -1,204 +0,0 @@ -/* Copyright (C) |Meso|Star> 2018-2020 (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 "senc2d.h" -#include "test_senc2d_utils.h" - -/* Manage add_geometry behaviour */ -struct add_geom_ctx { - unsigned add_cpt, merge_cpt; - res_T add_res, merge_res; -}; - -static res_T -add_seg - (const unsigned global_id, - const unsigned iseg, - void* context) -{ - struct context* ctx = context; - struct add_geom_ctx* add_geom_ctx; - ASSERT(ctx); (void)global_id; (void)iseg; - add_geom_ctx = ctx->custom; - if(add_geom_ctx->add_res == RES_OK) ++add_geom_ctx->add_cpt; - return add_geom_ctx->add_res; -} - -static res_T -merge_seg - (const unsigned global_id, - const unsigned iseg, - const int reversed_segment, - const unsigned segment_media[2], - const unsigned merge_media[2], - void* context) -{ - struct context* ctx = context; - struct add_geom_ctx* add_geom_ctx; - ASSERT(ctx && segment_media && merge_media); - (void)global_id; (void)iseg; (void)reversed_segment; (void)segment_media; (void)merge_media; - add_geom_ctx = ctx->custom; - if(add_geom_ctx->merge_res == RES_OK) ++add_geom_ctx->merge_cpt; - return add_geom_ctx->merge_res; -} - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc2d_device* dev = NULL; - struct senc2d_scene* scn = NULL; - struct context ctx; - unsigned i; - struct add_geom_ctx add_geom_ctx; - unsigned media[4]; - const int conv = SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE; - const unsigned media_count = sizeof(media) / sizeof(*media); - (void)argc; (void)argv; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); - OK(senc2d_scene_create(dev, conv, &scn)); - - /* A 2D square. - * 2 enclosures (inside, outside) sharing the same segments, - * but opposite sides */ - ctx.positions = box_vertices; - ctx.indices = box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - ctx.custom = &add_geom_ctx; - d2(ctx.offset, 0, 0); - ctx.front_media = media; - - add_geom_ctx.add_cpt = add_geom_ctx.merge_cpt = 0; - add_geom_ctx.add_res = add_geom_ctx.merge_res = RES_OK; - - /* Geometry with no media information on both sides */ - for (i = 0; i < media_count; i++) media[i] = SENC2D_UNDEFINED_MEDIUM; - ctx.front_media = media; - ctx.back_media = media; - - /* If add fails, add geometry fails the same way */ - add_geom_ctx.add_res = RES_BAD_ARG; - BA(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx)); - CHK(add_geom_ctx.add_cpt == 0); - add_geom_ctx.add_res = RES_MEM_ERR; - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx) == RES_MEM_ERR); - CHK(add_geom_ctx.add_cpt == 0); - - /* Successful add geometry with add callback */ - add_geom_ctx.add_res = RES_OK; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx)); - CHK(add_geom_ctx.add_cpt == media_count); - CHK(add_geom_ctx.merge_cpt == 0); - - /* Clear scene */ - SENC2D(scene_ref_put(scn)); - OK(senc2d_scene_create(dev, conv, &scn)); - - /* Successful add geometry without add callback */ - add_geom_ctx.add_cpt = 0; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, NULL, merge_seg, &ctx)); - CHK(add_geom_ctx.add_cpt == 0); - CHK(add_geom_ctx.merge_cpt == 0); - - /* If merge fails, add geometry fails the same way */ - add_geom_ctx.merge_res = RES_BAD_ARG; - BA(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx)); - CHK(add_geom_ctx.merge_cpt == 0); - add_geom_ctx.merge_res = RES_MEM_ERR; - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx) == RES_MEM_ERR); - CHK(add_geom_ctx.merge_cpt == 0); - - /* Successful add geometry without merge callback */ - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, NULL, &ctx)); - CHK(add_geom_ctx.merge_cpt == 0); - - /* Successful add geometry with merge callback */ - add_geom_ctx.merge_res = RES_OK; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx)); - CHK(add_geom_ctx.merge_cpt == media_count); - add_geom_ctx.merge_cpt = 0; - - /* Geometry with media information on both sides */ - ctx.front_media = medium0; - ctx.back_media = medium1; - - /* Clear scene */ - SENC2D(scene_ref_put(scn)); - OK(senc2d_scene_create(dev, conv, &scn)); - - /* Successful add geometry with add callback */ - add_geom_ctx.add_res = RES_OK; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx)); - CHK(add_geom_ctx.add_cpt == media_count); - CHK(add_geom_ctx.merge_cpt == 0); - add_geom_ctx.add_cpt = 0; - - /* Clear scene */ - SENC2D(scene_ref_put(scn)); - OK(senc2d_scene_create(dev, conv, &scn)); - - /* Successful add geometry with add callback */ - add_geom_ctx.add_res = RES_OK; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx)); - CHK(add_geom_ctx.add_cpt == media_count); - CHK(add_geom_ctx.merge_cpt == 0); - add_geom_ctx.add_cpt = 0; - - /* Successful add geometry with merge callback */ - add_geom_ctx.merge_res = RES_OK; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx)); - CHK(add_geom_ctx.merge_cpt == media_count); - add_geom_ctx.merge_cpt = 0; - - /* Geometry with incompatible media information on both sides */ - ctx.front_media = medium1; - ctx.back_media = medium0; - - /* Unsuccessful add geometry without merge callback */ - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, NULL, &ctx)); - CHK(add_geom_ctx.merge_cpt == 0); - - /* Successful add geometry with merge callback */ - add_geom_ctx.merge_res = RES_OK; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx)); - CHK(add_geom_ctx.merge_cpt == media_count); - add_geom_ctx.merge_cpt = 0; - - SENC2D(scene_ref_put(scn)); - SENC2D(device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - - return 0; -} diff --git a/src/test_senc2d_descriptor.c b/src/test_senc2d_descriptor.c @@ -1,254 +0,0 @@ -/* Copyright (C) |Meso|Star> 2018-2020 (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 "senc2d.h" -#include "test_senc2d_utils.h" - -#include <rsys/float2.h> -#include <rsys/double2.h> - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc2d_device* dev = NULL; - struct senc2d_scene* scn = NULL; - struct senc2d_descriptor* desc = NULL; - struct senc2d_enclosure* enc = NULL; - struct context ctx; - unsigned count, maxm; - unsigned indices[2]; - double coord[2]; - unsigned media[2]; - unsigned enclosures[2]; - (void)argc, (void)argv; - - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - CHK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev) - == RES_OK); - - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - - /* A 2D square */ - ctx.positions = box_vertices; - ctx.indices = box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - d2(ctx.offset, 0, 0); - ctx.front_media = medium0; - ctx.back_media = medium1; - - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); - - CHK(senc2d_descriptor_ref_get(desc) == RES_OK); - CHK(senc2d_descriptor_ref_get(NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_ref_put(NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_ref_put(desc) == RES_OK); - - CHK(senc2d_descriptor_get_max_medium(NULL, &maxm) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_max_medium(desc, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_max_medium(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_max_medium(desc, &maxm) == RES_OK); - - CHK(maxm == 1); - - CHK(senc2d_descriptor_get_enclosure_count(NULL, &count) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_count(desc, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_count(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_count(desc, &count) == RES_OK); - - CHK(count == 2); - - CHK(senc2d_descriptor_get_enclosure_count_by_medium(NULL, 0, &count) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_count_by_medium(desc, 9, &count) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_count_by_medium(desc, 0, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_count_by_medium(NULL, 9, &count) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_count_by_medium(NULL, 0, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_count_by_medium(desc, 9, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_count_by_medium(NULL, 9, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_count_by_medium(desc, 0, &count) - == RES_OK); - - CHK(count == 1); - - CHK(senc2d_descriptor_get_enclosure(desc, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure(desc, 9, &enc) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure(desc, 9, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure(NULL, 0, &enc) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure(NULL, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure(NULL, 9, &enc) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure(NULL, 9, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure(desc, 0, &enc) == RES_OK); - - CHK(senc2d_enclosure_ref_put(enc) == RES_OK); - - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, 0, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, 0, 9, &enc) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, 0, 9, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, 9, 0, &enc) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, 9, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, 9, 9, &enc) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, 9, 9, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(NULL, 0, 0, &enc) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(NULL, 0, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(NULL, 0, 9, &enc) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(NULL, 0, 9, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(NULL, 9, 0, &enc) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(NULL, 9, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(NULL, 9, 9, &enc) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(NULL, 9, 9, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, 0, 0, &enc) == RES_OK); - - CHK(senc2d_descriptor_get_global_vertices_count(NULL, &count) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_vertices_count(desc, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_vertices_count(desc, &count) == RES_OK); - CHK(count == nvertices); - - CHK(senc2d_descriptor_get_global_segments_count(NULL, &count) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segments_count(desc, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segments_count(desc, &count) == RES_OK); - CHK(count == nsegments); - - CHK(senc2d_descriptor_get_global_segment(NULL, 0, indices) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment(NULL, nsegments, indices) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment(desc, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment(desc, 0, indices) == RES_OK); - CHK(indices[0] == box_indices[0] && indices[1] == box_indices[1]); - - CHK(senc2d_descriptor_get_global_vertex(NULL, 0, coord) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_vertex(NULL, nvertices, coord) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_vertex(desc, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_vertex(desc, 0, coord) == RES_OK); - CHK(coord[0] == box_vertices[0] && coord[1] == box_vertices[1]); - - CHK(senc2d_descriptor_get_global_segment_media(NULL, 0, media) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment_media(NULL, nvertices, media) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment_media(desc, 0, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment_media(desc, 0, media) == RES_OK); - CHK(media[0] == ctx.front_media[0] && media[1] == ctx.back_media[1]); - - CHK(senc2d_descriptor_get_global_segment_enclosures(NULL, 0, enclosures) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment_enclosures(NULL, nvertices, enclosures) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment_enclosures(desc, 0, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment_enclosures(desc, 0, enclosures) - == RES_OK); - CHK(enclosures[0] == 0 && enclosures[1] == 1); - - CHK(senc2d_descriptor_get_global_segment_global_id(NULL, 0, indices) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment_global_id(NULL, nvertices, indices) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment_global_id(desc, 0, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_global_segment_global_id(desc, 0, indices) - == RES_OK); - /* No duplicates and no custom id: user id is unique vertex id */ - CHK(indices[0] == 0); - - /* Add valid duplicate geometry */ - CHK(senc2d_descriptor_ref_put(desc) == RES_OK); - desc = NULL; - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); - - CHK(senc2d_descriptor_get_global_vertices_count(desc, &count) == RES_OK); - /* Duplicate vertices have been replaced */ - CHK(count == nvertices); - - CHK(senc2d_descriptor_get_global_segments_count(desc, &count) == RES_OK); - /* Duplicate segments have been replaced */ - CHK(count == nsegments); - - /* Add invalid duplicate geometry */ - CHK(senc2d_descriptor_ref_put(desc) == RES_OK); - desc = NULL; - ctx.front_media = medium1; - ctx.back_media = medium0; - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_BAD_ARG); - - CHK(senc2d_scene_ref_put(scn) == RES_OK); - if(desc) CHK(senc2d_descriptor_ref_put(desc) == RES_OK); - desc = NULL; - CHK(senc2d_enclosure_ref_put(enc) == RES_OK); - - /* Same square with a hole (last segment is missing) */ - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - - CHK(senc2d_scene_add_geometry(scn, nsegments - 1, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); - - CHK(senc2d_descriptor_get_frontier_vertices_count(NULL, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_frontier_vertices_count(desc, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_frontier_vertices_count(NULL, &count) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_frontier_vertices_count(desc, &count) - == RES_OK); - - CHK(senc2d_descriptor_get_frontier_vertex(NULL, count, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_frontier_vertex(desc, count, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_frontier_vertex(NULL, 0, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_frontier_vertex(NULL, count, indices) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_frontier_vertex(desc, 0, NULL) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_frontier_vertex(desc, count, indices) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_frontier_vertex(NULL, 0, indices) - == RES_BAD_ARG); - CHK(senc2d_descriptor_get_frontier_vertex(desc, 0, indices) - == RES_OK); - - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); - if(desc) CHK(senc2d_descriptor_ref_put(desc) == RES_OK); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - - return 0; -} diff --git a/src/test_senc2d_device.c b/src/test_senc2d_device.c @@ -18,6 +18,8 @@ #include <rsys/logger.h> +#include <stdio.h> + static INLINE void log_stream(const char* msg, void* ctx) { @@ -34,40 +36,38 @@ main(int argc, char** argv) struct senc2d_device* dev; (void)argc, (void)argv; - CHK(senc2d_device_create(NULL, NULL, 0, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_device_create(NULL, NULL, 0, 0, &dev) == RES_BAD_ARG); - CHK(senc2d_device_create(NULL, NULL, 1, 0, &dev) == RES_OK); - CHK(senc2d_device_ref_get(NULL) == RES_BAD_ARG); - CHK(senc2d_device_ref_get(dev) == RES_OK); - CHK(senc2d_device_ref_put(NULL) == RES_BAD_ARG); - CHK(senc2d_device_ref_put(dev) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); + BA(senc2d_device_create(NULL, NULL, 0, 0, NULL)); + BA(senc2d_device_create(NULL, NULL, 0, 0, &dev)); + OK(senc2d_device_create(NULL, NULL, 1, 0, &dev)); + BA(senc2d_device_ref_get(NULL)); + OK(senc2d_device_ref_get(dev)); + BA(senc2d_device_ref_put(NULL)); + OK(senc2d_device_ref_put(dev)); + OK(senc2d_device_ref_put(dev)); - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) - == RES_OK); + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); - CHK(senc2d_device_create(NULL, &allocator, 1, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_device_create(NULL, &allocator, 1, 0, &dev) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); + BA(senc2d_device_create(NULL, &allocator, 1, 0, NULL)); + OK(senc2d_device_create(NULL, &allocator, 1, 0, &dev)); + OK(senc2d_device_ref_put(dev)); CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); - CHK(logger_init(&allocator, &logger) == RES_OK); + OK(logger_init(&allocator, &logger)); logger_set_stream(&logger, LOG_OUTPUT, log_stream, NULL); logger_set_stream(&logger, LOG_ERROR, log_stream, NULL); logger_set_stream(&logger, LOG_WARNING, log_stream, NULL); - CHK(senc2d_device_create(&logger, NULL, 1, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_device_create(&logger, NULL, 1, 0, &dev) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); + BA(senc2d_device_create(&logger, NULL, 1, 0, NULL)); + OK(senc2d_device_create(&logger, NULL, 1, 0, &dev)); + OK(senc2d_device_ref_put(dev)); - CHK(senc2d_device_create(&logger, &allocator, 1, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_device_create(&logger, &allocator, 1, 0, &dev) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); + BA(senc2d_device_create(&logger, &allocator, 1, 0, NULL)); + OK(senc2d_device_create(&logger, &allocator, 1, 0, &dev)); + OK(senc2d_device_ref_put(dev)); - CHK(senc2d_device_create - (&logger, &allocator, SENC2D_NTHREADS_DEFAULT, 0, &dev) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); + OK(senc2d_device_create(&logger, &allocator, SENC2D_NTHREADS_DEFAULT, 0, &dev)); + OK(senc2d_device_ref_put(dev)); logger_release(&logger); check_memory_allocator(&allocator); diff --git a/src/test_senc2d_enclosure.c b/src/test_senc2d_enclosure.c @@ -14,7 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "senc2d.h" -#include "senc2d_s2d_wrapper.h" +#include "senc2d_sXd_helper.h" #include "test_senc2d_utils.h" #include <rsys/double2.h> @@ -25,7 +25,6 @@ static void test(const int convention) { struct mem_allocator allocator; - struct senc2d_descriptor* desc = NULL; struct senc2d_device* dev = NULL; struct senc2d_scene* scn = NULL; struct senc2d_enclosure* enclosures[2] = { NULL, NULL }; @@ -40,157 +39,120 @@ test(const int convention) unsigned gid; enum senc2d_side side; double vrtx[2]; - struct context ctx; - unsigned i, n, s, ecount; + struct context ctx = CONTEXT_NULL__; + unsigned i, n, s, count; int conv; const int conv_front = (convention & SENC2D_CONVENTION_NORMAL_FRONT) != 0; const int conv_in = (convention & SENC2D_CONVENTION_NORMAL_INSIDE) != 0; - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - CHK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev) - == RES_OK); - - CHK(senc2d_scene_create(dev, convention, &scn) == RES_OK); - - CHK(senc2d_scene_get_convention(scn, &conv) == RES_OK); - CHK(conv == convention); - - s2d_attribs.type = S2D_FLOAT2; - s2d_attribs.usage = S2D_POSITION; - s2d_attribs.get = senc2d_enclosure_get_vertex__; - - CHK(s2d_device_create(NULL, &allocator, 0, &s2d) == RES_OK); - - CHK(s2d_scene_create(s2d, &s2d_scn) == RES_OK); + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); /* A 2D square. * 2 enclosures (inside, outside) sharing the same segments, * but opposite sides */ ctx.positions = box_vertices; ctx.indices = box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - d2(ctx.offset, 0, 0); ctx.front_media = medium0; ctx.back_media = medium1; - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); + OK(senc2d_scene_create(dev, convention, nsegments, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); + OK(senc2d_scene_get_convention(scn, &conv)); + CHK(conv == convention); - CHK(senc2d_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); - CHK(ecount == 2); + OK(senc2d_scene_get_enclosure_count(scn, &count)); + CHK(count == 2); - CHK(senc2d_descriptor_get_enclosure(desc, 0, &enclosure) == RES_OK); - CHK(senc2d_enclosure_ref_get(NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_ref_get(enclosure) == RES_OK); - CHK(senc2d_enclosure_ref_put(NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_ref_put(enclosure) == RES_OK); - - CHK(senc2d_enclosure_get_segment(NULL, 0, indices[0]) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment(enclosure, nsegments, indices[0]) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment(enclosure, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment(NULL, nsegments, indices[0]) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment(NULL, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment(enclosure, nsegments, NULL) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment(NULL, nsegments, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment(enclosure, 0, indices[0]) == RES_OK); - - CHK(senc2d_enclosure_get_vertex(NULL, 0, vrtx) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_vertex(enclosure, nvertices, vrtx) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_vertex(enclosure, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_vertex(NULL, nvertices, vrtx) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_vertex(NULL, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_vertex(enclosure, nvertices, NULL) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_vertex(NULL, nvertices, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_vertex(enclosure, 0, vrtx) == RES_OK); - - CHK(senc2d_enclosure_get_segment_global_id(NULL, 0, &gid, NULL) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(enclosure, nsegments, &gid, NULL) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(enclosure, 0, NULL, NULL) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(NULL, nsegments, &gid, NULL) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(NULL, 0, NULL, NULL) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(enclosure, nsegments, NULL, NULL) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(NULL, nsegments, NULL, NULL) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(enclosure, 0, &gid, NULL) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(NULL, 0, &gid, &side) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(enclosure, nsegments, &gid, &side) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(enclosure, 0, NULL, &side) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(NULL, nsegments, &gid, &side) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(NULL, 0, NULL, &side) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(enclosure, nsegments, NULL, &side) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(NULL, nsegments, NULL, &side) - == RES_BAD_ARG); - CHK(senc2d_enclosure_get_segment_global_id(enclosure, 0, &gid, &side) - == RES_OK); - - CHK(senc2d_enclosure_get_medium(NULL, 0, &medium) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_medium(enclosure, 2, &medium) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_medium(enclosure, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_medium(NULL, 2, &medium) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_medium(NULL, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_medium(enclosure, 2, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_medium(NULL, 2, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_medium(enclosure, 0, &medium) == RES_OK); - - CHK(senc2d_enclosure_ref_put(enclosure) == RES_OK); - - FOR_EACH(i, 0, ecount) { - CHK(senc2d_descriptor_get_enclosure(desc, i, &enclosure) == RES_OK); - - CHK(senc2d_enclosure_get_header(NULL, &header) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_header(enclosure, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_header(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_header(enclosure, &header) == RES_OK); + OK(senc2d_scene_get_enclosure(scn, 0, &enclosure)); + BA(senc2d_enclosure_ref_get(NULL)); + OK(senc2d_enclosure_ref_get(enclosure)); + BA(senc2d_enclosure_ref_put(NULL)); + OK(senc2d_enclosure_ref_put(enclosure)); + + BA(senc2d_enclosure_get_segment(NULL, 0, indices[0])); + BA(senc2d_enclosure_get_segment(enclosure, nsegments, indices[0])); + BA(senc2d_enclosure_get_segment(enclosure, 0, NULL)); + BA(senc2d_enclosure_get_segment(NULL, nsegments, indices[0])); + BA(senc2d_enclosure_get_segment(NULL, 0, NULL)); + BA(senc2d_enclosure_get_segment(enclosure, nsegments, NULL)); + BA(senc2d_enclosure_get_segment(NULL, nsegments, NULL)); + OK(senc2d_enclosure_get_segment(enclosure, 0, indices[0])); + + BA(senc2d_enclosure_get_vertex(NULL, 0, vrtx)); + BA(senc2d_enclosure_get_vertex(enclosure, nvertices, vrtx)); + BA(senc2d_enclosure_get_vertex(enclosure, 0, NULL)); + BA(senc2d_enclosure_get_vertex(NULL, nvertices, vrtx)); + BA(senc2d_enclosure_get_vertex(NULL, 0, NULL)); + BA(senc2d_enclosure_get_vertex(enclosure, nvertices, NULL)); + BA(senc2d_enclosure_get_vertex(NULL, nvertices, NULL)); + OK(senc2d_enclosure_get_vertex(enclosure, 0, vrtx)); + + BA(senc2d_enclosure_get_segment_id(NULL, 0, &gid, NULL)); + BA(senc2d_enclosure_get_segment_id(enclosure, nsegments, &gid, NULL)); + BA(senc2d_enclosure_get_segment_id(enclosure, 0, NULL, NULL)); + BA(senc2d_enclosure_get_segment_id(NULL, nsegments, &gid, NULL)); + BA(senc2d_enclosure_get_segment_id(NULL, 0, NULL, NULL)); + BA(senc2d_enclosure_get_segment_id(enclosure, nsegments, NULL, NULL)); + BA(senc2d_enclosure_get_segment_id(NULL, nsegments, NULL, NULL)); + BA(senc2d_enclosure_get_segment_id(enclosure, 0, &gid, NULL)); + BA(senc2d_enclosure_get_segment_id(NULL, 0, &gid, &side)); + BA(senc2d_enclosure_get_segment_id(enclosure, nsegments, &gid, &side)); + BA(senc2d_enclosure_get_segment_id(enclosure, 0, NULL, &side)); + BA(senc2d_enclosure_get_segment_id(NULL, nsegments, &gid, &side)); + BA(senc2d_enclosure_get_segment_id(NULL, 0, NULL, &side)); + BA(senc2d_enclosure_get_segment_id(enclosure, nsegments, NULL, &side)); + BA(senc2d_enclosure_get_segment_id(NULL, nsegments, NULL, &side)); + OK(senc2d_enclosure_get_segment_id(enclosure, 0, &gid, &side)); + + BA(senc2d_enclosure_get_medium(NULL, 0, &medium)); + BA(senc2d_enclosure_get_medium(enclosure, 2, &medium)); + BA(senc2d_enclosure_get_medium(enclosure, 0, NULL)); + BA(senc2d_enclosure_get_medium(NULL, 2, &medium)); + BA(senc2d_enclosure_get_medium(NULL, 0, NULL)); + BA(senc2d_enclosure_get_medium(enclosure, 2, NULL)); + BA(senc2d_enclosure_get_medium(NULL, 2, NULL)); + OK(senc2d_enclosure_get_medium(enclosure, 0, &medium)); + + OK(senc2d_enclosure_ref_put(enclosure)); + + FOR_EACH(i, 0, count) { + OK(senc2d_scene_get_enclosure(scn, i, &enclosure)); + + BA(senc2d_enclosure_get_header(NULL, &header)); + BA(senc2d_enclosure_get_header(enclosure, NULL)); + BA(senc2d_enclosure_get_header(NULL, NULL)); + OK(senc2d_enclosure_get_header(enclosure, &header)); CHK(header.enclosure_id == i); CHK(header.enclosed_media_count == 1); - CHK(senc2d_enclosure_get_medium(enclosure, 0, &medium) == RES_OK); + OK(senc2d_enclosure_get_medium(enclosure, 0, &medium)); /* Geometrical normals point outside the square in input segments: * if convention is front, front medium (0) is outside, * that is medium 0's enclosure is infinite */ CHK(conv_front == ((medium == 0) == header.is_infinite)); - CHK(header.segment_count == nsegments); - CHK(header.unique_segment_count == nsegments); + CHK(header.primitives_count == nsegments); + CHK(header.unique_primitives_count == nsegments); CHK(header.vertices_count == nvertices); + CHK(header.is_infinite == (i == 0)); - FOR_EACH(s, 0, header.segment_count) { - CHK(senc2d_enclosure_get_segment_global_id(enclosure, s, &gid, &side) == RES_OK); + FOR_EACH(s, 0, header.primitives_count) { + OK(senc2d_enclosure_get_segment_id(enclosure, s, &gid, &side)); CHK(gid == s); CHK(side == (medium == 0) ? SENC2D_FRONT : SENC2D_BACK); } - CHK(senc2d_enclosure_ref_put(enclosure) == RES_OK); + OK(senc2d_enclosure_ref_put(enclosure)); } FOR_EACH(i, 0, 2) - CHK(senc2d_descriptor_get_enclosure(desc, i, enclosures + i) == RES_OK); + OK(senc2d_scene_get_enclosure(scn, i, enclosures + i)); FOR_EACH(n, 0, nsegments) { int same, reversed; /* Read same segments in both enclosures */ FOR_EACH(i, 0, 2) - CHK(senc2d_enclosure_get_segment(enclosures[i], n, indices[i]) == RES_OK); + OK(senc2d_enclosure_get_segment(enclosures[i], n, indices[i])); /* Same segments and opposite sides for the 2 enclosures */ FOR_EACH(i, 0, 2) CHK(indices[0][i] == indices[1][1 - i]); /* Enclosure 0 is outside (and contains medium 0 if convention is front). @@ -203,74 +165,70 @@ test(const int convention) CHK(same && reversed == conv_in); } FOR_EACH(i, 0, 2) - CHK(senc2d_enclosure_ref_put(enclosures[i]) == RES_OK); + OK(senc2d_enclosure_ref_put(enclosures[i])); - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_descriptor_ref_put(desc) == RES_OK); + OK(senc2d_scene_ref_put(scn)); /* Same 2D square, but with a hole (incomplete). * 1 single enclosure including both sides of segments */ - CHK(senc2d_scene_create(dev, convention, &scn) == RES_OK); - ctx.positions = box_vertices; ctx.indices = box_indices; - ctx.scale = 1; - d2(ctx.offset, 0, 0); ctx.front_media = medium0; ctx.back_media = medium1; - CHK(senc2d_scene_add_geometry(scn, nsegments - 1, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); + OK(senc2d_scene_create(dev, convention, nsegments - 1, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); + OK(senc2d_scene_get_frontier_vertice_count(scn, &count)); + CHK(count == 2); - CHK(senc2d_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); - CHK(ecount == 1); + OK(senc2d_scene_get_enclosure_count(scn, &count)); + CHK(count == 1); - dump_enclosure(desc, 0, "test2d_enclosure_hole.obj"); +#ifdef DUMP_ENCLOSURES + dump_enclosure(scn, 0, "test_enclosure_hole.obj"); +#endif - CHK(senc2d_descriptor_get_enclosure(desc, 0, &enclosure) == RES_OK); + OK(senc2d_scene_get_enclosure(scn, 0, &enclosure)); - CHK(senc2d_enclosure_get_header(NULL, &header) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_header(enclosure, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_header(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_enclosure_get_header(enclosure, &header) == RES_OK); + BA(senc2d_enclosure_get_header(NULL, &header)); + BA(senc2d_enclosure_get_header(enclosure, NULL)); + BA(senc2d_enclosure_get_header(NULL, NULL)); + OK(senc2d_enclosure_get_header(enclosure, &header)); CHK(header.enclosure_id == 0); CHK(header.enclosed_media_count == 2); - CHK(header.segment_count == 2 * header.unique_segment_count); - CHK(header.unique_segment_count == nsegments - 1); + CHK(header.primitives_count == 2 * header.unique_primitives_count); + CHK(header.unique_primitives_count == nsegments - 1); CHK(header.vertices_count == nvertices); CHK(header.is_infinite == 1); - FOR_EACH(s, 0, header.segment_count) { - CHK(senc2d_enclosure_get_segment_global_id(enclosure, s, &gid, &side) == RES_OK); - /* The first unique_segment_count segments of an enclosure + FOR_EACH(s, 0, header.primitives_count) { + OK(senc2d_enclosure_get_segment_id(enclosure, s, &gid, &side)); + /* The first unique_primitives_count segments of an enclosure * are unique segments */ - if(s < header.unique_segment_count) CHK(gid == s); - CHK(side == (s < header.unique_segment_count) ? SENC2D_FRONT : SENC2D_BACK); - } - - FOR_EACH(n, 0, header.unique_segment_count) { - /* Put geometry in a 2D view */ - CHK(s2d_shape_create_line_segments(s2d, &s2d_shp) == RES_OK); - - CHK(s2d_line_segments_setup_indexed_vertices(s2d_shp, header.segment_count, - senc2d_enclosure_get_segment__, header.vertices_count, &s2d_attribs, - 1, enclosure) - == RES_OK); - - CHK(s2d_scene_attach_shape(s2d_scn, s2d_shp) == RES_OK); - S2D(shape_ref_put(s2d_shp)); + if(s < header.unique_primitives_count) CHK(gid == s); + CHK(side == (s < header.unique_primitives_count) ? SENC2D_FRONT : SENC2D_BACK); } + /* Put geometry in a 2D view using helper functions */ + s2d_attribs.type = S2D_FLOAT2; + s2d_attribs.usage = S2D_POSITION; + s2d_attribs.get = senc2d_sXd_enclosure_get_position; + OK(s2d_device_create(NULL, &allocator, 0, &s2d)); + OK(s2d_scene_create(s2d, &s2d_scn)); + S2D(shape_create_line_segments(s2d, &s2d_shp)); + S2D(line_segments_setup_indexed_vertices(s2d_shp, header.primitives_count, + senc2d_sXd_enclosure_get_indices, header.vertices_count, &s2d_attribs, + 1, enclosure)); + OK(s2d_scene_attach_shape(s2d_scn, s2d_shp)); + S2D(shape_ref_put(s2d_shp)); S2D(device_ref_put(s2d)); S2D(scene_ref_put(s2d_scn)); SENC2D(scene_ref_put(scn)); SENC2D(device_ref_put(dev)); - SENC2D(descriptor_ref_put(desc)); SENC2D(enclosure_ref_put(enclosure)); check_memory_allocator(&allocator); @@ -281,7 +239,7 @@ test(const int convention) int main(int argc, char** argv) { - (void) argc, (void) argv; + (void)argc, (void)argv; test(SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE); test(SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_INSIDE); test(SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_OUTSIDE); diff --git a/src/test_senc2d_inconsistant_square.c b/src/test_senc2d_inconsistant_square.c @@ -14,13 +14,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "senc2d.h" -#include "senc2d_s2d_wrapper.h" #include "test_senc2d_utils.h" #include <rsys/double2.h> /* The following array lists the indices toward the 2D vertices of each -* segment. + * segment. * Y * 2----3 | * | | 0----X @@ -47,45 +46,35 @@ static void test(const int convention) { struct mem_allocator allocator; - struct senc2d_descriptor* desc = NULL; struct senc2d_device* dev = NULL; struct senc2d_scene* scn = NULL; struct senc2d_enclosure* enclosure; struct senc2d_enclosure_header header; int conv; int conv_front, conv_in; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned i, e, ecount; - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - CHK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev) - == RES_OK); - - CHK(senc2d_scene_create(dev, convention, &scn) == RES_OK); + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); /* A 2D square. * 2 enclosures (inside, outside) sharing the same segments, * but opposite sides. * What differs in this test is that segment #0 vertices are given - * in the opposite order. */ + * in the opposite rotation order. */ ctx.positions = box_vertices; ctx.indices = inconsistant_box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - d2(ctx.offset, 0, 0); ctx.front_media = inconsistant_medium_front; ctx.back_media = inconsistant_medium_back; - CHK(senc2d_scene_add_geometry(scn, inconsistant_box_nsegments, get_indices, - get_media, nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); + OK(senc2d_scene_create(dev, convention, inconsistant_box_nsegments, + get_indices, get_media, nvertices, get_position, &ctx, &scn)); - CHK(senc2d_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); + OK(senc2d_scene_get_enclosure_count(scn, &ecount)); CHK(ecount == 2); - CHK(senc2d_scene_get_convention(scn, &conv) == RES_OK); + OK(senc2d_scene_get_convention(scn, &conv)); CHK(conv == convention); conv_front = (conv & SENC2D_CONVENTION_NORMAL_FRONT) != 0; conv_in = (conv & SENC2D_CONVENTION_NORMAL_INSIDE) != 0; @@ -95,10 +84,11 @@ test(const int convention) char name[128]; enum senc2d_side side, expected_side; unsigned gid; - CHK(senc2d_descriptor_get_enclosure(desc, e, &enclosure) == RES_OK); - CHK(senc2d_enclosure_get_header(enclosure, &header) == RES_OK); + (void)name; + OK(senc2d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); CHK(header.enclosed_media_count == 1); - CHK(senc2d_enclosure_get_medium(enclosure, 0, &medium) == RES_OK); + OK(senc2d_enclosure_get_medium(enclosure, 0, &medium)); /* If NORMAL_FRONT the external enclosure's medium should be 0, * 1 if NORMAL_BACK */ expected_external_medium = conv_front ? 0 : 1; @@ -106,11 +96,13 @@ test(const int convention) expected_external_medium : !expected_external_medium); CHK(medium == expected_medium); +#ifdef DUMP_ENCLOSURES sprintf(name, "test_inconsistant_square_%s_%s_%u.obj", conv_front ? "front" : "back", conv_in ? "in" : "out", e); - dump_enclosure(desc, e, name); + dump_enclosure(scn, e, name); +#endif - FOR_EACH(i, 0, header.segment_count) { + FOR_EACH(i, 0, header.primitives_count) { int same, reversed, fst_reversed; fst_reversed = ((e == 0) == conv_in); expected_side = (inconsistant_medium_front[i] == expected_medium) @@ -121,7 +113,7 @@ test(const int convention) /* Should be made of the same segments */ CHK(same); CHK(i ? reversed != fst_reversed : reversed == fst_reversed); - CHK(senc2d_enclosure_get_segment_global_id(enclosure, i, &gid, &side) == RES_OK); + OK(senc2d_enclosure_get_segment_id(enclosure, i, &gid, &side)); CHK(side == expected_side); } SENC2D(enclosure_ref_put(enclosure)); @@ -129,7 +121,6 @@ test(const int convention) SENC2D(scene_ref_put(scn)); SENC2D(device_ref_put(dev)); - SENC2D(descriptor_ref_put(desc)); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); @@ -138,11 +129,12 @@ test(const int convention) int main(int argc, char** argv) { - (void) argc, (void) argv; + (void)argc, (void)argv; test(SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE); test(SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_INSIDE); test(SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_OUTSIDE); test(SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_OUTSIDE); + return 0; } diff --git a/src/test_senc2d_many_enclosures.c b/src/test_senc2d_many_enclosures.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2018-2020 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2016-2020 (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 @@ -13,79 +13,42 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/* This test is similar to test_senc2d_some_enclosures, but involves 64*64*64 + * circles instead of 4*4*4, thus making it impossible to define the geometry + * through static arrays. */ + +#define NB_CIRC_X 32 +#define NB_CIRC_Y 32 +#define NB_CIRC_Z 64 +/* 64^3 = 262144 circles */ +#define NB_CIRC (NB_CIRC_X * NB_CIRC_Y * NB_CIRC_Z) + #include "senc2d.h" #include "test_senc2d_utils.h" +#include "test_senc2d_utils2.h" -#include <rsys/double2.h> -#include <rsys/stretchy_array.h> #include <rsys/clock_time.h> +#include <rsys/double2.h> +#include <stdio.h> #include <limits.h> -static void -get_ctx_indices(const unsigned iseg, unsigned ids[2], void* context) -{ - struct context* ctx = context; - (void)ctx; - ASSERT(ids && ctx); - ASSERT(2 * iseg + 1 < sa_size(ctx->indices)); - get_indices(iseg, ids, context); -} - -static void -get_ctx_position(const unsigned ivert, double pos[2], void* context) -{ - struct context* ctx = context; - (void)ctx; - ASSERT(pos && ctx); - ASSERT(2 * ivert + 1 < sa_size(ctx->positions)); - get_position(ivert, pos, context); -} - -static void -get_ctx_media(const unsigned iseg, unsigned medium[2], void* context) -{ - struct context* ctx = context; - (void)iseg; - ASSERT(medium && ctx); - medium[ctx->reverse_med ? 1 : 0] = *ctx->front_media; - medium[ctx->reverse_med ? 0 : 1] = *ctx->back_media; -} - int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc2d_descriptor* desc = NULL; struct senc2d_device* dev = NULL; struct senc2d_scene* scn = NULL; - struct context ctx; - unsigned m_in, m_out; + struct context ctx = CONTEXT_NULL__; unsigned count; unsigned circ_seg_count, circ_vrtx_count, e; - int i, j, k; char dump[64]; struct time t0, t1; (void)argc, (void)argv; - CHK(mem_init_regular_allocator(&allocator) == RES_OK); - CHK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev) - == RES_OK); + OK(mem_init_regular_allocator(&allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); -#define NB_CIRC_1 64 - /* 64^3 = 262144 circles */ -#define NB_CIRC (NB_CIRC_1 * NB_CIRC_1 * NB_CIRC_1) - /* Create the scene */ - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - - ctx.positions = NULL; - ctx.indices = NULL; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - ctx.front_media = &m_in; - ctx.back_media = &m_out; /* A 16 segments circle template */ create_circle(1, 16, &ctx); ASSERT(sa_size(ctx.positions) % 2 == 0 @@ -94,61 +57,48 @@ main(int argc, char** argv) && sa_size(ctx.indices) / 2 < UINT_MAX); circ_seg_count = (unsigned)sa_size(ctx.indices) / 2; circ_vrtx_count = (unsigned)sa_size(ctx.positions) / 2; - CHK(senc2d_scene_reserve(scn, NB_CIRC * circ_vrtx_count, NB_CIRC * circ_seg_count, 0) - == RES_OK); - FOR_EACH(i, 0, NB_CIRC_1) { - double center_x = 2 * (1 + NB_CIRC_1) * (i - NB_CIRC_1 / 2); - FOR_EACH(j, 0, NB_CIRC_1) { - FOR_EACH(k, 0, NB_CIRC_1) { - double center_y = 2 * (1 + NB_CIRC_1) * (j - NB_CIRC_1 / 2); - m_in = (unsigned)k; - m_out = (unsigned)(k + 1); - ctx.scale = k + 1; - d2(ctx.offset, center_x, center_y); - CHK(senc2d_scene_add_geometry(scn, circ_seg_count, get_ctx_indices, - get_ctx_media, circ_vrtx_count, get_ctx_position, NULL, NULL, &ctx) - == RES_OK); - } - } - } - circle_release(&ctx); + /* Create the scene with NB_CIRC circles. + * There are NB_CIRC_X * NB_CIRC_Y imbrications of NB_CIRC_Z circles each. + * Each imbrication is located on a grid. + * The get_ctx_xxx getters have to retrieve the circle from the + * primitive and vertice indexes. */ time_current(&t0); - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + NB_CIRC * circ_seg_count, get_ctx_indices, get_ctx_media, + NB_CIRC * circ_vrtx_count, get_ctx_position, &ctx, &scn)); time_sub(&t0, time_current(&t1), &t0); time_dump(&t0, TIME_MSEC | TIME_SEC | TIME_MIN, NULL, dump, sizeof(dump)); - printf("Scene analyzed in: %s\n", dump); - - /* dump_global(desc, "test2d_many_enclosures.obj"); */ + printf("Scene created in: %s\n", dump); + circle_release(&ctx); - CHK(senc2d_descriptor_get_global_vertices_count(desc, &count) == RES_OK); + OK(senc2d_scene_get_vertices_count(scn, &count)); CHK(count == NB_CIRC * circ_vrtx_count); - CHK(senc2d_descriptor_get_global_segments_count(desc, &count) == RES_OK); + OK(senc2d_scene_get_segments_count(scn, &count)); CHK(count == NB_CIRC * circ_seg_count); - CHK(senc2d_descriptor_get_enclosure_count(desc, &count) == RES_OK); + OK(senc2d_scene_get_enclosure_count(scn, &count)); CHK(count == 1 + NB_CIRC); - FOR_EACH(e, 0, count) { struct senc2d_enclosure* enclosure; struct senc2d_enclosure_header header; unsigned m; - CHK(senc2d_descriptor_get_enclosure(desc, e, &enclosure) == RES_OK); - CHK(senc2d_enclosure_get_header(enclosure, &header) == RES_OK); + OK(senc2d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); CHK(header.enclosed_media_count == 1); - CHK(senc2d_enclosure_get_medium(enclosure, 0, &m) == RES_OK); - CHK(header.segment_count == - (header.is_infinite /* Outermost enclosure: NB_CIRC_1*NB_CIRC_1 circles */ - ? NB_CIRC_1 * NB_CIRC_1 * circ_seg_count + OK(senc2d_enclosure_get_medium(enclosure, 0, &m)); + CHK(header.primitives_count == + (header.is_infinite /* Outermost enclosure: NB_CIRC_X*NB_CIRC_Y circles */ + ? NB_CIRC_X * NB_CIRC_Y * circ_seg_count : (m == 0 - ? circ_seg_count /* Innermost enclosures: 1 circle */ + ? circ_seg_count /* Innermost enclosures: 1 circles */ : 2 * circ_seg_count))); /* Other enclosures: 2 circles */ - CHK(senc2d_enclosure_ref_put(enclosure) == RES_OK); + OK(senc2d_enclosure_ref_put(enclosure)); } - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); - CHK(senc2d_descriptor_ref_put(desc) == RES_OK); + OK(senc2d_scene_ref_put(scn)); + OK(senc2d_device_ref_put(dev)); check_memory_allocator(&allocator); mem_shutdown_regular_allocator(&allocator); diff --git a/src/test_senc2d_many_segments.c b/src/test_senc2d_many_segments.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2018-2020 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2016-2020 (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 @@ -13,77 +13,43 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/* This test is similar to test_senc2d_some_segments, but involves 4*2562560 + * segments instead of 4*1054, thus making it impossible to define the geometry + * through static arrays. */ + +#define NB_CIRC_X 2 +#define NB_CIRC_Y 1 +#define NB_CIRC_Z 1 + /* 4 circles */ +#define NB_CIRC (NB_CIRC_X * NB_CIRC_Y * NB_CIRC_Z) + #include "senc2d.h" #include "test_senc2d_utils.h" +#include "test_senc2d_utils2.h" -#include <rsys/double2.h> -#include <rsys/stretchy_array.h> #include <rsys/clock_time.h> +#include <rsys/double2.h> +#include <stdio.h> #include <limits.h> -static void -get_ctx_indices(const unsigned iseg, unsigned ids[2], void* context) -{ - struct context* ctx = context; - (void)ctx; - ASSERT(ids && ctx); - ASSERT(2*iseg+1 < sa_size(ctx->indices)); - get_indices(iseg, ids, context); -} - -static void -get_ctx_position(const unsigned ivert, double pos[2], void* context) -{ - struct context* ctx = context; - (void)ctx; - ASSERT(pos && ctx); - ASSERT(2*ivert+1 < sa_size(ctx->positions)); - get_position(ivert, pos, context); -} - -static void -get_ctx_media(const unsigned iseg, unsigned medium[2], void* context) -{ - struct context* ctx = context; - (void)iseg; - ASSERT(medium && ctx); - medium[ctx->reverse_med ? 1 : 0] = *ctx->front_media; - medium[ctx->reverse_med ? 0 : 1] = *ctx->back_media; -} - int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc2d_descriptor* desc = NULL; struct senc2d_device* dev = NULL; struct senc2d_scene* scn = NULL; - struct context ctx; - unsigned m0 = 0, m1; + struct context ctx = CONTEXT_NULL__; + unsigned m0 = 0; unsigned count; - unsigned circ_seg_count, circ_vrtx_count, i; + unsigned circ_seg_count, circ_vrtx_count, e; char dump[64]; struct time t0, t1; (void)argc, (void)argv; - CHK(mem_init_regular_allocator(&allocator) == RES_OK); - CHK(senc2d_device_create (NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev) - == RES_OK); + OK(mem_init_regular_allocator(&allocator)); + OK(senc2d_device_create (NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); -#define NB_CIRC 4 - /* Create the scene */ - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - - ctx.positions = NULL; - ctx.indices = NULL; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - ctx.back_media = &m0; - ctx.front_media = &m1; /* A 1,048,576 segments circle template */ create_circle(1, 1048576, &ctx); ASSERT(sa_size(ctx.positions) % 2 == 0 @@ -92,45 +58,40 @@ main(int argc, char** argv) && sa_size(ctx.indices) / 2 < UINT_MAX); circ_seg_count = (unsigned)sa_size(ctx.indices) / 2; circ_vrtx_count = (unsigned)sa_size(ctx.positions) / 2; - CHK(senc2d_scene_reserve(scn, NB_CIRC * circ_vrtx_count, NB_CIRC * circ_seg_count, 0) - == RES_OK); - FOR_EACH(i, 0, NB_CIRC) { - m1 = i; - d2(ctx.offset, 0, i * 10); - CHK(senc2d_scene_add_geometry(scn, circ_seg_count, get_ctx_indices, - get_ctx_media, circ_vrtx_count, get_ctx_position, NULL, NULL, &ctx) - == RES_OK); - } - circle_release(&ctx); + /* Create the scene with 4 circles. + * The get_ctx_xxx getters have to retrieve the circle from the + * primitive and vertice indexes. */ + ctx.back_media = &m0; time_current(&t0); - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + NB_CIRC* circ_seg_count, get_ctx_indices, get_ctx_media, + NB_CIRC* circ_vrtx_count, get_ctx_position, &ctx, &scn)); time_sub(&t0, time_current(&t1), &t0); time_dump(&t0, TIME_MSEC | TIME_SEC | TIME_MIN, NULL, dump, sizeof(dump)); - printf("Scene analyzed in: %s\n", dump); - - /* dump_global(desc, "test2d_many_segments.obj"); */ + printf("Scene created in: %s\n", dump); + circle_release(&ctx); - CHK(senc2d_descriptor_get_global_vertices_count(desc, &count) == RES_OK); + OK(senc2d_scene_get_vertices_count(scn, &count)); CHK(count == NB_CIRC * circ_vrtx_count); - CHK(senc2d_descriptor_get_global_segments_count(desc, &count) == RES_OK); + OK(senc2d_scene_get_segments_count(scn, &count)); CHK(count == NB_CIRC * circ_seg_count); - CHK(senc2d_descriptor_get_enclosure_count(desc, &count) == RES_OK); + OK(senc2d_scene_get_enclosure_count(scn, &count)); CHK(count == 1 + NB_CIRC); - FOR_EACH(i, 0, count) { + FOR_EACH(e, 0, count) { struct senc2d_enclosure* enclosure; struct senc2d_enclosure_header header; - CHK(senc2d_descriptor_get_enclosure(desc, i, &enclosure) == RES_OK); - CHK(senc2d_enclosure_get_header(enclosure, &header) == RES_OK); - CHK(header.segment_count == - i ? circ_seg_count : NB_CIRC * circ_seg_count); - CHK(senc2d_enclosure_ref_put(enclosure) == RES_OK); + OK(senc2d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); + CHK(header.primitives_count == + e ? circ_seg_count : NB_CIRC * circ_seg_count); + OK(senc2d_enclosure_ref_put(enclosure)); } - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); - CHK(senc2d_descriptor_ref_put(desc) == RES_OK); + OK(senc2d_scene_ref_put(scn)); + OK(senc2d_device_ref_put(dev)); check_memory_allocator(&allocator); mem_shutdown_regular_allocator(&allocator); diff --git a/src/test_senc2d_sample_enclosure.c b/src/test_senc2d_sample_enclosure.c @@ -14,7 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "senc2d.h" -#include "senc2d_s2d_wrapper.h" +#include "senc2d_sXd_helper.h" #include "test_senc2d_utils.h" #include <rsys/float2.h> @@ -27,7 +27,6 @@ int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc2d_descriptor* desc = NULL; struct senc2d_device* dev = NULL; struct senc2d_scene* scn = NULL; struct senc2d_enclosure* enclosure = NULL; @@ -39,74 +38,57 @@ main(int argc, char** argv) struct s2d_primitive prim; struct s2d_vertex_data vrtx_get; struct ssp_rng* rng; - struct context ctx; + struct context ctx = CONTEXT_NULL__; int i; - float s; + float st; (void)argc, (void)argv; - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - CHK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev) - == RES_OK); - - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - - vrtx_get.type = S2D_FLOAT2; - vrtx_get.usage = S2D_POSITION; - vrtx_get.get = senc2d_enclosure_get_vertex__; - - S2D(device_create(NULL, &allocator, 0, &s2d)); - - S2D(scene_create(s2d, &s2d_scn)); + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); /* A 2D square, but with a hole (incomplete). * 1 single enclosure including both sides of segments */ - - ctx.positions = square_vertices; /* Need a true square */ + ctx.positions = square_vertices; ctx.indices = box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - d2(ctx.offset, 0, 0); ctx.front_media = medium0; ctx.back_media = medium0; - CHK(senc2d_scene_add_geometry(scn, nsegments - 1, get_indices, - get_media, nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments - 1, get_indices, get_media, nvertices, get_position, &ctx, + &scn)); - CHK(senc2d_descriptor_get_enclosure(desc, 0, &enclosure) == RES_OK); - CHK(senc2d_enclosure_get_header(enclosure, &header) == RES_OK); + OK(senc2d_scene_get_enclosure(scn, 0, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); /* Put enclosure in a 2D view... */ + vrtx_get.type = S2D_FLOAT2; + vrtx_get.usage = S2D_POSITION; + vrtx_get.get = senc2d_sXd_enclosure_get_position; + S2D(device_create(NULL, &allocator, 0, &s2d)); + S2D(scene_create(s2d, &s2d_scn)); S2D(shape_create_line_segments(s2d, &s2d_shp)); - S2D(line_segments_setup_indexed_vertices(s2d_shp, header.segment_count, - senc2d_enclosure_get_segment__, header.vertices_count, &vrtx_get, 1, + S2D(line_segments_setup_indexed_vertices(s2d_shp, header.primitives_count, + senc2d_sXd_enclosure_get_indices, header.vertices_count, &vrtx_get, 1, enclosure)); - S2D(scene_attach_shape(s2d_scn, s2d_shp)); - S2D(scene_view_create(s2d_scn, S2D_SAMPLE, &s2d_view)); /* ... and sample it. */ - CHK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng) == RES_OK); + OK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng)); FOR_EACH(i, 0, 10000) { struct s2d_attrib attrib; int n, c; - S2D(scene_view_sample(s2d_view, - ssp_rng_canonical_float(rng), - ssp_rng_canonical_float(rng), - &prim, &s)); - S2D(primitive_get_attrib(&prim, S2D_POSITION, s, &attrib)); + S2D(scene_view_sample(s2d_view, ssp_rng_canonical_float(rng), + ssp_rng_canonical_float(rng), &prim, &st)); + S2D(primitive_get_attrib(&prim, S2D_POSITION, st, &attrib)); c = 0; FOR_EACH(n, 0, 2) if(eq_eps(attrib.value[n], 0, FLT_EPSILON) || eq_eps(attrib.value[n], 1, FLT_EPSILON)) c++; CHK(c == 1); - S2D(primitive_get_attrib(&prim, S2D_GEOMETRY_NORMAL, s, &attrib)); + S2D(primitive_get_attrib(&prim, S2D_GEOMETRY_NORMAL, st, &attrib)); c = 0; FOR_EACH(n, 0, 2) if(eq_eps(attrib.value[n], -1, FLT_EPSILON) @@ -123,7 +105,6 @@ main(int argc, char** argv) SENC2D(enclosure_ref_put(enclosure)); SENC2D(scene_ref_put(scn)); SENC2D(device_ref_put(dev)); - SENC2D(descriptor_ref_put(desc)); SSP(rng_ref_put(rng)); diff --git a/src/test_senc2d_scene.c b/src/test_senc2d_scene.c @@ -25,267 +25,276 @@ main(int argc, char** argv) struct mem_allocator allocator; struct senc2d_device* dev = NULL; struct senc2d_scene* scn = NULL; - struct senc2d_descriptor* desc = NULL; struct senc2d_enclosure* enc = NULL; struct senc2d_enclosure_header header; - struct context ctx; - unsigned medfront[2], medback[2], ind[2]; + struct context ctx = CONTEXT_NULL__; + unsigned medfront[2], medback[2], ind[2], ids[2], seg; double vrtx[2]; unsigned count, i, maxm; int convention; (void)argc, (void)argv; - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - CHK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev) - == RES_OK); - - CHK(senc2d_scene_create(NULL, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_BAD_ARG); - CHK(senc2d_scene_create(dev, 0, &scn) == RES_BAD_ARG); - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, NULL) - == RES_BAD_ARG); - CHK(senc2d_scene_create(NULL, 0, &scn) == RES_BAD_ARG); - CHK(senc2d_scene_create(NULL, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, NULL) - == RES_BAD_ARG); - CHK(senc2d_scene_create(dev, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_create(NULL, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - - CHK(senc2d_scene_reserve(NULL, 0, 0, 0) == RES_BAD_ARG); - CHK(senc2d_scene_reserve(scn, 0, 0, 0) == RES_OK); - - CHK(senc2d_scene_get_convention(NULL, &convention) == RES_BAD_ARG); - CHK(senc2d_scene_get_convention(scn, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_convention(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_convention(scn, &convention) == RES_OK); - CHK(convention == - (SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE)); - - CHK(senc2d_scene_get_segments_count(NULL, &count) == RES_BAD_ARG); - CHK(senc2d_scene_get_segments_count(scn, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_segments_count(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_segments_count(scn, &count) == RES_OK); - CHK(count == 0); - - CHK(senc2d_scene_get_unique_segments_count(NULL, &count) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segments_count(scn, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segments_count(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segments_count(scn, &count) == RES_OK); - CHK(count == 0); - - CHK(senc2d_scene_get_vertices_count(NULL, &count) == RES_BAD_ARG); - CHK(senc2d_scene_get_vertices_count(scn, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_vertices_count(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_vertices_count(scn, &count) == RES_OK); - CHK(count == 0); - - CHK(senc2d_scene_get_unique_vertices_count(NULL, &count) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_vertices_count(scn, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_vertices_count(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_vertices_count(scn, &count) == RES_OK); - CHK(count == 0); - - CHK(senc2d_scene_get_unique_sides_without_medium_count(NULL, &count) - == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_sides_without_medium_count(scn, NULL) - == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_sides_without_medium_count(NULL, NULL) - == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_sides_without_medium_count(scn, &count) - == RES_OK); - CHK(count == 0); + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); - /* A 2D square + /* A 2D square. * With this geometry front is inside with NORMAL_BACK convention, * outside with NORMAL_FRONT convention */ ctx.positions = box_vertices; ctx.indices = box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - d2(ctx.offset, 0, 0); ctx.front_media = medium0; ctx.back_media = medium1; - CHK(senc2d_scene_add_geometry(NULL, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_BAD_ARG); - CHK(senc2d_scene_add_geometry(scn, 0, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_BAD_ARG); - CHK(senc2d_scene_add_geometry(scn, nsegments, NULL, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_BAD_ARG); - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - 0, get_position, NULL, NULL, &ctx) == RES_BAD_ARG); - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, NULL, NULL, NULL, &ctx) == RES_BAD_ARG); - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - CHK(senc2d_scene_get_segments_count(scn, &count) == RES_OK); + BA(senc2d_scene_create(NULL, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + BA(senc2d_scene_create(dev, + 0, + nsegments, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + BA(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + 0, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + BA(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments, NULL, get_media, + nvertices, get_position, &ctx, &scn)); + BA(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments, get_indices, get_media, + 0, get_position, &ctx, &scn)); + BA(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments, get_indices, get_media, + nvertices, NULL, &ctx, &scn)); + BA(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments, get_indices, get_media, + nvertices, get_position, &ctx, NULL)); + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + + BA(senc2d_scene_get_convention(NULL, &convention)); + BA(senc2d_scene_get_convention(scn, NULL)); + BA(senc2d_scene_get_convention(NULL, NULL)); + OK(senc2d_scene_get_convention(scn, &convention)); + CHK(convention + == (SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE)); + + BA(senc2d_scene_get_segments_count(NULL, &count)); + BA(senc2d_scene_get_segments_count(scn, NULL)); + BA(senc2d_scene_get_segments_count(NULL, NULL)); + OK(senc2d_scene_get_segments_count(scn, &count)); CHK(count == nsegments); - CHK(senc2d_scene_get_unique_segments_count(scn, &count) == RES_OK); - CHK(count == nsegments); - CHK(senc2d_scene_get_vertices_count(scn, &count) == RES_OK); - CHK(count == nvertices); - CHK(senc2d_scene_get_unique_vertices_count(scn, &count) == RES_OK); + + BA(senc2d_scene_get_vertices_count(NULL, &count)); + BA(senc2d_scene_get_vertices_count(scn, NULL)); + BA(senc2d_scene_get_vertices_count(NULL, NULL)); + OK(senc2d_scene_get_vertices_count(scn, &count)); CHK(count == nvertices); - CHK(senc2d_scene_get_unique_segment(NULL, 0, ind) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment(scn, UINT_MAX, ind) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment(scn, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment(NULL, UINT_MAX, ind) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment(NULL, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment(scn, UINT_MAX, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment(NULL, UINT_MAX, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment(scn, 0, ind) == RES_OK); - - CHK(senc2d_scene_get_unique_segment_media(NULL, 0, ind) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment_media(scn, UINT_MAX, ind) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment_media(scn, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment_media(NULL, UINT_MAX, ind) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment_media(NULL, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment_media(scn, UINT_MAX, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment_media(NULL, UINT_MAX, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_segment_media(scn, 0, ind) == RES_OK); - - CHK(senc2d_scene_get_unique_vertex(NULL, 0, vrtx) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_vertex(scn, UINT_MAX, vrtx) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_vertex(scn, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_vertex(NULL, UINT_MAX, vrtx) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_vertex(NULL, 0, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_vertex(scn, UINT_MAX, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_vertex(NULL, UINT_MAX, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_get_unique_vertex(scn, 0, vrtx) == RES_OK); - - CHK(senc2d_scene_analyze(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_analyze(scn, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_analyze(NULL, &desc) == RES_BAD_ARG); - CHK(senc2d_scene_analyze(NULL, NULL) == RES_BAD_ARG); - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); - - CHK(senc2d_scene_ref_get(NULL) == RES_BAD_ARG); - CHK(senc2d_scene_ref_get(scn) == RES_OK); - CHK(senc2d_scene_ref_put(NULL) == RES_BAD_ARG); - CHK(senc2d_scene_ref_put(scn) == RES_OK); - - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_descriptor_ref_put(desc) == RES_OK); - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - CHK(senc2d_scene_get_convention(scn, &convention) == RES_OK); - CHK(convention == - (SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_INSIDE)); - /* Add the first segment twice to create a shift in numbering */ - CHK(senc2d_scene_add_geometry(scn, 1, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); + BA(senc2d_scene_get_segment(NULL, 0, ind)); + BA(senc2d_scene_get_segment(scn, UINT_MAX, ind)); + BA(senc2d_scene_get_segment(scn, 0, NULL)); + BA(senc2d_scene_get_segment(NULL, UINT_MAX, ind)); + BA(senc2d_scene_get_segment(NULL, 0, NULL)); + BA(senc2d_scene_get_segment(scn, UINT_MAX, NULL)); + BA(senc2d_scene_get_segment(NULL, UINT_MAX, NULL)); + OK(senc2d_scene_get_segment(scn, 0, ind)); + + BA(senc2d_scene_get_segment_media(NULL, 0, ind)); + BA(senc2d_scene_get_segment_media(scn, UINT_MAX, ind)); + BA(senc2d_scene_get_segment_media(scn, 0, NULL)); + BA(senc2d_scene_get_segment_media(NULL, UINT_MAX, ind)); + BA(senc2d_scene_get_segment_media(NULL, 0, NULL)); + BA(senc2d_scene_get_segment_media(scn, UINT_MAX, NULL)); + BA(senc2d_scene_get_segment_media(NULL, UINT_MAX, NULL)); + OK(senc2d_scene_get_segment_media(scn, 0, ind)); + + BA(senc2d_scene_get_vertex(NULL, 0, vrtx)); + BA(senc2d_scene_get_vertex(scn, UINT_MAX, vrtx)); + BA(senc2d_scene_get_vertex(scn, 0, NULL)); + BA(senc2d_scene_get_vertex(NULL, UINT_MAX, vrtx)); + BA(senc2d_scene_get_vertex(NULL, 0, NULL)); + BA(senc2d_scene_get_vertex(scn, UINT_MAX, NULL)); + BA(senc2d_scene_get_vertex(NULL, UINT_MAX, NULL)); + OK(senc2d_scene_get_vertex(scn, 0, vrtx)); + + BA(senc2d_scene_get_max_medium(NULL, &maxm)); + BA(senc2d_scene_get_max_medium(scn, NULL)); + BA(senc2d_scene_get_max_medium(NULL, NULL)); + OK(senc2d_scene_get_max_medium(scn, &maxm)); + CHK(maxm == 1); + + BA(senc2d_scene_get_enclosure_count(NULL, &count)); + BA(senc2d_scene_get_enclosure_count(scn, NULL)); + BA(senc2d_scene_get_enclosure_count(NULL, NULL)); + OK(senc2d_scene_get_enclosure_count(scn, &count)); + CHK(count == 2); + + BA(senc2d_scene_get_enclosure_count_by_medium(NULL, 0, &count)); + BA(senc2d_scene_get_enclosure_count_by_medium(scn, 100, &count)); + BA(senc2d_scene_get_enclosure_count_by_medium(scn, 0, NULL)); + BA(senc2d_scene_get_enclosure_count_by_medium(NULL, 100, &count)); + BA(senc2d_scene_get_enclosure_count_by_medium(NULL, 0, NULL)); + BA(senc2d_scene_get_enclosure_count_by_medium(scn, 100, NULL)); + BA(senc2d_scene_get_enclosure_count_by_medium(NULL, 100, NULL)); + OK(senc2d_scene_get_enclosure_count_by_medium(scn, 0, &count)); + CHK(count == 1); + OK(senc2d_scene_get_enclosure_count_by_medium(scn, SENC2D_UNSPECIFIED_MEDIUM, + &count)); + CHK(count == 0); + + BA(senc2d_scene_get_enclosure(NULL, 0, &enc)); + BA(senc2d_scene_get_enclosure(scn, UINT_MAX, &enc)); + BA(senc2d_scene_get_enclosure(scn, 0, NULL)); + BA(senc2d_scene_get_enclosure(NULL, UINT_MAX, &enc)); + BA(senc2d_scene_get_enclosure(NULL, 0, NULL)); + BA(senc2d_scene_get_enclosure(scn, UINT_MAX, NULL)); + BA(senc2d_scene_get_enclosure(NULL, UINT_MAX, NULL)); + OK(senc2d_scene_get_enclosure(scn, 0, &enc)); + OK(senc2d_enclosure_ref_put(enc)); + + BA(senc2d_scene_get_enclosure_by_medium(NULL, 0, 0, &enc)); + BA(senc2d_scene_get_enclosure_by_medium(scn, 100, 0, &enc)); + BA(senc2d_scene_get_enclosure_by_medium(scn, 0, UINT_MAX, &enc)); + BA(senc2d_scene_get_enclosure_by_medium(scn, 0, 0, NULL)); + BA(senc2d_scene_get_enclosure_by_medium(NULL, 100, 0, &enc)); + BA(senc2d_scene_get_enclosure_by_medium(NULL, 0, UINT_MAX, &enc)); + BA(senc2d_scene_get_enclosure_by_medium(NULL, 0, 0, NULL)); + BA(senc2d_scene_get_enclosure_by_medium(scn, 100, UINT_MAX, &enc)); + BA(senc2d_scene_get_enclosure_by_medium(scn, 100, 0, NULL)); + BA(senc2d_scene_get_enclosure_by_medium(scn, 0, UINT_MAX, NULL)); + BA(senc2d_scene_get_enclosure_by_medium(scn, 100, UINT_MAX, NULL)); + BA(senc2d_scene_get_enclosure_by_medium(NULL, 0, UINT_MAX, NULL)); + BA(senc2d_scene_get_enclosure_by_medium(NULL, 100, 0, NULL)); + BA(senc2d_scene_get_enclosure_by_medium(NULL, 100, UINT_MAX, &enc)); + BA(senc2d_scene_get_enclosure_by_medium(NULL, 100, UINT_MAX, NULL)); + OK(senc2d_scene_get_enclosure_by_medium(scn, 0, 0, &enc)); + OK(senc2d_enclosure_ref_put(enc)); + /* Index 0 is out of range for SENC2D_UNSPECIFIED_MEDIUM. */ + BA(senc2d_scene_get_enclosure_by_medium(scn, SENC2D_UNSPECIFIED_MEDIUM, 0, &enc)); + + BA(senc2d_scene_get_segment_enclosures(NULL, 0, ids)); + BA(senc2d_scene_get_segment_enclosures(scn, UINT_MAX, ids)); + BA(senc2d_scene_get_segment_enclosures(scn, 0, NULL)); + BA(senc2d_scene_get_segment_enclosures(NULL, UINT_MAX, ids)); + BA(senc2d_scene_get_segment_enclosures(NULL, 0, NULL)); + BA(senc2d_scene_get_segment_enclosures(scn, UINT_MAX, NULL)); + BA(senc2d_scene_get_segment_enclosures(NULL, UINT_MAX, NULL)); + OK(senc2d_scene_get_segment_enclosures(scn, 0, ids)); + + BA(senc2d_scene_get_frontier_vertice_count(NULL, &count)); + BA(senc2d_scene_get_frontier_vertice_count(scn, NULL)); + BA(senc2d_scene_get_frontier_vertice_count(NULL, NULL)); + OK(senc2d_scene_get_frontier_vertice_count(scn, &count)); + CHK(count == 0); + + BA(senc2d_scene_get_frontier_vertex(NULL, 0, &ids[0], &seg)); + BA(senc2d_scene_get_frontier_vertex(scn, UINT_MAX, &ids[0], &seg)); + BA(senc2d_scene_get_frontier_vertex(scn, 0, NULL, &seg)); + BA(senc2d_scene_get_frontier_vertex(scn, 0, &ids[0], NULL)); + BA(senc2d_scene_get_frontier_vertex(NULL, UINT_MAX, &ids[0], &seg)); + BA(senc2d_scene_get_frontier_vertex(NULL, 0, NULL, &seg)); + BA(senc2d_scene_get_frontier_vertex(NULL, 0, &ids[0], NULL)); + BA(senc2d_scene_get_frontier_vertex(scn, UINT_MAX, NULL, &seg)); + BA(senc2d_scene_get_frontier_vertex(scn, UINT_MAX, &ids[0], NULL)); + BA(senc2d_scene_get_frontier_vertex(scn, 0, NULL, NULL)); + BA(senc2d_scene_get_frontier_vertex(NULL, UINT_MAX, NULL, &seg)); + BA(senc2d_scene_get_frontier_vertex(NULL, UINT_MAX, &ids[0], NULL)); + BA(senc2d_scene_get_frontier_vertex(NULL, 0, NULL, NULL)); + BA(senc2d_scene_get_frontier_vertex(scn, UINT_MAX, NULL, NULL)); + BA(senc2d_scene_get_frontier_vertex(NULL, UINT_MAX, NULL, NULL)); + + BA(senc2d_scene_ref_get(NULL)); + OK(senc2d_scene_ref_get(scn)); + BA(senc2d_scene_ref_put(NULL)); + OK(senc2d_scene_ref_put(scn)); + + OK(senc2d_scene_ref_put(scn)); + + /* Same geometry with SENC2D_UNSPECIFIED_MEDIUM */ + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments, get_indices, NULL, + nvertices, get_position, &ctx, &scn)); + + OK(senc2d_scene_get_enclosure_by_medium(scn, SENC2D_UNSPECIFIED_MEDIUM, 0, &enc)); + OK(senc2d_enclosure_ref_put(enc)); + BA(senc2d_scene_get_enclosure_by_medium(scn, SENC2D_UNSPECIFIED_MEDIUM, 100, &enc)); + + OK(senc2d_scene_ref_put(scn)); + + /* Same geometry with a hole (1 missing segment) */ + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments - 1, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + + OK(senc2d_scene_get_frontier_vertice_count(scn, &count)); + CHK(count == 2); + OK(senc2d_scene_get_frontier_vertex(scn, 0, &ids[0], &seg)); + BA(senc2d_scene_get_frontier_vertex(scn, 3, &ids[0], &seg)); + + OK(senc2d_scene_ref_put(scn)); + + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + + OK(senc2d_scene_get_convention(scn, &convention)); + CHK(convention + == (SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_INSIDE)); /* Check that medium 0 is inside */ - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, 0, 0, &enc) == RES_OK); - CHK(senc2d_enclosure_get_header(enc, &header) == RES_OK); + OK(senc2d_scene_get_enclosure_by_medium(scn, 0, 0, &enc)); + OK(senc2d_enclosure_get_header(enc, &header)); CHK(!header.is_infinite); - CHK(senc2d_enclosure_ref_put(enc) == RES_OK); + OK(senc2d_enclosure_ref_put(enc)); - FOR_EACH(i, 0, nsegments) { - unsigned gid; - CHK(senc2d_descriptor_get_global_segment_global_id(desc, i, &gid) == RES_OK); - /* Check numbering shift */ - CHK(gid == (i ? i + 1 : 0)); - } + OK(senc2d_scene_get_segment_media(scn, 0, medback)); + OK(senc2d_scene_ref_put(scn)); - CHK(senc2d_descriptor_get_global_segment_media(desc, 0, medback) == RES_OK); - ctx.front_media = medium1_3; - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_descriptor_ref_put(desc) == RES_OK); - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); /* Medium mismatch between neighbour segments, but OK */ - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); + ctx.front_media = medium1_3; + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); - CHK(senc2d_descriptor_get_max_medium(desc, &maxm) == RES_OK); + OK(senc2d_scene_get_max_medium(scn, &maxm)); CHK(maxm == 3); - CHK(senc2d_descriptor_get_enclosure_count_by_medium(desc, 0, &count) == RES_OK); + OK(senc2d_scene_get_enclosure_count_by_medium(scn, 0, &count)); CHK(count == 0); /* Medium 0 unused */ - CHK(senc2d_descriptor_get_enclosure_count_by_medium(desc, 1, &count) == RES_OK); + OK(senc2d_scene_get_enclosure_count_by_medium(scn, 1, &count)); CHK(count == 2); /* Medium 1 used twice */ - CHK(senc2d_descriptor_get_enclosure_count_by_medium(desc, 2, &count) == RES_OK); + OK(senc2d_scene_get_enclosure_count_by_medium(scn, 2, &count)); CHK(count == 0); /* Medium 2 unused */ - CHK(senc2d_descriptor_get_enclosure_count_by_medium(desc, 3, &count) == RES_OK); + OK(senc2d_scene_get_enclosure_count_by_medium(scn, 3, &count)); CHK(count == 1); /* Medium 3 used */ - check_desc(desc); + + OK(senc2d_scene_ref_put(scn)); ctx.front_media = medium0; - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_descriptor_ref_put(desc) == RES_OK); - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - /* Add the first segment twice to create a shift in numbering */ - CHK(senc2d_scene_add_geometry(scn, 1, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + nsegments, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); /* Check that medium 0 is outside */ - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, 0, 0, &enc) == RES_OK); - CHK(senc2d_enclosure_get_header(enc, &header) == RES_OK); + OK(senc2d_scene_get_enclosure_by_medium(scn, 0, 0, &enc)); + OK(senc2d_enclosure_get_header(enc, &header)); CHK(header.is_infinite); - CHK(senc2d_enclosure_ref_put(enc) == RES_OK); + OK(senc2d_enclosure_ref_put(enc)); - FOR_EACH(i, 0, nsegments) { - unsigned gid; - CHK(senc2d_descriptor_get_global_segment_global_id(desc, i, &gid) == RES_OK); - /* Check numbering shift */ - CHK(gid == (i ? i + 1 : 0)); - } - - CHK(senc2d_descriptor_get_global_segment_media(desc, 0, medfront) == RES_OK); + OK(senc2d_scene_get_segment_media(scn, 0, medfront)); FOR_EACH(i, 0, 2) CHK(medback[i] == medfront[i]); - /* Invalid vertex ID */ - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices - 1, get_position, NULL, NULL, &ctx) == RES_BAD_ARG); - - /* Incoherent medium on a duplicate segment */ - ctx.back_media = medium1_3; - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_BAD_ARG); - - /* It is OK add geometry after a failed add */ - ctx.back_media = medium1; - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - /* Coherent medium on duplicate segment */ - ctx.back_media = medium1; - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - /* Coherent medium on duplicate segment V2 */ - ctx.reverse_med = 1; - ctx.front_media = medium1; - ctx.back_media = medium0; - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - /* Coherent medium on duplicate segment V3 */ - ctx.reverse_med = 0; - ctx.reverse_vrtx = 1; - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); - CHK(senc2d_descriptor_ref_put(desc) == RES_OK); + OK(senc2d_scene_ref_put(scn)); + OK(senc2d_device_ref_put(dev)); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); diff --git a/src/test_senc2d_some_enclosures.c b/src/test_senc2d_some_enclosures.c @@ -0,0 +1,3173 @@ +/* Copyright (C) |Meso|Star> 2018-2020 (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/>. */ + +/* This test has been created using the sg2_geometry_dump_as_C_code feature + * of star-geometry-2D-2D. It uses output from test_sg2_some_enclosures. + * This test is similar to test_senc2d_many_enclosures that creates a huge + * geometry by program. */ + +#include "senc2d.h" +#include "test_senc2d_utils.h" + +#include <rsys/double2.h> + +/* Dump of star-geometry-2D 'some_enclosures'. */ +static const unsigned some_enclosures_vertices_count = 1024; +static const double some_enclosures_vertices[2048] = +{ + -19, -20, + -19.0761, -19.6173, + -19.2929, -19.2929, + -19.6173, -19.0761, + -20, -19, + -20.3827, -19.0761, + -20.7071, -19.2929, + -20.9239, -19.6173, + -21, -20, + -20.9239, -20.3827, + -20.7071, -20.7071, + -20.3827, -20.9239, + -20, -21, + -19.6173, -20.9239, + -19.2929, -20.7071, + -19.0761, -20.3827, + -18, -20, + -18.1522, -19.2346, + -18.5858, -18.5858, + -19.2346, -18.1522, + -20, -18, + -20.7654, -18.1522, + -21.4142, -18.5858, + -21.8478, -19.2346, + -22, -20, + -21.8478, -20.7654, + -21.4142, -21.4142, + -20.7654, -21.8478, + -20, -22, + -19.2346, -21.8478, + -18.5858, -21.4142, + -18.1522, -20.7654, + -17, -20, + -17.2284, -18.8519, + -17.8787, -17.8787, + -18.8519, -17.2284, + -20, -17, + -21.1481, -17.2284, + -22.1213, -17.8787, + -22.7716, -18.8519, + -23, -20, + -22.7716, -21.1481, + -22.1213, -22.1213, + -21.1481, -22.7716, + -20, -23, + -18.8519, -22.7716, + -17.8787, -22.1213, + -17.2284, -21.1481, + -16, -20, + -16.3045, -18.4693, + -17.1716, -17.1716, + -18.4693, -16.3045, + -20, -16, + -21.5307, -16.3045, + -22.8284, -17.1716, + -23.6955, -18.4693, + -24, -20, + -23.6955, -21.5307, + -22.8284, -22.8284, + -21.5307, -23.6955, + -20, -24, + -18.4693, -23.6955, + -17.1716, -22.8284, + -16.3045, -21.5307, + -19, -10, + -19.0761, -9.61732, + -19.2929, -9.29289, + -19.6173, -9.07612, + -20, -9, + -20.3827, -9.07612, + -20.7071, -9.29289, + -20.9239, -9.61732, + -21, -10, + -20.9239, -10.3827, + -20.7071, -10.7071, + -20.3827, -10.9239, + -20, -11, + -19.6173, -10.9239, + -19.2929, -10.7071, + -19.0761, -10.3827, + -18, -10, + -18.1522, -9.23463, + -18.5858, -8.58579, + -19.2346, -8.15224, + -20, -8, + -20.7654, -8.15224, + -21.4142, -8.58579, + -21.8478, -9.23463, + -22, -10, + -21.8478, -10.7654, + -21.4142, -11.4142, + -20.7654, -11.8478, + -20, -12, + -19.2346, -11.8478, + -18.5858, -11.4142, + -18.1522, -10.7654, + -17, -10, + -17.2284, -8.85195, + -17.8787, -7.87868, + -18.8519, -7.22836, + -20, -7, + -21.1481, -7.22836, + -22.1213, -7.87868, + -22.7716, -8.85195, + -23, -10, + -22.7716, -11.1481, + -22.1213, -12.1213, + -21.1481, -12.7716, + -20, -13, + -18.8519, -12.7716, + -17.8787, -12.1213, + -17.2284, -11.1481, + -16, -10, + -16.3045, -8.46927, + -17.1716, -7.17157, + -18.4693, -6.30448, + -20, -6, + -21.5307, -6.30448, + -22.8284, -7.17157, + -23.6955, -8.46927, + -24, -10, + -23.6955, -11.5307, + -22.8284, -12.8284, + -21.5307, -13.6955, + -20, -14, + -18.4693, -13.6955, + -17.1716, -12.8284, + -16.3045, -11.5307, + -19, 0, + -19.0761, 0.382683, + -19.2929, 0.707107, + -19.6173, 0.92388, + -20, 1, + -20.3827, 0.92388, + -20.7071, 0.707107, + -20.9239, 0.382683, + -21, 1.22465e-16, + -20.9239, -0.382683, + -20.7071, -0.707107, + -20.3827, -0.92388, + -20, -1, + -19.6173, -0.92388, + -19.2929, -0.707107, + -19.0761, -0.382683, + -18, 0, + -18.1522, 0.765367, + -18.5858, 1.41421, + -19.2346, 1.84776, + -20, 2, + -20.7654, 1.84776, + -21.4142, 1.41421, + -21.8478, 0.765367, + -22, 2.44929e-16, + -21.8478, -0.765367, + -21.4142, -1.41421, + -20.7654, -1.84776, + -20, -2, + -19.2346, -1.84776, + -18.5858, -1.41421, + -18.1522, -0.765367, + -17, 0, + -17.2284, 1.14805, + -17.8787, 2.12132, + -18.8519, 2.77164, + -20, 3, + -21.1481, 2.77164, + -22.1213, 2.12132, + -22.7716, 1.14805, + -23, 3.67394e-16, + -22.7716, -1.14805, + -22.1213, -2.12132, + -21.1481, -2.77164, + -20, -3, + -18.8519, -2.77164, + -17.8787, -2.12132, + -17.2284, -1.14805, + -16, 0, + -16.3045, 1.53073, + -17.1716, 2.82843, + -18.4693, 3.69552, + -20, 4, + -21.5307, 3.69552, + -22.8284, 2.82843, + -23.6955, 1.53073, + -24, 4.89859e-16, + -23.6955, -1.53073, + -22.8284, -2.82843, + -21.5307, -3.69552, + -20, -4, + -18.4693, -3.69552, + -17.1716, -2.82843, + -16.3045, -1.53073, + -19, 10, + -19.0761, 10.3827, + -19.2929, 10.7071, + -19.6173, 10.9239, + -20, 11, + -20.3827, 10.9239, + -20.7071, 10.7071, + -20.9239, 10.3827, + -21, 10, + -20.9239, 9.61732, + -20.7071, 9.29289, + -20.3827, 9.07612, + -20, 9, + -19.6173, 9.07612, + -19.2929, 9.29289, + -19.0761, 9.61732, + -18, 10, + -18.1522, 10.7654, + -18.5858, 11.4142, + -19.2346, 11.8478, + -20, 12, + -20.7654, 11.8478, + -21.4142, 11.4142, + -21.8478, 10.7654, + -22, 10, + -21.8478, 9.23463, + -21.4142, 8.58579, + -20.7654, 8.15224, + -20, 8, + -19.2346, 8.15224, + -18.5858, 8.58579, + -18.1522, 9.23463, + -17, 10, + -17.2284, 11.1481, + -17.8787, 12.1213, + -18.8519, 12.7716, + -20, 13, + -21.1481, 12.7716, + -22.1213, 12.1213, + -22.7716, 11.1481, + -23, 10, + -22.7716, 8.85195, + -22.1213, 7.87868, + -21.1481, 7.22836, + -20, 7, + -18.8519, 7.22836, + -17.8787, 7.87868, + -17.2284, 8.85195, + -16, 10, + -16.3045, 11.5307, + -17.1716, 12.8284, + -18.4693, 13.6955, + -20, 14, + -21.5307, 13.6955, + -22.8284, 12.8284, + -23.6955, 11.5307, + -24, 10, + -23.6955, 8.46927, + -22.8284, 7.17157, + -21.5307, 6.30448, + -20, 6, + -18.4693, 6.30448, + -17.1716, 7.17157, + -16.3045, 8.46927, + -9, -20, + -9.07612, -19.6173, + -9.29289, -19.2929, + -9.61732, -19.0761, + -10, -19, + -10.3827, -19.0761, + -10.7071, -19.2929, + -10.9239, -19.6173, + -11, -20, + -10.9239, -20.3827, + -10.7071, -20.7071, + -10.3827, -20.9239, + -10, -21, + -9.61732, -20.9239, + -9.29289, -20.7071, + -9.07612, -20.3827, + -8, -20, + -8.15224, -19.2346, + -8.58579, -18.5858, + -9.23463, -18.1522, + -10, -18, + -10.7654, -18.1522, + -11.4142, -18.5858, + -11.8478, -19.2346, + -12, -20, + -11.8478, -20.7654, + -11.4142, -21.4142, + -10.7654, -21.8478, + -10, -22, + -9.23463, -21.8478, + -8.58579, -21.4142, + -8.15224, -20.7654, + -7, -20, + -7.22836, -18.8519, + -7.87868, -17.8787, + -8.85195, -17.2284, + -10, -17, + -11.1481, -17.2284, + -12.1213, -17.8787, + -12.7716, -18.8519, + -13, -20, + -12.7716, -21.1481, + -12.1213, -22.1213, + -11.1481, -22.7716, + -10, -23, + -8.85195, -22.7716, + -7.87868, -22.1213, + -7.22836, -21.1481, + -6, -20, + -6.30448, -18.4693, + -7.17157, -17.1716, + -8.46927, -16.3045, + -10, -16, + -11.5307, -16.3045, + -12.8284, -17.1716, + -13.6955, -18.4693, + -14, -20, + -13.6955, -21.5307, + -12.8284, -22.8284, + -11.5307, -23.6955, + -10, -24, + -8.46927, -23.6955, + -7.17157, -22.8284, + -6.30448, -21.5307, + -9, -10, + -9.07612, -9.61732, + -9.29289, -9.29289, + -9.61732, -9.07612, + -10, -9, + -10.3827, -9.07612, + -10.7071, -9.29289, + -10.9239, -9.61732, + -11, -10, + -10.9239, -10.3827, + -10.7071, -10.7071, + -10.3827, -10.9239, + -10, -11, + -9.61732, -10.9239, + -9.29289, -10.7071, + -9.07612, -10.3827, + -8, -10, + -8.15224, -9.23463, + -8.58579, -8.58579, + -9.23463, -8.15224, + -10, -8, + -10.7654, -8.15224, + -11.4142, -8.58579, + -11.8478, -9.23463, + -12, -10, + -11.8478, -10.7654, + -11.4142, -11.4142, + -10.7654, -11.8478, + -10, -12, + -9.23463, -11.8478, + -8.58579, -11.4142, + -8.15224, -10.7654, + -7, -10, + -7.22836, -8.85195, + -7.87868, -7.87868, + -8.85195, -7.22836, + -10, -7, + -11.1481, -7.22836, + -12.1213, -7.87868, + -12.7716, -8.85195, + -13, -10, + -12.7716, -11.1481, + -12.1213, -12.1213, + -11.1481, -12.7716, + -10, -13, + -8.85195, -12.7716, + -7.87868, -12.1213, + -7.22836, -11.1481, + -6, -10, + -6.30448, -8.46927, + -7.17157, -7.17157, + -8.46927, -6.30448, + -10, -6, + -11.5307, -6.30448, + -12.8284, -7.17157, + -13.6955, -8.46927, + -14, -10, + -13.6955, -11.5307, + -12.8284, -12.8284, + -11.5307, -13.6955, + -10, -14, + -8.46927, -13.6955, + -7.17157, -12.8284, + -6.30448, -11.5307, + -9, 0, + -9.07612, 0.382683, + -9.29289, 0.707107, + -9.61732, 0.92388, + -10, 1, + -10.3827, 0.92388, + -10.7071, 0.707107, + -10.9239, 0.382683, + -11, 1.22465e-16, + -10.9239, -0.382683, + -10.7071, -0.707107, + -10.3827, -0.92388, + -10, -1, + -9.61732, -0.92388, + -9.29289, -0.707107, + -9.07612, -0.382683, + -8, 0, + -8.15224, 0.765367, + -8.58579, 1.41421, + -9.23463, 1.84776, + -10, 2, + -10.7654, 1.84776, + -11.4142, 1.41421, + -11.8478, 0.765367, + -12, 2.44929e-16, + -11.8478, -0.765367, + -11.4142, -1.41421, + -10.7654, -1.84776, + -10, -2, + -9.23463, -1.84776, + -8.58579, -1.41421, + -8.15224, -0.765367, + -7, 0, + -7.22836, 1.14805, + -7.87868, 2.12132, + -8.85195, 2.77164, + -10, 3, + -11.1481, 2.77164, + -12.1213, 2.12132, + -12.7716, 1.14805, + -13, 3.67394e-16, + -12.7716, -1.14805, + -12.1213, -2.12132, + -11.1481, -2.77164, + -10, -3, + -8.85195, -2.77164, + -7.87868, -2.12132, + -7.22836, -1.14805, + -6, 0, + -6.30448, 1.53073, + -7.17157, 2.82843, + -8.46927, 3.69552, + -10, 4, + -11.5307, 3.69552, + -12.8284, 2.82843, + -13.6955, 1.53073, + -14, 4.89859e-16, + -13.6955, -1.53073, + -12.8284, -2.82843, + -11.5307, -3.69552, + -10, -4, + -8.46927, -3.69552, + -7.17157, -2.82843, + -6.30448, -1.53073, + -9, 10, + -9.07612, 10.3827, + -9.29289, 10.7071, + -9.61732, 10.9239, + -10, 11, + -10.3827, 10.9239, + -10.7071, 10.7071, + -10.9239, 10.3827, + -11, 10, + -10.9239, 9.61732, + -10.7071, 9.29289, + -10.3827, 9.07612, + -10, 9, + -9.61732, 9.07612, + -9.29289, 9.29289, + -9.07612, 9.61732, + -8, 10, + -8.15224, 10.7654, + -8.58579, 11.4142, + -9.23463, 11.8478, + -10, 12, + -10.7654, 11.8478, + -11.4142, 11.4142, + -11.8478, 10.7654, + -12, 10, + -11.8478, 9.23463, + -11.4142, 8.58579, + -10.7654, 8.15224, + -10, 8, + -9.23463, 8.15224, + -8.58579, 8.58579, + -8.15224, 9.23463, + -7, 10, + -7.22836, 11.1481, + -7.87868, 12.1213, + -8.85195, 12.7716, + -10, 13, + -11.1481, 12.7716, + -12.1213, 12.1213, + -12.7716, 11.1481, + -13, 10, + -12.7716, 8.85195, + -12.1213, 7.87868, + -11.1481, 7.22836, + -10, 7, + -8.85195, 7.22836, + -7.87868, 7.87868, + -7.22836, 8.85195, + -6, 10, + -6.30448, 11.5307, + -7.17157, 12.8284, + -8.46927, 13.6955, + -10, 14, + -11.5307, 13.6955, + -12.8284, 12.8284, + -13.6955, 11.5307, + -14, 10, + -13.6955, 8.46927, + -12.8284, 7.17157, + -11.5307, 6.30448, + -10, 6, + -8.46927, 6.30448, + -7.17157, 7.17157, + -6.30448, 8.46927, + 1, -20, + 0.92388, -19.6173, + 0.707107, -19.2929, + 0.382683, -19.0761, + 6.12323e-17, -19, + -0.382683, -19.0761, + -0.707107, -19.2929, + -0.92388, -19.6173, + -1, -20, + -0.92388, -20.3827, + -0.707107, -20.7071, + -0.382683, -20.9239, + -1.83697e-16, -21, + 0.382683, -20.9239, + 0.707107, -20.7071, + 0.92388, -20.3827, + 2, -20, + 1.84776, -19.2346, + 1.41421, -18.5858, + 0.765367, -18.1522, + 1.22465e-16, -18, + -0.765367, -18.1522, + -1.41421, -18.5858, + -1.84776, -19.2346, + -2, -20, + -1.84776, -20.7654, + -1.41421, -21.4142, + -0.765367, -21.8478, + -3.67394e-16, -22, + 0.765367, -21.8478, + 1.41421, -21.4142, + 1.84776, -20.7654, + 3, -20, + 2.77164, -18.8519, + 2.12132, -17.8787, + 1.14805, -17.2284, + 1.83697e-16, -17, + -1.14805, -17.2284, + -2.12132, -17.8787, + -2.77164, -18.8519, + -3, -20, + -2.77164, -21.1481, + -2.12132, -22.1213, + -1.14805, -22.7716, + -5.51091e-16, -23, + 1.14805, -22.7716, + 2.12132, -22.1213, + 2.77164, -21.1481, + 4, -20, + 3.69552, -18.4693, + 2.82843, -17.1716, + 1.53073, -16.3045, + 2.44929e-16, -16, + -1.53073, -16.3045, + -2.82843, -17.1716, + -3.69552, -18.4693, + -4, -20, + -3.69552, -21.5307, + -2.82843, -22.8284, + -1.53073, -23.6955, + -7.34788e-16, -24, + 1.53073, -23.6955, + 2.82843, -22.8284, + 3.69552, -21.5307, + 1, -10, + 0.92388, -9.61732, + 0.707107, -9.29289, + 0.382683, -9.07612, + 6.12323e-17, -9, + -0.382683, -9.07612, + -0.707107, -9.29289, + -0.92388, -9.61732, + -1, -10, + -0.92388, -10.3827, + -0.707107, -10.7071, + -0.382683, -10.9239, + -1.83697e-16, -11, + 0.382683, -10.9239, + 0.707107, -10.7071, + 0.92388, -10.3827, + 2, -10, + 1.84776, -9.23463, + 1.41421, -8.58579, + 0.765367, -8.15224, + 1.22465e-16, -8, + -0.765367, -8.15224, + -1.41421, -8.58579, + -1.84776, -9.23463, + -2, -10, + -1.84776, -10.7654, + -1.41421, -11.4142, + -0.765367, -11.8478, + -3.67394e-16, -12, + 0.765367, -11.8478, + 1.41421, -11.4142, + 1.84776, -10.7654, + 3, -10, + 2.77164, -8.85195, + 2.12132, -7.87868, + 1.14805, -7.22836, + 1.83697e-16, -7, + -1.14805, -7.22836, + -2.12132, -7.87868, + -2.77164, -8.85195, + -3, -10, + -2.77164, -11.1481, + -2.12132, -12.1213, + -1.14805, -12.7716, + -5.51091e-16, -13, + 1.14805, -12.7716, + 2.12132, -12.1213, + 2.77164, -11.1481, + 4, -10, + 3.69552, -8.46927, + 2.82843, -7.17157, + 1.53073, -6.30448, + 2.44929e-16, -6, + -1.53073, -6.30448, + -2.82843, -7.17157, + -3.69552, -8.46927, + -4, -10, + -3.69552, -11.5307, + -2.82843, -12.8284, + -1.53073, -13.6955, + -7.34788e-16, -14, + 1.53073, -13.6955, + 2.82843, -12.8284, + 3.69552, -11.5307, + 1, 0, + 0.92388, 0.382683, + 0.707107, 0.707107, + 0.382683, 0.92388, + 6.12323e-17, 1, + -0.382683, 0.92388, + -0.707107, 0.707107, + -0.92388, 0.382683, + -1, 1.22465e-16, + -0.92388, -0.382683, + -0.707107, -0.707107, + -0.382683, -0.92388, + -1.83697e-16, -1, + 0.382683, -0.92388, + 0.707107, -0.707107, + 0.92388, -0.382683, + 2, 0, + 1.84776, 0.765367, + 1.41421, 1.41421, + 0.765367, 1.84776, + 1.22465e-16, 2, + -0.765367, 1.84776, + -1.41421, 1.41421, + -1.84776, 0.765367, + -2, 2.44929e-16, + -1.84776, -0.765367, + -1.41421, -1.41421, + -0.765367, -1.84776, + -3.67394e-16, -2, + 0.765367, -1.84776, + 1.41421, -1.41421, + 1.84776, -0.765367, + 3, 0, + 2.77164, 1.14805, + 2.12132, 2.12132, + 1.14805, 2.77164, + 1.83697e-16, 3, + -1.14805, 2.77164, + -2.12132, 2.12132, + -2.77164, 1.14805, + -3, 3.67394e-16, + -2.77164, -1.14805, + -2.12132, -2.12132, + -1.14805, -2.77164, + -5.51091e-16, -3, + 1.14805, -2.77164, + 2.12132, -2.12132, + 2.77164, -1.14805, + 4, 0, + 3.69552, 1.53073, + 2.82843, 2.82843, + 1.53073, 3.69552, + 2.44929e-16, 4, + -1.53073, 3.69552, + -2.82843, 2.82843, + -3.69552, 1.53073, + -4, 4.89859e-16, + -3.69552, -1.53073, + -2.82843, -2.82843, + -1.53073, -3.69552, + -7.34788e-16, -4, + 1.53073, -3.69552, + 2.82843, -2.82843, + 3.69552, -1.53073, + 1, 10, + 0.92388, 10.3827, + 0.707107, 10.7071, + 0.382683, 10.9239, + 6.12323e-17, 11, + -0.382683, 10.9239, + -0.707107, 10.7071, + -0.92388, 10.3827, + -1, 10, + -0.92388, 9.61732, + -0.707107, 9.29289, + -0.382683, 9.07612, + -1.83697e-16, 9, + 0.382683, 9.07612, + 0.707107, 9.29289, + 0.92388, 9.61732, + 2, 10, + 1.84776, 10.7654, + 1.41421, 11.4142, + 0.765367, 11.8478, + 1.22465e-16, 12, + -0.765367, 11.8478, + -1.41421, 11.4142, + -1.84776, 10.7654, + -2, 10, + -1.84776, 9.23463, + -1.41421, 8.58579, + -0.765367, 8.15224, + -3.67394e-16, 8, + 0.765367, 8.15224, + 1.41421, 8.58579, + 1.84776, 9.23463, + 3, 10, + 2.77164, 11.1481, + 2.12132, 12.1213, + 1.14805, 12.7716, + 1.83697e-16, 13, + -1.14805, 12.7716, + -2.12132, 12.1213, + -2.77164, 11.1481, + -3, 10, + -2.77164, 8.85195, + -2.12132, 7.87868, + -1.14805, 7.22836, + -5.51091e-16, 7, + 1.14805, 7.22836, + 2.12132, 7.87868, + 2.77164, 8.85195, + 4, 10, + 3.69552, 11.5307, + 2.82843, 12.8284, + 1.53073, 13.6955, + 2.44929e-16, 14, + -1.53073, 13.6955, + -2.82843, 12.8284, + -3.69552, 11.5307, + -4, 10, + -3.69552, 8.46927, + -2.82843, 7.17157, + -1.53073, 6.30448, + -7.34788e-16, 6, + 1.53073, 6.30448, + 2.82843, 7.17157, + 3.69552, 8.46927, + 11, -20, + 10.9239, -19.6173, + 10.7071, -19.2929, + 10.3827, -19.0761, + 10, -19, + 9.61732, -19.0761, + 9.29289, -19.2929, + 9.07612, -19.6173, + 9, -20, + 9.07612, -20.3827, + 9.29289, -20.7071, + 9.61732, -20.9239, + 10, -21, + 10.3827, -20.9239, + 10.7071, -20.7071, + 10.9239, -20.3827, + 12, -20, + 11.8478, -19.2346, + 11.4142, -18.5858, + 10.7654, -18.1522, + 10, -18, + 9.23463, -18.1522, + 8.58579, -18.5858, + 8.15224, -19.2346, + 8, -20, + 8.15224, -20.7654, + 8.58579, -21.4142, + 9.23463, -21.8478, + 10, -22, + 10.7654, -21.8478, + 11.4142, -21.4142, + 11.8478, -20.7654, + 13, -20, + 12.7716, -18.8519, + 12.1213, -17.8787, + 11.1481, -17.2284, + 10, -17, + 8.85195, -17.2284, + 7.87868, -17.8787, + 7.22836, -18.8519, + 7, -20, + 7.22836, -21.1481, + 7.87868, -22.1213, + 8.85195, -22.7716, + 10, -23, + 11.1481, -22.7716, + 12.1213, -22.1213, + 12.7716, -21.1481, + 14, -20, + 13.6955, -18.4693, + 12.8284, -17.1716, + 11.5307, -16.3045, + 10, -16, + 8.46927, -16.3045, + 7.17157, -17.1716, + 6.30448, -18.4693, + 6, -20, + 6.30448, -21.5307, + 7.17157, -22.8284, + 8.46927, -23.6955, + 10, -24, + 11.5307, -23.6955, + 12.8284, -22.8284, + 13.6955, -21.5307, + 11, -10, + 10.9239, -9.61732, + 10.7071, -9.29289, + 10.3827, -9.07612, + 10, -9, + 9.61732, -9.07612, + 9.29289, -9.29289, + 9.07612, -9.61732, + 9, -10, + 9.07612, -10.3827, + 9.29289, -10.7071, + 9.61732, -10.9239, + 10, -11, + 10.3827, -10.9239, + 10.7071, -10.7071, + 10.9239, -10.3827, + 12, -10, + 11.8478, -9.23463, + 11.4142, -8.58579, + 10.7654, -8.15224, + 10, -8, + 9.23463, -8.15224, + 8.58579, -8.58579, + 8.15224, -9.23463, + 8, -10, + 8.15224, -10.7654, + 8.58579, -11.4142, + 9.23463, -11.8478, + 10, -12, + 10.7654, -11.8478, + 11.4142, -11.4142, + 11.8478, -10.7654, + 13, -10, + 12.7716, -8.85195, + 12.1213, -7.87868, + 11.1481, -7.22836, + 10, -7, + 8.85195, -7.22836, + 7.87868, -7.87868, + 7.22836, -8.85195, + 7, -10, + 7.22836, -11.1481, + 7.87868, -12.1213, + 8.85195, -12.7716, + 10, -13, + 11.1481, -12.7716, + 12.1213, -12.1213, + 12.7716, -11.1481, + 14, -10, + 13.6955, -8.46927, + 12.8284, -7.17157, + 11.5307, -6.30448, + 10, -6, + 8.46927, -6.30448, + 7.17157, -7.17157, + 6.30448, -8.46927, + 6, -10, + 6.30448, -11.5307, + 7.17157, -12.8284, + 8.46927, -13.6955, + 10, -14, + 11.5307, -13.6955, + 12.8284, -12.8284, + 13.6955, -11.5307, + 11, 0, + 10.9239, 0.382683, + 10.7071, 0.707107, + 10.3827, 0.92388, + 10, 1, + 9.61732, 0.92388, + 9.29289, 0.707107, + 9.07612, 0.382683, + 9, 1.22465e-16, + 9.07612, -0.382683, + 9.29289, -0.707107, + 9.61732, -0.92388, + 10, -1, + 10.3827, -0.92388, + 10.7071, -0.707107, + 10.9239, -0.382683, + 12, 0, + 11.8478, 0.765367, + 11.4142, 1.41421, + 10.7654, 1.84776, + 10, 2, + 9.23463, 1.84776, + 8.58579, 1.41421, + 8.15224, 0.765367, + 8, 2.44929e-16, + 8.15224, -0.765367, + 8.58579, -1.41421, + 9.23463, -1.84776, + 10, -2, + 10.7654, -1.84776, + 11.4142, -1.41421, + 11.8478, -0.765367, + 13, 0, + 12.7716, 1.14805, + 12.1213, 2.12132, + 11.1481, 2.77164, + 10, 3, + 8.85195, 2.77164, + 7.87868, 2.12132, + 7.22836, 1.14805, + 7, 3.67394e-16, + 7.22836, -1.14805, + 7.87868, -2.12132, + 8.85195, -2.77164, + 10, -3, + 11.1481, -2.77164, + 12.1213, -2.12132, + 12.7716, -1.14805, + 14, 0, + 13.6955, 1.53073, + 12.8284, 2.82843, + 11.5307, 3.69552, + 10, 4, + 8.46927, 3.69552, + 7.17157, 2.82843, + 6.30448, 1.53073, + 6, 4.89859e-16, + 6.30448, -1.53073, + 7.17157, -2.82843, + 8.46927, -3.69552, + 10, -4, + 11.5307, -3.69552, + 12.8284, -2.82843, + 13.6955, -1.53073, + 11, 10, + 10.9239, 10.3827, + 10.7071, 10.7071, + 10.3827, 10.9239, + 10, 11, + 9.61732, 10.9239, + 9.29289, 10.7071, + 9.07612, 10.3827, + 9, 10, + 9.07612, 9.61732, + 9.29289, 9.29289, + 9.61732, 9.07612, + 10, 9, + 10.3827, 9.07612, + 10.7071, 9.29289, + 10.9239, 9.61732, + 12, 10, + 11.8478, 10.7654, + 11.4142, 11.4142, + 10.7654, 11.8478, + 10, 12, + 9.23463, 11.8478, + 8.58579, 11.4142, + 8.15224, 10.7654, + 8, 10, + 8.15224, 9.23463, + 8.58579, 8.58579, + 9.23463, 8.15224, + 10, 8, + 10.7654, 8.15224, + 11.4142, 8.58579, + 11.8478, 9.23463, + 13, 10, + 12.7716, 11.1481, + 12.1213, 12.1213, + 11.1481, 12.7716, + 10, 13, + 8.85195, 12.7716, + 7.87868, 12.1213, + 7.22836, 11.1481, + 7, 10, + 7.22836, 8.85195, + 7.87868, 7.87868, + 8.85195, 7.22836, + 10, 7, + 11.1481, 7.22836, + 12.1213, 7.87868, + 12.7716, 8.85195, + 14, 10, + 13.6955, 11.5307, + 12.8284, 12.8284, + 11.5307, 13.6955, + 10, 14, + 8.46927, 13.6955, + 7.17157, 12.8284, + 6.30448, 11.5307, + 6, 10, + 6.30448, 8.46927, + 7.17157, 7.17157, + 8.46927, 6.30448, + 10, 6, + 11.5307, 6.30448, + 12.8284, 7.17157, + 13.6955, 8.46927 +}; +static const unsigned some_enclosures_segments_count = 1024; +static const unsigned some_enclosures_segments[2048] = +{ + 0, 1, + 1, 2, + 2, 3, + 3, 4, + 4, 5, + 5, 6, + 6, 7, + 7, 8, + 8, 9, + 9, 10, + 10, 11, + 11, 12, + 12, 13, + 13, 14, + 14, 15, + 15, 0, + 16, 17, + 17, 18, + 18, 19, + 19, 20, + 20, 21, + 21, 22, + 22, 23, + 23, 24, + 24, 25, + 25, 26, + 26, 27, + 27, 28, + 28, 29, + 29, 30, + 30, 31, + 31, 16, + 32, 33, + 33, 34, + 34, 35, + 35, 36, + 36, 37, + 37, 38, + 38, 39, + 39, 40, + 40, 41, + 41, 42, + 42, 43, + 43, 44, + 44, 45, + 45, 46, + 46, 47, + 47, 32, + 48, 49, + 49, 50, + 50, 51, + 51, 52, + 52, 53, + 53, 54, + 54, 55, + 55, 56, + 56, 57, + 57, 58, + 58, 59, + 59, 60, + 60, 61, + 61, 62, + 62, 63, + 63, 48, + 64, 65, + 65, 66, + 66, 67, + 67, 68, + 68, 69, + 69, 70, + 70, 71, + 71, 72, + 72, 73, + 73, 74, + 74, 75, + 75, 76, + 76, 77, + 77, 78, + 78, 79, + 79, 64, + 80, 81, + 81, 82, + 82, 83, + 83, 84, + 84, 85, + 85, 86, + 86, 87, + 87, 88, + 88, 89, + 89, 90, + 90, 91, + 91, 92, + 92, 93, + 93, 94, + 94, 95, + 95, 80, + 96, 97, + 97, 98, + 98, 99, + 99, 100, + 100, 101, + 101, 102, + 102, 103, + 103, 104, + 104, 105, + 105, 106, + 106, 107, + 107, 108, + 108, 109, + 109, 110, + 110, 111, + 111, 96, + 112, 113, + 113, 114, + 114, 115, + 115, 116, + 116, 117, + 117, 118, + 118, 119, + 119, 120, + 120, 121, + 121, 122, + 122, 123, + 123, 124, + 124, 125, + 125, 126, + 126, 127, + 127, 112, + 128, 129, + 129, 130, + 130, 131, + 131, 132, + 132, 133, + 133, 134, + 134, 135, + 135, 136, + 136, 137, + 137, 138, + 138, 139, + 139, 140, + 140, 141, + 141, 142, + 142, 143, + 143, 128, + 144, 145, + 145, 146, + 146, 147, + 147, 148, + 148, 149, + 149, 150, + 150, 151, + 151, 152, + 152, 153, + 153, 154, + 154, 155, + 155, 156, + 156, 157, + 157, 158, + 158, 159, + 159, 144, + 160, 161, + 161, 162, + 162, 163, + 163, 164, + 164, 165, + 165, 166, + 166, 167, + 167, 168, + 168, 169, + 169, 170, + 170, 171, + 171, 172, + 172, 173, + 173, 174, + 174, 175, + 175, 160, + 176, 177, + 177, 178, + 178, 179, + 179, 180, + 180, 181, + 181, 182, + 182, 183, + 183, 184, + 184, 185, + 185, 186, + 186, 187, + 187, 188, + 188, 189, + 189, 190, + 190, 191, + 191, 176, + 192, 193, + 193, 194, + 194, 195, + 195, 196, + 196, 197, + 197, 198, + 198, 199, + 199, 200, + 200, 201, + 201, 202, + 202, 203, + 203, 204, + 204, 205, + 205, 206, + 206, 207, + 207, 192, + 208, 209, + 209, 210, + 210, 211, + 211, 212, + 212, 213, + 213, 214, + 214, 215, + 215, 216, + 216, 217, + 217, 218, + 218, 219, + 219, 220, + 220, 221, + 221, 222, + 222, 223, + 223, 208, + 224, 225, + 225, 226, + 226, 227, + 227, 228, + 228, 229, + 229, 230, + 230, 231, + 231, 232, + 232, 233, + 233, 234, + 234, 235, + 235, 236, + 236, 237, + 237, 238, + 238, 239, + 239, 224, + 240, 241, + 241, 242, + 242, 243, + 243, 244, + 244, 245, + 245, 246, + 246, 247, + 247, 248, + 248, 249, + 249, 250, + 250, 251, + 251, 252, + 252, 253, + 253, 254, + 254, 255, + 255, 240, + 256, 257, + 257, 258, + 258, 259, + 259, 260, + 260, 261, + 261, 262, + 262, 263, + 263, 264, + 264, 265, + 265, 266, + 266, 267, + 267, 268, + 268, 269, + 269, 270, + 270, 271, + 271, 256, + 272, 273, + 273, 274, + 274, 275, + 275, 276, + 276, 277, + 277, 278, + 278, 279, + 279, 280, + 280, 281, + 281, 282, + 282, 283, + 283, 284, + 284, 285, + 285, 286, + 286, 287, + 287, 272, + 288, 289, + 289, 290, + 290, 291, + 291, 292, + 292, 293, + 293, 294, + 294, 295, + 295, 296, + 296, 297, + 297, 298, + 298, 299, + 299, 300, + 300, 301, + 301, 302, + 302, 303, + 303, 288, + 304, 305, + 305, 306, + 306, 307, + 307, 308, + 308, 309, + 309, 310, + 310, 311, + 311, 312, + 312, 313, + 313, 314, + 314, 315, + 315, 316, + 316, 317, + 317, 318, + 318, 319, + 319, 304, + 320, 321, + 321, 322, + 322, 323, + 323, 324, + 324, 325, + 325, 326, + 326, 327, + 327, 328, + 328, 329, + 329, 330, + 330, 331, + 331, 332, + 332, 333, + 333, 334, + 334, 335, + 335, 320, + 336, 337, + 337, 338, + 338, 339, + 339, 340, + 340, 341, + 341, 342, + 342, 343, + 343, 344, + 344, 345, + 345, 346, + 346, 347, + 347, 348, + 348, 349, + 349, 350, + 350, 351, + 351, 336, + 352, 353, + 353, 354, + 354, 355, + 355, 356, + 356, 357, + 357, 358, + 358, 359, + 359, 360, + 360, 361, + 361, 362, + 362, 363, + 363, 364, + 364, 365, + 365, 366, + 366, 367, + 367, 352, + 368, 369, + 369, 370, + 370, 371, + 371, 372, + 372, 373, + 373, 374, + 374, 375, + 375, 376, + 376, 377, + 377, 378, + 378, 379, + 379, 380, + 380, 381, + 381, 382, + 382, 383, + 383, 368, + 384, 385, + 385, 386, + 386, 387, + 387, 388, + 388, 389, + 389, 390, + 390, 391, + 391, 392, + 392, 393, + 393, 394, + 394, 395, + 395, 396, + 396, 397, + 397, 398, + 398, 399, + 399, 384, + 400, 401, + 401, 402, + 402, 403, + 403, 404, + 404, 405, + 405, 406, + 406, 407, + 407, 408, + 408, 409, + 409, 410, + 410, 411, + 411, 412, + 412, 413, + 413, 414, + 414, 415, + 415, 400, + 416, 417, + 417, 418, + 418, 419, + 419, 420, + 420, 421, + 421, 422, + 422, 423, + 423, 424, + 424, 425, + 425, 426, + 426, 427, + 427, 428, + 428, 429, + 429, 430, + 430, 431, + 431, 416, + 432, 433, + 433, 434, + 434, 435, + 435, 436, + 436, 437, + 437, 438, + 438, 439, + 439, 440, + 440, 441, + 441, 442, + 442, 443, + 443, 444, + 444, 445, + 445, 446, + 446, 447, + 447, 432, + 448, 449, + 449, 450, + 450, 451, + 451, 452, + 452, 453, + 453, 454, + 454, 455, + 455, 456, + 456, 457, + 457, 458, + 458, 459, + 459, 460, + 460, 461, + 461, 462, + 462, 463, + 463, 448, + 464, 465, + 465, 466, + 466, 467, + 467, 468, + 468, 469, + 469, 470, + 470, 471, + 471, 472, + 472, 473, + 473, 474, + 474, 475, + 475, 476, + 476, 477, + 477, 478, + 478, 479, + 479, 464, + 480, 481, + 481, 482, + 482, 483, + 483, 484, + 484, 485, + 485, 486, + 486, 487, + 487, 488, + 488, 489, + 489, 490, + 490, 491, + 491, 492, + 492, 493, + 493, 494, + 494, 495, + 495, 480, + 496, 497, + 497, 498, + 498, 499, + 499, 500, + 500, 501, + 501, 502, + 502, 503, + 503, 504, + 504, 505, + 505, 506, + 506, 507, + 507, 508, + 508, 509, + 509, 510, + 510, 511, + 511, 496, + 512, 513, + 513, 514, + 514, 515, + 515, 516, + 516, 517, + 517, 518, + 518, 519, + 519, 520, + 520, 521, + 521, 522, + 522, 523, + 523, 524, + 524, 525, + 525, 526, + 526, 527, + 527, 512, + 528, 529, + 529, 530, + 530, 531, + 531, 532, + 532, 533, + 533, 534, + 534, 535, + 535, 536, + 536, 537, + 537, 538, + 538, 539, + 539, 540, + 540, 541, + 541, 542, + 542, 543, + 543, 528, + 544, 545, + 545, 546, + 546, 547, + 547, 548, + 548, 549, + 549, 550, + 550, 551, + 551, 552, + 552, 553, + 553, 554, + 554, 555, + 555, 556, + 556, 557, + 557, 558, + 558, 559, + 559, 544, + 560, 561, + 561, 562, + 562, 563, + 563, 564, + 564, 565, + 565, 566, + 566, 567, + 567, 568, + 568, 569, + 569, 570, + 570, 571, + 571, 572, + 572, 573, + 573, 574, + 574, 575, + 575, 560, + 576, 577, + 577, 578, + 578, 579, + 579, 580, + 580, 581, + 581, 582, + 582, 583, + 583, 584, + 584, 585, + 585, 586, + 586, 587, + 587, 588, + 588, 589, + 589, 590, + 590, 591, + 591, 576, + 592, 593, + 593, 594, + 594, 595, + 595, 596, + 596, 597, + 597, 598, + 598, 599, + 599, 600, + 600, 601, + 601, 602, + 602, 603, + 603, 604, + 604, 605, + 605, 606, + 606, 607, + 607, 592, + 608, 609, + 609, 610, + 610, 611, + 611, 612, + 612, 613, + 613, 614, + 614, 615, + 615, 616, + 616, 617, + 617, 618, + 618, 619, + 619, 620, + 620, 621, + 621, 622, + 622, 623, + 623, 608, + 624, 625, + 625, 626, + 626, 627, + 627, 628, + 628, 629, + 629, 630, + 630, 631, + 631, 632, + 632, 633, + 633, 634, + 634, 635, + 635, 636, + 636, 637, + 637, 638, + 638, 639, + 639, 624, + 640, 641, + 641, 642, + 642, 643, + 643, 644, + 644, 645, + 645, 646, + 646, 647, + 647, 648, + 648, 649, + 649, 650, + 650, 651, + 651, 652, + 652, 653, + 653, 654, + 654, 655, + 655, 640, + 656, 657, + 657, 658, + 658, 659, + 659, 660, + 660, 661, + 661, 662, + 662, 663, + 663, 664, + 664, 665, + 665, 666, + 666, 667, + 667, 668, + 668, 669, + 669, 670, + 670, 671, + 671, 656, + 672, 673, + 673, 674, + 674, 675, + 675, 676, + 676, 677, + 677, 678, + 678, 679, + 679, 680, + 680, 681, + 681, 682, + 682, 683, + 683, 684, + 684, 685, + 685, 686, + 686, 687, + 687, 672, + 688, 689, + 689, 690, + 690, 691, + 691, 692, + 692, 693, + 693, 694, + 694, 695, + 695, 696, + 696, 697, + 697, 698, + 698, 699, + 699, 700, + 700, 701, + 701, 702, + 702, 703, + 703, 688, + 704, 705, + 705, 706, + 706, 707, + 707, 708, + 708, 709, + 709, 710, + 710, 711, + 711, 712, + 712, 713, + 713, 714, + 714, 715, + 715, 716, + 716, 717, + 717, 718, + 718, 719, + 719, 704, + 720, 721, + 721, 722, + 722, 723, + 723, 724, + 724, 725, + 725, 726, + 726, 727, + 727, 728, + 728, 729, + 729, 730, + 730, 731, + 731, 732, + 732, 733, + 733, 734, + 734, 735, + 735, 720, + 736, 737, + 737, 738, + 738, 739, + 739, 740, + 740, 741, + 741, 742, + 742, 743, + 743, 744, + 744, 745, + 745, 746, + 746, 747, + 747, 748, + 748, 749, + 749, 750, + 750, 751, + 751, 736, + 752, 753, + 753, 754, + 754, 755, + 755, 756, + 756, 757, + 757, 758, + 758, 759, + 759, 760, + 760, 761, + 761, 762, + 762, 763, + 763, 764, + 764, 765, + 765, 766, + 766, 767, + 767, 752, + 768, 769, + 769, 770, + 770, 771, + 771, 772, + 772, 773, + 773, 774, + 774, 775, + 775, 776, + 776, 777, + 777, 778, + 778, 779, + 779, 780, + 780, 781, + 781, 782, + 782, 783, + 783, 768, + 784, 785, + 785, 786, + 786, 787, + 787, 788, + 788, 789, + 789, 790, + 790, 791, + 791, 792, + 792, 793, + 793, 794, + 794, 795, + 795, 796, + 796, 797, + 797, 798, + 798, 799, + 799, 784, + 800, 801, + 801, 802, + 802, 803, + 803, 804, + 804, 805, + 805, 806, + 806, 807, + 807, 808, + 808, 809, + 809, 810, + 810, 811, + 811, 812, + 812, 813, + 813, 814, + 814, 815, + 815, 800, + 816, 817, + 817, 818, + 818, 819, + 819, 820, + 820, 821, + 821, 822, + 822, 823, + 823, 824, + 824, 825, + 825, 826, + 826, 827, + 827, 828, + 828, 829, + 829, 830, + 830, 831, + 831, 816, + 832, 833, + 833, 834, + 834, 835, + 835, 836, + 836, 837, + 837, 838, + 838, 839, + 839, 840, + 840, 841, + 841, 842, + 842, 843, + 843, 844, + 844, 845, + 845, 846, + 846, 847, + 847, 832, + 848, 849, + 849, 850, + 850, 851, + 851, 852, + 852, 853, + 853, 854, + 854, 855, + 855, 856, + 856, 857, + 857, 858, + 858, 859, + 859, 860, + 860, 861, + 861, 862, + 862, 863, + 863, 848, + 864, 865, + 865, 866, + 866, 867, + 867, 868, + 868, 869, + 869, 870, + 870, 871, + 871, 872, + 872, 873, + 873, 874, + 874, 875, + 875, 876, + 876, 877, + 877, 878, + 878, 879, + 879, 864, + 880, 881, + 881, 882, + 882, 883, + 883, 884, + 884, 885, + 885, 886, + 886, 887, + 887, 888, + 888, 889, + 889, 890, + 890, 891, + 891, 892, + 892, 893, + 893, 894, + 894, 895, + 895, 880, + 896, 897, + 897, 898, + 898, 899, + 899, 900, + 900, 901, + 901, 902, + 902, 903, + 903, 904, + 904, 905, + 905, 906, + 906, 907, + 907, 908, + 908, 909, + 909, 910, + 910, 911, + 911, 896, + 912, 913, + 913, 914, + 914, 915, + 915, 916, + 916, 917, + 917, 918, + 918, 919, + 919, 920, + 920, 921, + 921, 922, + 922, 923, + 923, 924, + 924, 925, + 925, 926, + 926, 927, + 927, 912, + 928, 929, + 929, 930, + 930, 931, + 931, 932, + 932, 933, + 933, 934, + 934, 935, + 935, 936, + 936, 937, + 937, 938, + 938, 939, + 939, 940, + 940, 941, + 941, 942, + 942, 943, + 943, 928, + 944, 945, + 945, 946, + 946, 947, + 947, 948, + 948, 949, + 949, 950, + 950, 951, + 951, 952, + 952, 953, + 953, 954, + 954, 955, + 955, 956, + 956, 957, + 957, 958, + 958, 959, + 959, 944, + 960, 961, + 961, 962, + 962, 963, + 963, 964, + 964, 965, + 965, 966, + 966, 967, + 967, 968, + 968, 969, + 969, 970, + 970, 971, + 971, 972, + 972, 973, + 973, 974, + 974, 975, + 975, 960, + 976, 977, + 977, 978, + 978, 979, + 979, 980, + 980, 981, + 981, 982, + 982, 983, + 983, 984, + 984, 985, + 985, 986, + 986, 987, + 987, 988, + 988, 989, + 989, 990, + 990, 991, + 991, 976, + 992, 993, + 993, 994, + 994, 995, + 995, 996, + 996, 997, + 997, 998, + 998, 999, + 999, 1000, + 1000, 1001, + 1001, 1002, + 1002, 1003, + 1003, 1004, + 1004, 1005, + 1005, 1006, + 1006, 1007, + 1007, 992, + 1008, 1009, + 1009, 1010, + 1010, 1011, + 1011, 1012, + 1012, 1013, + 1013, 1014, + 1014, 1015, + 1015, 1016, + 1016, 1017, + 1017, 1018, + 1018, 1019, + 1019, 1020, + 1020, 1021, + 1021, 1022, + 1022, 1023, + 1023, 1008 +}; +static const unsigned some_enclosures_properties[3072] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0 +}; + +#define NB_CIRC_X 4 +#define NB_CIRC_Y 4 +#define NB_CIRC_Z 4 +#define NB_CIRC (NB_CIRC_X * NB_CIRC_Y * NB_CIRC_Z) +#define CIRC_VRTX_COUNT 16u +#define CIRC_SEG_COUNT 16u + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc2d_device* dev = NULL; + struct senc2d_scene* scn = NULL; + struct context ctx = CONTEXT_NULL__; + unsigned e, count; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); + + /* Create a scene */ + ctx.positions = some_enclosures_vertices; + ctx.indices = some_enclosures_segments; + ctx.properties = some_enclosures_properties; + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + some_enclosures_segments_count, get_indices, get_media_from_properties, + some_enclosures_vertices_count, get_position, &ctx, &scn)); + + OK(senc2d_scene_get_vertices_count(scn, &count)); + CHK(count == some_enclosures_vertices_count); + CHK(count == NB_CIRC * CIRC_VRTX_COUNT); + OK(senc2d_scene_get_segments_count(scn, &count)); + CHK(count == some_enclosures_segments_count); + CHK(count == NB_CIRC * CIRC_SEG_COUNT); + + OK(senc2d_scene_get_enclosure_count(scn, &count)); + CHK(count == 1 + NB_CIRC); + FOR_EACH(e, 0, count) { + struct senc2d_enclosure* enclosure; + struct senc2d_enclosure_header header; + unsigned m; + OK(senc2d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); + CHK(header.enclosed_media_count == 1); + OK(senc2d_enclosure_get_medium(enclosure, 0, &m)); + CHK(header.primitives_count == + (header.is_infinite /* Outermost enclosure: NB_CIRC_X*NB_CIRC_Y circles */ + ? NB_CIRC_X * NB_CIRC_Y * CIRC_SEG_COUNT + : (m == 0 + ? CIRC_SEG_COUNT /* Innermost enclosures: 1 circle */ + : 2 * CIRC_SEG_COUNT))); /* Other enclosures: 2 circles */ + OK(senc2d_enclosure_ref_put(enclosure)); + } + + OK(senc2d_scene_ref_put(scn)); + OK(senc2d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_senc2d_some_segments.c b/src/test_senc2d_some_segments.c @@ -0,0 +1,3259 @@ +/* Copyright (C) |Meso|Star> 2018-2020 (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/>. */ + +/* This test has been created using the sg2_geometry_dump_as_C_code feature + * of star-geometry-2D. It uses output from test_sg2_some_segments. + * This test is similar to test_senc2d_many_segments that creates a huge + * geometry by program. */ + +#include "senc2d.h" +#include "test_senc2d_utils.h" + +#include <rsys/double2.h> + +/* Dump of star-geometry-2D 'some_segments'. */ +static const unsigned some_segments_vertices_count = 1056; +static const double some_segments_vertices[2112] = +{ + 1, 0, + 0.999717, 0.0237977, + 0.998867, 0.0475819, + 0.997452, 0.0713392, + 0.995472, 0.095056, + 0.992928, 0.118719, + 0.989821, 0.142315, + 0.986154, 0.16583, + 0.981929, 0.189251, + 0.977147, 0.212565, + 0.971812, 0.235759, + 0.965926, 0.258819, + 0.959493, 0.281733, + 0.952517, 0.304486, + 0.945001, 0.327068, + 0.93695, 0.349464, + 0.928368, 0.371662, + 0.91926, 0.39365, + 0.909632, 0.415415, + 0.899488, 0.436945, + 0.888835, 0.458227, + 0.877679, 0.479249, + 0.866025, 0.5, + 0.853881, 0.520468, + 0.841254, 0.540641, + 0.828149, 0.560508, + 0.814576, 0.580057, + 0.800541, 0.599278, + 0.786053, 0.618159, + 0.77112, 0.63669, + 0.75575, 0.654861, + 0.739951, 0.67266, + 0.723734, 0.690079, + 0.707107, 0.707107, + 0.690079, 0.723734, + 0.67266, 0.739951, + 0.654861, 0.75575, + 0.63669, 0.77112, + 0.618159, 0.786053, + 0.599278, 0.800541, + 0.580057, 0.814576, + 0.560508, 0.828149, + 0.540641, 0.841254, + 0.520468, 0.853881, + 0.5, 0.866025, + 0.479249, 0.877679, + 0.458227, 0.888835, + 0.436945, 0.899488, + 0.415415, 0.909632, + 0.39365, 0.91926, + 0.371662, 0.928368, + 0.349464, 0.93695, + 0.327068, 0.945001, + 0.304486, 0.952517, + 0.281733, 0.959493, + 0.258819, 0.965926, + 0.235759, 0.971812, + 0.212565, 0.977147, + 0.189251, 0.981929, + 0.16583, 0.986154, + 0.142315, 0.989821, + 0.118719, 0.992928, + 0.095056, 0.995472, + 0.0713392, 0.997452, + 0.0475819, 0.998867, + 0.0237977, 0.999717, + 6.12323e-17, 1, + -0.0237977, 0.999717, + -0.0475819, 0.998867, + -0.0713392, 0.997452, + -0.095056, 0.995472, + -0.118719, 0.992928, + -0.142315, 0.989821, + -0.16583, 0.986154, + -0.189251, 0.981929, + -0.212565, 0.977147, + -0.235759, 0.971812, + -0.258819, 0.965926, + -0.281733, 0.959493, + -0.304486, 0.952517, + -0.327068, 0.945001, + -0.349464, 0.93695, + -0.371662, 0.928368, + -0.39365, 0.91926, + -0.415415, 0.909632, + -0.436945, 0.899488, + -0.458227, 0.888835, + -0.479249, 0.877679, + -0.5, 0.866025, + -0.520468, 0.853881, + -0.540641, 0.841254, + -0.560508, 0.828149, + -0.580057, 0.814576, + -0.599278, 0.800541, + -0.618159, 0.786053, + -0.63669, 0.77112, + -0.654861, 0.75575, + -0.67266, 0.739951, + -0.690079, 0.723734, + -0.707107, 0.707107, + -0.723734, 0.690079, + -0.739951, 0.67266, + -0.75575, 0.654861, + -0.77112, 0.63669, + -0.786053, 0.618159, + -0.800541, 0.599278, + -0.814576, 0.580057, + -0.828149, 0.560508, + -0.841254, 0.540641, + -0.853881, 0.520468, + -0.866025, 0.5, + -0.877679, 0.479249, + -0.888835, 0.458227, + -0.899488, 0.436945, + -0.909632, 0.415415, + -0.91926, 0.39365, + -0.928368, 0.371662, + -0.93695, 0.349464, + -0.945001, 0.327068, + -0.952517, 0.304486, + -0.959493, 0.281733, + -0.965926, 0.258819, + -0.971812, 0.235759, + -0.977147, 0.212565, + -0.981929, 0.189251, + -0.986154, 0.16583, + -0.989821, 0.142315, + -0.992928, 0.118719, + -0.995472, 0.095056, + -0.997452, 0.0713392, + -0.998867, 0.0475819, + -0.999717, 0.0237977, + -1, 1.22465e-16, + -0.999717, -0.0237977, + -0.998867, -0.0475819, + -0.997452, -0.0713392, + -0.995472, -0.095056, + -0.992928, -0.118719, + -0.989821, -0.142315, + -0.986154, -0.16583, + -0.981929, -0.189251, + -0.977147, -0.212565, + -0.971812, -0.235759, + -0.965926, -0.258819, + -0.959493, -0.281733, + -0.952517, -0.304486, + -0.945001, -0.327068, + -0.93695, -0.349464, + -0.928368, -0.371662, + -0.91926, -0.39365, + -0.909632, -0.415415, + -0.899488, -0.436945, + -0.888835, -0.458227, + -0.877679, -0.479249, + -0.866025, -0.5, + -0.853881, -0.520468, + -0.841254, -0.540641, + -0.828149, -0.560508, + -0.814576, -0.580057, + -0.800541, -0.599278, + -0.786053, -0.618159, + -0.77112, -0.63669, + -0.75575, -0.654861, + -0.739951, -0.67266, + -0.723734, -0.690079, + -0.707107, -0.707107, + -0.690079, -0.723734, + -0.67266, -0.739951, + -0.654861, -0.75575, + -0.63669, -0.77112, + -0.618159, -0.786053, + -0.599278, -0.800541, + -0.580057, -0.814576, + -0.560508, -0.828149, + -0.540641, -0.841254, + -0.520468, -0.853881, + -0.5, -0.866025, + -0.479249, -0.877679, + -0.458227, -0.888835, + -0.436945, -0.899488, + -0.415415, -0.909632, + -0.39365, -0.91926, + -0.371662, -0.928368, + -0.349464, -0.93695, + -0.327068, -0.945001, + -0.304486, -0.952517, + -0.281733, -0.959493, + -0.258819, -0.965926, + -0.235759, -0.971812, + -0.212565, -0.977147, + -0.189251, -0.981929, + -0.16583, -0.986154, + -0.142315, -0.989821, + -0.118719, -0.992928, + -0.095056, -0.995472, + -0.0713392, -0.997452, + -0.0475819, -0.998867, + -0.0237977, -0.999717, + -1.83697e-16, -1, + 0.0237977, -0.999717, + 0.0475819, -0.998867, + 0.0713392, -0.997452, + 0.095056, -0.995472, + 0.118719, -0.992928, + 0.142315, -0.989821, + 0.16583, -0.986154, + 0.189251, -0.981929, + 0.212565, -0.977147, + 0.235759, -0.971812, + 0.258819, -0.965926, + 0.281733, -0.959493, + 0.304486, -0.952517, + 0.327068, -0.945001, + 0.349464, -0.93695, + 0.371662, -0.928368, + 0.39365, -0.91926, + 0.415415, -0.909632, + 0.436945, -0.899488, + 0.458227, -0.888835, + 0.479249, -0.877679, + 0.5, -0.866025, + 0.520468, -0.853881, + 0.540641, -0.841254, + 0.560508, -0.828149, + 0.580057, -0.814576, + 0.599278, -0.800541, + 0.618159, -0.786053, + 0.63669, -0.77112, + 0.654861, -0.75575, + 0.67266, -0.739951, + 0.690079, -0.723734, + 0.707107, -0.707107, + 0.723734, -0.690079, + 0.739951, -0.67266, + 0.75575, -0.654861, + 0.77112, -0.63669, + 0.786053, -0.618159, + 0.800541, -0.599278, + 0.814576, -0.580057, + 0.828149, -0.560508, + 0.841254, -0.540641, + 0.853881, -0.520468, + 0.866025, -0.5, + 0.877679, -0.479249, + 0.888835, -0.458227, + 0.899488, -0.436945, + 0.909632, -0.415415, + 0.91926, -0.39365, + 0.928368, -0.371662, + 0.93695, -0.349464, + 0.945001, -0.327068, + 0.952517, -0.304486, + 0.959493, -0.281733, + 0.965926, -0.258819, + 0.971812, -0.235759, + 0.977147, -0.212565, + 0.981929, -0.189251, + 0.986154, -0.16583, + 0.989821, -0.142315, + 0.992928, -0.118719, + 0.995472, -0.095056, + 0.997452, -0.0713392, + 0.998867, -0.0475819, + 0.999717, -0.0237977, + 1, 10, + 0.999717, 10.0238, + 0.998867, 10.0476, + 0.997452, 10.0713, + 0.995472, 10.0951, + 0.992928, 10.1187, + 0.989821, 10.1423, + 0.986154, 10.1658, + 0.981929, 10.1893, + 0.977147, 10.2126, + 0.971812, 10.2358, + 0.965926, 10.2588, + 0.959493, 10.2817, + 0.952517, 10.3045, + 0.945001, 10.3271, + 0.93695, 10.3495, + 0.928368, 10.3717, + 0.91926, 10.3937, + 0.909632, 10.4154, + 0.899488, 10.4369, + 0.888835, 10.4582, + 0.877679, 10.4792, + 0.866025, 10.5, + 0.853881, 10.5205, + 0.841254, 10.5406, + 0.828149, 10.5605, + 0.814576, 10.5801, + 0.800541, 10.5993, + 0.786053, 10.6182, + 0.77112, 10.6367, + 0.75575, 10.6549, + 0.739951, 10.6727, + 0.723734, 10.6901, + 0.707107, 10.7071, + 0.690079, 10.7237, + 0.67266, 10.74, + 0.654861, 10.7557, + 0.63669, 10.7711, + 0.618159, 10.7861, + 0.599278, 10.8005, + 0.580057, 10.8146, + 0.560508, 10.8281, + 0.540641, 10.8413, + 0.520468, 10.8539, + 0.5, 10.866, + 0.479249, 10.8777, + 0.458227, 10.8888, + 0.436945, 10.8995, + 0.415415, 10.9096, + 0.39365, 10.9193, + 0.371662, 10.9284, + 0.349464, 10.9369, + 0.327068, 10.945, + 0.304486, 10.9525, + 0.281733, 10.9595, + 0.258819, 10.9659, + 0.235759, 10.9718, + 0.212565, 10.9771, + 0.189251, 10.9819, + 0.16583, 10.9862, + 0.142315, 10.9898, + 0.118719, 10.9929, + 0.095056, 10.9955, + 0.0713392, 10.9975, + 0.0475819, 10.9989, + 0.0237977, 10.9997, + 6.12323e-17, 11, + -0.0237977, 10.9997, + -0.0475819, 10.9989, + -0.0713392, 10.9975, + -0.095056, 10.9955, + -0.118719, 10.9929, + -0.142315, 10.9898, + -0.16583, 10.9862, + -0.189251, 10.9819, + -0.212565, 10.9771, + -0.235759, 10.9718, + -0.258819, 10.9659, + -0.281733, 10.9595, + -0.304486, 10.9525, + -0.327068, 10.945, + -0.349464, 10.9369, + -0.371662, 10.9284, + -0.39365, 10.9193, + -0.415415, 10.9096, + -0.436945, 10.8995, + -0.458227, 10.8888, + -0.479249, 10.8777, + -0.5, 10.866, + -0.520468, 10.8539, + -0.540641, 10.8413, + -0.560508, 10.8281, + -0.580057, 10.8146, + -0.599278, 10.8005, + -0.618159, 10.7861, + -0.63669, 10.7711, + -0.654861, 10.7557, + -0.67266, 10.74, + -0.690079, 10.7237, + -0.707107, 10.7071, + -0.723734, 10.6901, + -0.739951, 10.6727, + -0.75575, 10.6549, + -0.77112, 10.6367, + -0.786053, 10.6182, + -0.800541, 10.5993, + -0.814576, 10.5801, + -0.828149, 10.5605, + -0.841254, 10.5406, + -0.853881, 10.5205, + -0.866025, 10.5, + -0.877679, 10.4792, + -0.888835, 10.4582, + -0.899488, 10.4369, + -0.909632, 10.4154, + -0.91926, 10.3937, + -0.928368, 10.3717, + -0.93695, 10.3495, + -0.945001, 10.3271, + -0.952517, 10.3045, + -0.959493, 10.2817, + -0.965926, 10.2588, + -0.971812, 10.2358, + -0.977147, 10.2126, + -0.981929, 10.1893, + -0.986154, 10.1658, + -0.989821, 10.1423, + -0.992928, 10.1187, + -0.995472, 10.0951, + -0.997452, 10.0713, + -0.998867, 10.0476, + -0.999717, 10.0238, + -1, 10, + -0.999717, 9.9762, + -0.998867, 9.95242, + -0.997452, 9.92866, + -0.995472, 9.90494, + -0.992928, 9.88128, + -0.989821, 9.85769, + -0.986154, 9.83417, + -0.981929, 9.81075, + -0.977147, 9.78743, + -0.971812, 9.76424, + -0.965926, 9.74118, + -0.959493, 9.71827, + -0.952517, 9.69551, + -0.945001, 9.67293, + -0.93695, 9.65054, + -0.928368, 9.62834, + -0.91926, 9.60635, + -0.909632, 9.58458, + -0.899488, 9.56306, + -0.888835, 9.54177, + -0.877679, 9.52075, + -0.866025, 9.5, + -0.853881, 9.47953, + -0.841254, 9.45936, + -0.828149, 9.43949, + -0.814576, 9.41994, + -0.800541, 9.40072, + -0.786053, 9.38184, + -0.77112, 9.36331, + -0.75575, 9.34514, + -0.739951, 9.32734, + -0.723734, 9.30992, + -0.707107, 9.29289, + -0.690079, 9.27627, + -0.67266, 9.26005, + -0.654861, 9.24425, + -0.63669, 9.22888, + -0.618159, 9.21395, + -0.599278, 9.19946, + -0.580057, 9.18542, + -0.560508, 9.17185, + -0.540641, 9.15875, + -0.520468, 9.14612, + -0.5, 9.13397, + -0.479249, 9.12232, + -0.458227, 9.11116, + -0.436945, 9.10051, + -0.415415, 9.09037, + -0.39365, 9.08074, + -0.371662, 9.07163, + -0.349464, 9.06305, + -0.327068, 9.055, + -0.304486, 9.04748, + -0.281733, 9.04051, + -0.258819, 9.03407, + -0.235759, 9.02819, + -0.212565, 9.02285, + -0.189251, 9.01807, + -0.16583, 9.01385, + -0.142315, 9.01018, + -0.118719, 9.00707, + -0.095056, 9.00453, + -0.0713392, 9.00255, + -0.0475819, 9.00113, + -0.0237977, 9.00028, + -1.83697e-16, 9, + 0.0237977, 9.00028, + 0.0475819, 9.00113, + 0.0713392, 9.00255, + 0.095056, 9.00453, + 0.118719, 9.00707, + 0.142315, 9.01018, + 0.16583, 9.01385, + 0.189251, 9.01807, + 0.212565, 9.02285, + 0.235759, 9.02819, + 0.258819, 9.03407, + 0.281733, 9.04051, + 0.304486, 9.04748, + 0.327068, 9.055, + 0.349464, 9.06305, + 0.371662, 9.07163, + 0.39365, 9.08074, + 0.415415, 9.09037, + 0.436945, 9.10051, + 0.458227, 9.11116, + 0.479249, 9.12232, + 0.5, 9.13397, + 0.520468, 9.14612, + 0.540641, 9.15875, + 0.560508, 9.17185, + 0.580057, 9.18542, + 0.599278, 9.19946, + 0.618159, 9.21395, + 0.63669, 9.22888, + 0.654861, 9.24425, + 0.67266, 9.26005, + 0.690079, 9.27627, + 0.707107, 9.29289, + 0.723734, 9.30992, + 0.739951, 9.32734, + 0.75575, 9.34514, + 0.77112, 9.36331, + 0.786053, 9.38184, + 0.800541, 9.40072, + 0.814576, 9.41994, + 0.828149, 9.43949, + 0.841254, 9.45936, + 0.853881, 9.47953, + 0.866025, 9.5, + 0.877679, 9.52075, + 0.888835, 9.54177, + 0.899488, 9.56306, + 0.909632, 9.58458, + 0.91926, 9.60635, + 0.928368, 9.62834, + 0.93695, 9.65054, + 0.945001, 9.67293, + 0.952517, 9.69551, + 0.959493, 9.71827, + 0.965926, 9.74118, + 0.971812, 9.76424, + 0.977147, 9.78743, + 0.981929, 9.81075, + 0.986154, 9.83417, + 0.989821, 9.85769, + 0.992928, 9.88128, + 0.995472, 9.90494, + 0.997452, 9.92866, + 0.998867, 9.95242, + 0.999717, 9.9762, + 1, 20, + 0.999717, 20.0238, + 0.998867, 20.0476, + 0.997452, 20.0713, + 0.995472, 20.0951, + 0.992928, 20.1187, + 0.989821, 20.1423, + 0.986154, 20.1658, + 0.981929, 20.1893, + 0.977147, 20.2126, + 0.971812, 20.2358, + 0.965926, 20.2588, + 0.959493, 20.2817, + 0.952517, 20.3045, + 0.945001, 20.3271, + 0.93695, 20.3495, + 0.928368, 20.3717, + 0.91926, 20.3937, + 0.909632, 20.4154, + 0.899488, 20.4369, + 0.888835, 20.4582, + 0.877679, 20.4792, + 0.866025, 20.5, + 0.853881, 20.5205, + 0.841254, 20.5406, + 0.828149, 20.5605, + 0.814576, 20.5801, + 0.800541, 20.5993, + 0.786053, 20.6182, + 0.77112, 20.6367, + 0.75575, 20.6549, + 0.739951, 20.6727, + 0.723734, 20.6901, + 0.707107, 20.7071, + 0.690079, 20.7237, + 0.67266, 20.74, + 0.654861, 20.7557, + 0.63669, 20.7711, + 0.618159, 20.7861, + 0.599278, 20.8005, + 0.580057, 20.8146, + 0.560508, 20.8281, + 0.540641, 20.8413, + 0.520468, 20.8539, + 0.5, 20.866, + 0.479249, 20.8777, + 0.458227, 20.8888, + 0.436945, 20.8995, + 0.415415, 20.9096, + 0.39365, 20.9193, + 0.371662, 20.9284, + 0.349464, 20.9369, + 0.327068, 20.945, + 0.304486, 20.9525, + 0.281733, 20.9595, + 0.258819, 20.9659, + 0.235759, 20.9718, + 0.212565, 20.9771, + 0.189251, 20.9819, + 0.16583, 20.9862, + 0.142315, 20.9898, + 0.118719, 20.9929, + 0.095056, 20.9955, + 0.0713392, 20.9975, + 0.0475819, 20.9989, + 0.0237977, 20.9997, + 6.12323e-17, 21, + -0.0237977, 20.9997, + -0.0475819, 20.9989, + -0.0713392, 20.9975, + -0.095056, 20.9955, + -0.118719, 20.9929, + -0.142315, 20.9898, + -0.16583, 20.9862, + -0.189251, 20.9819, + -0.212565, 20.9771, + -0.235759, 20.9718, + -0.258819, 20.9659, + -0.281733, 20.9595, + -0.304486, 20.9525, + -0.327068, 20.945, + -0.349464, 20.9369, + -0.371662, 20.9284, + -0.39365, 20.9193, + -0.415415, 20.9096, + -0.436945, 20.8995, + -0.458227, 20.8888, + -0.479249, 20.8777, + -0.5, 20.866, + -0.520468, 20.8539, + -0.540641, 20.8413, + -0.560508, 20.8281, + -0.580057, 20.8146, + -0.599278, 20.8005, + -0.618159, 20.7861, + -0.63669, 20.7711, + -0.654861, 20.7557, + -0.67266, 20.74, + -0.690079, 20.7237, + -0.707107, 20.7071, + -0.723734, 20.6901, + -0.739951, 20.6727, + -0.75575, 20.6549, + -0.77112, 20.6367, + -0.786053, 20.6182, + -0.800541, 20.5993, + -0.814576, 20.5801, + -0.828149, 20.5605, + -0.841254, 20.5406, + -0.853881, 20.5205, + -0.866025, 20.5, + -0.877679, 20.4792, + -0.888835, 20.4582, + -0.899488, 20.4369, + -0.909632, 20.4154, + -0.91926, 20.3937, + -0.928368, 20.3717, + -0.93695, 20.3495, + -0.945001, 20.3271, + -0.952517, 20.3045, + -0.959493, 20.2817, + -0.965926, 20.2588, + -0.971812, 20.2358, + -0.977147, 20.2126, + -0.981929, 20.1893, + -0.986154, 20.1658, + -0.989821, 20.1423, + -0.992928, 20.1187, + -0.995472, 20.0951, + -0.997452, 20.0713, + -0.998867, 20.0476, + -0.999717, 20.0238, + -1, 20, + -0.999717, 19.9762, + -0.998867, 19.9524, + -0.997452, 19.9287, + -0.995472, 19.9049, + -0.992928, 19.8813, + -0.989821, 19.8577, + -0.986154, 19.8342, + -0.981929, 19.8107, + -0.977147, 19.7874, + -0.971812, 19.7642, + -0.965926, 19.7412, + -0.959493, 19.7183, + -0.952517, 19.6955, + -0.945001, 19.6729, + -0.93695, 19.6505, + -0.928368, 19.6283, + -0.91926, 19.6063, + -0.909632, 19.5846, + -0.899488, 19.5631, + -0.888835, 19.5418, + -0.877679, 19.5208, + -0.866025, 19.5, + -0.853881, 19.4795, + -0.841254, 19.4594, + -0.828149, 19.4395, + -0.814576, 19.4199, + -0.800541, 19.4007, + -0.786053, 19.3818, + -0.77112, 19.3633, + -0.75575, 19.3451, + -0.739951, 19.3273, + -0.723734, 19.3099, + -0.707107, 19.2929, + -0.690079, 19.2763, + -0.67266, 19.26, + -0.654861, 19.2443, + -0.63669, 19.2289, + -0.618159, 19.2139, + -0.599278, 19.1995, + -0.580057, 19.1854, + -0.560508, 19.1719, + -0.540641, 19.1587, + -0.520468, 19.1461, + -0.5, 19.134, + -0.479249, 19.1223, + -0.458227, 19.1112, + -0.436945, 19.1005, + -0.415415, 19.0904, + -0.39365, 19.0807, + -0.371662, 19.0716, + -0.349464, 19.0631, + -0.327068, 19.055, + -0.304486, 19.0475, + -0.281733, 19.0405, + -0.258819, 19.0341, + -0.235759, 19.0282, + -0.212565, 19.0229, + -0.189251, 19.0181, + -0.16583, 19.0138, + -0.142315, 19.0102, + -0.118719, 19.0071, + -0.095056, 19.0045, + -0.0713392, 19.0025, + -0.0475819, 19.0011, + -0.0237977, 19.0003, + -1.83697e-16, 19, + 0.0237977, 19.0003, + 0.0475819, 19.0011, + 0.0713392, 19.0025, + 0.095056, 19.0045, + 0.118719, 19.0071, + 0.142315, 19.0102, + 0.16583, 19.0138, + 0.189251, 19.0181, + 0.212565, 19.0229, + 0.235759, 19.0282, + 0.258819, 19.0341, + 0.281733, 19.0405, + 0.304486, 19.0475, + 0.327068, 19.055, + 0.349464, 19.0631, + 0.371662, 19.0716, + 0.39365, 19.0807, + 0.415415, 19.0904, + 0.436945, 19.1005, + 0.458227, 19.1112, + 0.479249, 19.1223, + 0.5, 19.134, + 0.520468, 19.1461, + 0.540641, 19.1587, + 0.560508, 19.1719, + 0.580057, 19.1854, + 0.599278, 19.1995, + 0.618159, 19.2139, + 0.63669, 19.2289, + 0.654861, 19.2443, + 0.67266, 19.26, + 0.690079, 19.2763, + 0.707107, 19.2929, + 0.723734, 19.3099, + 0.739951, 19.3273, + 0.75575, 19.3451, + 0.77112, 19.3633, + 0.786053, 19.3818, + 0.800541, 19.4007, + 0.814576, 19.4199, + 0.828149, 19.4395, + 0.841254, 19.4594, + 0.853881, 19.4795, + 0.866025, 19.5, + 0.877679, 19.5208, + 0.888835, 19.5418, + 0.899488, 19.5631, + 0.909632, 19.5846, + 0.91926, 19.6063, + 0.928368, 19.6283, + 0.93695, 19.6505, + 0.945001, 19.6729, + 0.952517, 19.6955, + 0.959493, 19.7183, + 0.965926, 19.7412, + 0.971812, 19.7642, + 0.977147, 19.7874, + 0.981929, 19.8107, + 0.986154, 19.8342, + 0.989821, 19.8577, + 0.992928, 19.8813, + 0.995472, 19.9049, + 0.997452, 19.9287, + 0.998867, 19.9524, + 0.999717, 19.9762, + 1, 30, + 0.999717, 30.0238, + 0.998867, 30.0476, + 0.997452, 30.0713, + 0.995472, 30.0951, + 0.992928, 30.1187, + 0.989821, 30.1423, + 0.986154, 30.1658, + 0.981929, 30.1893, + 0.977147, 30.2126, + 0.971812, 30.2358, + 0.965926, 30.2588, + 0.959493, 30.2817, + 0.952517, 30.3045, + 0.945001, 30.3271, + 0.93695, 30.3495, + 0.928368, 30.3717, + 0.91926, 30.3937, + 0.909632, 30.4154, + 0.899488, 30.4369, + 0.888835, 30.4582, + 0.877679, 30.4792, + 0.866025, 30.5, + 0.853881, 30.5205, + 0.841254, 30.5406, + 0.828149, 30.5605, + 0.814576, 30.5801, + 0.800541, 30.5993, + 0.786053, 30.6182, + 0.77112, 30.6367, + 0.75575, 30.6549, + 0.739951, 30.6727, + 0.723734, 30.6901, + 0.707107, 30.7071, + 0.690079, 30.7237, + 0.67266, 30.74, + 0.654861, 30.7557, + 0.63669, 30.7711, + 0.618159, 30.7861, + 0.599278, 30.8005, + 0.580057, 30.8146, + 0.560508, 30.8281, + 0.540641, 30.8413, + 0.520468, 30.8539, + 0.5, 30.866, + 0.479249, 30.8777, + 0.458227, 30.8888, + 0.436945, 30.8995, + 0.415415, 30.9096, + 0.39365, 30.9193, + 0.371662, 30.9284, + 0.349464, 30.9369, + 0.327068, 30.945, + 0.304486, 30.9525, + 0.281733, 30.9595, + 0.258819, 30.9659, + 0.235759, 30.9718, + 0.212565, 30.9771, + 0.189251, 30.9819, + 0.16583, 30.9862, + 0.142315, 30.9898, + 0.118719, 30.9929, + 0.095056, 30.9955, + 0.0713392, 30.9975, + 0.0475819, 30.9989, + 0.0237977, 30.9997, + 6.12323e-17, 31, + -0.0237977, 30.9997, + -0.0475819, 30.9989, + -0.0713392, 30.9975, + -0.095056, 30.9955, + -0.118719, 30.9929, + -0.142315, 30.9898, + -0.16583, 30.9862, + -0.189251, 30.9819, + -0.212565, 30.9771, + -0.235759, 30.9718, + -0.258819, 30.9659, + -0.281733, 30.9595, + -0.304486, 30.9525, + -0.327068, 30.945, + -0.349464, 30.9369, + -0.371662, 30.9284, + -0.39365, 30.9193, + -0.415415, 30.9096, + -0.436945, 30.8995, + -0.458227, 30.8888, + -0.479249, 30.8777, + -0.5, 30.866, + -0.520468, 30.8539, + -0.540641, 30.8413, + -0.560508, 30.8281, + -0.580057, 30.8146, + -0.599278, 30.8005, + -0.618159, 30.7861, + -0.63669, 30.7711, + -0.654861, 30.7557, + -0.67266, 30.74, + -0.690079, 30.7237, + -0.707107, 30.7071, + -0.723734, 30.6901, + -0.739951, 30.6727, + -0.75575, 30.6549, + -0.77112, 30.6367, + -0.786053, 30.6182, + -0.800541, 30.5993, + -0.814576, 30.5801, + -0.828149, 30.5605, + -0.841254, 30.5406, + -0.853881, 30.5205, + -0.866025, 30.5, + -0.877679, 30.4792, + -0.888835, 30.4582, + -0.899488, 30.4369, + -0.909632, 30.4154, + -0.91926, 30.3937, + -0.928368, 30.3717, + -0.93695, 30.3495, + -0.945001, 30.3271, + -0.952517, 30.3045, + -0.959493, 30.2817, + -0.965926, 30.2588, + -0.971812, 30.2358, + -0.977147, 30.2126, + -0.981929, 30.1893, + -0.986154, 30.1658, + -0.989821, 30.1423, + -0.992928, 30.1187, + -0.995472, 30.0951, + -0.997452, 30.0713, + -0.998867, 30.0476, + -0.999717, 30.0238, + -1, 30, + -0.999717, 29.9762, + -0.998867, 29.9524, + -0.997452, 29.9287, + -0.995472, 29.9049, + -0.992928, 29.8813, + -0.989821, 29.8577, + -0.986154, 29.8342, + -0.981929, 29.8107, + -0.977147, 29.7874, + -0.971812, 29.7642, + -0.965926, 29.7412, + -0.959493, 29.7183, + -0.952517, 29.6955, + -0.945001, 29.6729, + -0.93695, 29.6505, + -0.928368, 29.6283, + -0.91926, 29.6063, + -0.909632, 29.5846, + -0.899488, 29.5631, + -0.888835, 29.5418, + -0.877679, 29.5208, + -0.866025, 29.5, + -0.853881, 29.4795, + -0.841254, 29.4594, + -0.828149, 29.4395, + -0.814576, 29.4199, + -0.800541, 29.4007, + -0.786053, 29.3818, + -0.77112, 29.3633, + -0.75575, 29.3451, + -0.739951, 29.3273, + -0.723734, 29.3099, + -0.707107, 29.2929, + -0.690079, 29.2763, + -0.67266, 29.26, + -0.654861, 29.2443, + -0.63669, 29.2289, + -0.618159, 29.2139, + -0.599278, 29.1995, + -0.580057, 29.1854, + -0.560508, 29.1719, + -0.540641, 29.1587, + -0.520468, 29.1461, + -0.5, 29.134, + -0.479249, 29.1223, + -0.458227, 29.1112, + -0.436945, 29.1005, + -0.415415, 29.0904, + -0.39365, 29.0807, + -0.371662, 29.0716, + -0.349464, 29.0631, + -0.327068, 29.055, + -0.304486, 29.0475, + -0.281733, 29.0405, + -0.258819, 29.0341, + -0.235759, 29.0282, + -0.212565, 29.0229, + -0.189251, 29.0181, + -0.16583, 29.0138, + -0.142315, 29.0102, + -0.118719, 29.0071, + -0.095056, 29.0045, + -0.0713392, 29.0025, + -0.0475819, 29.0011, + -0.0237977, 29.0003, + -1.83697e-16, 29, + 0.0237977, 29.0003, + 0.0475819, 29.0011, + 0.0713392, 29.0025, + 0.095056, 29.0045, + 0.118719, 29.0071, + 0.142315, 29.0102, + 0.16583, 29.0138, + 0.189251, 29.0181, + 0.212565, 29.0229, + 0.235759, 29.0282, + 0.258819, 29.0341, + 0.281733, 29.0405, + 0.304486, 29.0475, + 0.327068, 29.055, + 0.349464, 29.0631, + 0.371662, 29.0716, + 0.39365, 29.0807, + 0.415415, 29.0904, + 0.436945, 29.1005, + 0.458227, 29.1112, + 0.479249, 29.1223, + 0.5, 29.134, + 0.520468, 29.1461, + 0.540641, 29.1587, + 0.560508, 29.1719, + 0.580057, 29.1854, + 0.599278, 29.1995, + 0.618159, 29.2139, + 0.63669, 29.2289, + 0.654861, 29.2443, + 0.67266, 29.26, + 0.690079, 29.2763, + 0.707107, 29.2929, + 0.723734, 29.3099, + 0.739951, 29.3273, + 0.75575, 29.3451, + 0.77112, 29.3633, + 0.786053, 29.3818, + 0.800541, 29.4007, + 0.814576, 29.4199, + 0.828149, 29.4395, + 0.841254, 29.4594, + 0.853881, 29.4795, + 0.866025, 29.5, + 0.877679, 29.5208, + 0.888835, 29.5418, + 0.899488, 29.5631, + 0.909632, 29.5846, + 0.91926, 29.6063, + 0.928368, 29.6283, + 0.93695, 29.6505, + 0.945001, 29.6729, + 0.952517, 29.6955, + 0.959493, 29.7183, + 0.965926, 29.7412, + 0.971812, 29.7642, + 0.977147, 29.7874, + 0.981929, 29.8107, + 0.986154, 29.8342, + 0.989821, 29.8577, + 0.992928, 29.8813, + 0.995472, 29.9049, + 0.997452, 29.9287, + 0.998867, 29.9524, + 0.999717, 29.9762 +}; +static const unsigned some_segments_segments_count = 1056; +static const unsigned some_segments_segments[2112] = +{ + 0, 1, + 1, 2, + 2, 3, + 3, 4, + 4, 5, + 5, 6, + 6, 7, + 7, 8, + 8, 9, + 9, 10, + 10, 11, + 11, 12, + 12, 13, + 13, 14, + 14, 15, + 15, 16, + 16, 17, + 17, 18, + 18, 19, + 19, 20, + 20, 21, + 21, 22, + 22, 23, + 23, 24, + 24, 25, + 25, 26, + 26, 27, + 27, 28, + 28, 29, + 29, 30, + 30, 31, + 31, 32, + 32, 33, + 33, 34, + 34, 35, + 35, 36, + 36, 37, + 37, 38, + 38, 39, + 39, 40, + 40, 41, + 41, 42, + 42, 43, + 43, 44, + 44, 45, + 45, 46, + 46, 47, + 47, 48, + 48, 49, + 49, 50, + 50, 51, + 51, 52, + 52, 53, + 53, 54, + 54, 55, + 55, 56, + 56, 57, + 57, 58, + 58, 59, + 59, 60, + 60, 61, + 61, 62, + 62, 63, + 63, 64, + 64, 65, + 65, 66, + 66, 67, + 67, 68, + 68, 69, + 69, 70, + 70, 71, + 71, 72, + 72, 73, + 73, 74, + 74, 75, + 75, 76, + 76, 77, + 77, 78, + 78, 79, + 79, 80, + 80, 81, + 81, 82, + 82, 83, + 83, 84, + 84, 85, + 85, 86, + 86, 87, + 87, 88, + 88, 89, + 89, 90, + 90, 91, + 91, 92, + 92, 93, + 93, 94, + 94, 95, + 95, 96, + 96, 97, + 97, 98, + 98, 99, + 99, 100, + 100, 101, + 101, 102, + 102, 103, + 103, 104, + 104, 105, + 105, 106, + 106, 107, + 107, 108, + 108, 109, + 109, 110, + 110, 111, + 111, 112, + 112, 113, + 113, 114, + 114, 115, + 115, 116, + 116, 117, + 117, 118, + 118, 119, + 119, 120, + 120, 121, + 121, 122, + 122, 123, + 123, 124, + 124, 125, + 125, 126, + 126, 127, + 127, 128, + 128, 129, + 129, 130, + 130, 131, + 131, 132, + 132, 133, + 133, 134, + 134, 135, + 135, 136, + 136, 137, + 137, 138, + 138, 139, + 139, 140, + 140, 141, + 141, 142, + 142, 143, + 143, 144, + 144, 145, + 145, 146, + 146, 147, + 147, 148, + 148, 149, + 149, 150, + 150, 151, + 151, 152, + 152, 153, + 153, 154, + 154, 155, + 155, 156, + 156, 157, + 157, 158, + 158, 159, + 159, 160, + 160, 161, + 161, 162, + 162, 163, + 163, 164, + 164, 165, + 165, 166, + 166, 167, + 167, 168, + 168, 169, + 169, 170, + 170, 171, + 171, 172, + 172, 173, + 173, 174, + 174, 175, + 175, 176, + 176, 177, + 177, 178, + 178, 179, + 179, 180, + 180, 181, + 181, 182, + 182, 183, + 183, 184, + 184, 185, + 185, 186, + 186, 187, + 187, 188, + 188, 189, + 189, 190, + 190, 191, + 191, 192, + 192, 193, + 193, 194, + 194, 195, + 195, 196, + 196, 197, + 197, 198, + 198, 199, + 199, 200, + 200, 201, + 201, 202, + 202, 203, + 203, 204, + 204, 205, + 205, 206, + 206, 207, + 207, 208, + 208, 209, + 209, 210, + 210, 211, + 211, 212, + 212, 213, + 213, 214, + 214, 215, + 215, 216, + 216, 217, + 217, 218, + 218, 219, + 219, 220, + 220, 221, + 221, 222, + 222, 223, + 223, 224, + 224, 225, + 225, 226, + 226, 227, + 227, 228, + 228, 229, + 229, 230, + 230, 231, + 231, 232, + 232, 233, + 233, 234, + 234, 235, + 235, 236, + 236, 237, + 237, 238, + 238, 239, + 239, 240, + 240, 241, + 241, 242, + 242, 243, + 243, 244, + 244, 245, + 245, 246, + 246, 247, + 247, 248, + 248, 249, + 249, 250, + 250, 251, + 251, 252, + 252, 253, + 253, 254, + 254, 255, + 255, 256, + 256, 257, + 257, 258, + 258, 259, + 259, 260, + 260, 261, + 261, 262, + 262, 263, + 263, 0, + 264, 265, + 265, 266, + 266, 267, + 267, 268, + 268, 269, + 269, 270, + 270, 271, + 271, 272, + 272, 273, + 273, 274, + 274, 275, + 275, 276, + 276, 277, + 277, 278, + 278, 279, + 279, 280, + 280, 281, + 281, 282, + 282, 283, + 283, 284, + 284, 285, + 285, 286, + 286, 287, + 287, 288, + 288, 289, + 289, 290, + 290, 291, + 291, 292, + 292, 293, + 293, 294, + 294, 295, + 295, 296, + 296, 297, + 297, 298, + 298, 299, + 299, 300, + 300, 301, + 301, 302, + 302, 303, + 303, 304, + 304, 305, + 305, 306, + 306, 307, + 307, 308, + 308, 309, + 309, 310, + 310, 311, + 311, 312, + 312, 313, + 313, 314, + 314, 315, + 315, 316, + 316, 317, + 317, 318, + 318, 319, + 319, 320, + 320, 321, + 321, 322, + 322, 323, + 323, 324, + 324, 325, + 325, 326, + 326, 327, + 327, 328, + 328, 329, + 329, 330, + 330, 331, + 331, 332, + 332, 333, + 333, 334, + 334, 335, + 335, 336, + 336, 337, + 337, 338, + 338, 339, + 339, 340, + 340, 341, + 341, 342, + 342, 343, + 343, 344, + 344, 345, + 345, 346, + 346, 347, + 347, 348, + 348, 349, + 349, 350, + 350, 351, + 351, 352, + 352, 353, + 353, 354, + 354, 355, + 355, 356, + 356, 357, + 357, 358, + 358, 359, + 359, 360, + 360, 361, + 361, 362, + 362, 363, + 363, 364, + 364, 365, + 365, 366, + 366, 367, + 367, 368, + 368, 369, + 369, 370, + 370, 371, + 371, 372, + 372, 373, + 373, 374, + 374, 375, + 375, 376, + 376, 377, + 377, 378, + 378, 379, + 379, 380, + 380, 381, + 381, 382, + 382, 383, + 383, 384, + 384, 385, + 385, 386, + 386, 387, + 387, 388, + 388, 389, + 389, 390, + 390, 391, + 391, 392, + 392, 393, + 393, 394, + 394, 395, + 395, 396, + 396, 397, + 397, 398, + 398, 399, + 399, 400, + 400, 401, + 401, 402, + 402, 403, + 403, 404, + 404, 405, + 405, 406, + 406, 407, + 407, 408, + 408, 409, + 409, 410, + 410, 411, + 411, 412, + 412, 413, + 413, 414, + 414, 415, + 415, 416, + 416, 417, + 417, 418, + 418, 419, + 419, 420, + 420, 421, + 421, 422, + 422, 423, + 423, 424, + 424, 425, + 425, 426, + 426, 427, + 427, 428, + 428, 429, + 429, 430, + 430, 431, + 431, 432, + 432, 433, + 433, 434, + 434, 435, + 435, 436, + 436, 437, + 437, 438, + 438, 439, + 439, 440, + 440, 441, + 441, 442, + 442, 443, + 443, 444, + 444, 445, + 445, 446, + 446, 447, + 447, 448, + 448, 449, + 449, 450, + 450, 451, + 451, 452, + 452, 453, + 453, 454, + 454, 455, + 455, 456, + 456, 457, + 457, 458, + 458, 459, + 459, 460, + 460, 461, + 461, 462, + 462, 463, + 463, 464, + 464, 465, + 465, 466, + 466, 467, + 467, 468, + 468, 469, + 469, 470, + 470, 471, + 471, 472, + 472, 473, + 473, 474, + 474, 475, + 475, 476, + 476, 477, + 477, 478, + 478, 479, + 479, 480, + 480, 481, + 481, 482, + 482, 483, + 483, 484, + 484, 485, + 485, 486, + 486, 487, + 487, 488, + 488, 489, + 489, 490, + 490, 491, + 491, 492, + 492, 493, + 493, 494, + 494, 495, + 495, 496, + 496, 497, + 497, 498, + 498, 499, + 499, 500, + 500, 501, + 501, 502, + 502, 503, + 503, 504, + 504, 505, + 505, 506, + 506, 507, + 507, 508, + 508, 509, + 509, 510, + 510, 511, + 511, 512, + 512, 513, + 513, 514, + 514, 515, + 515, 516, + 516, 517, + 517, 518, + 518, 519, + 519, 520, + 520, 521, + 521, 522, + 522, 523, + 523, 524, + 524, 525, + 525, 526, + 526, 527, + 527, 264, + 528, 529, + 529, 530, + 530, 531, + 531, 532, + 532, 533, + 533, 534, + 534, 535, + 535, 536, + 536, 537, + 537, 538, + 538, 539, + 539, 540, + 540, 541, + 541, 542, + 542, 543, + 543, 544, + 544, 545, + 545, 546, + 546, 547, + 547, 548, + 548, 549, + 549, 550, + 550, 551, + 551, 552, + 552, 553, + 553, 554, + 554, 555, + 555, 556, + 556, 557, + 557, 558, + 558, 559, + 559, 560, + 560, 561, + 561, 562, + 562, 563, + 563, 564, + 564, 565, + 565, 566, + 566, 567, + 567, 568, + 568, 569, + 569, 570, + 570, 571, + 571, 572, + 572, 573, + 573, 574, + 574, 575, + 575, 576, + 576, 577, + 577, 578, + 578, 579, + 579, 580, + 580, 581, + 581, 582, + 582, 583, + 583, 584, + 584, 585, + 585, 586, + 586, 587, + 587, 588, + 588, 589, + 589, 590, + 590, 591, + 591, 592, + 592, 593, + 593, 594, + 594, 595, + 595, 596, + 596, 597, + 597, 598, + 598, 599, + 599, 600, + 600, 601, + 601, 602, + 602, 603, + 603, 604, + 604, 605, + 605, 606, + 606, 607, + 607, 608, + 608, 609, + 609, 610, + 610, 611, + 611, 612, + 612, 613, + 613, 614, + 614, 615, + 615, 616, + 616, 617, + 617, 618, + 618, 619, + 619, 620, + 620, 621, + 621, 622, + 622, 623, + 623, 624, + 624, 625, + 625, 626, + 626, 627, + 627, 628, + 628, 629, + 629, 630, + 630, 631, + 631, 632, + 632, 633, + 633, 634, + 634, 635, + 635, 636, + 636, 637, + 637, 638, + 638, 639, + 639, 640, + 640, 641, + 641, 642, + 642, 643, + 643, 644, + 644, 645, + 645, 646, + 646, 647, + 647, 648, + 648, 649, + 649, 650, + 650, 651, + 651, 652, + 652, 653, + 653, 654, + 654, 655, + 655, 656, + 656, 657, + 657, 658, + 658, 659, + 659, 660, + 660, 661, + 661, 662, + 662, 663, + 663, 664, + 664, 665, + 665, 666, + 666, 667, + 667, 668, + 668, 669, + 669, 670, + 670, 671, + 671, 672, + 672, 673, + 673, 674, + 674, 675, + 675, 676, + 676, 677, + 677, 678, + 678, 679, + 679, 680, + 680, 681, + 681, 682, + 682, 683, + 683, 684, + 684, 685, + 685, 686, + 686, 687, + 687, 688, + 688, 689, + 689, 690, + 690, 691, + 691, 692, + 692, 693, + 693, 694, + 694, 695, + 695, 696, + 696, 697, + 697, 698, + 698, 699, + 699, 700, + 700, 701, + 701, 702, + 702, 703, + 703, 704, + 704, 705, + 705, 706, + 706, 707, + 707, 708, + 708, 709, + 709, 710, + 710, 711, + 711, 712, + 712, 713, + 713, 714, + 714, 715, + 715, 716, + 716, 717, + 717, 718, + 718, 719, + 719, 720, + 720, 721, + 721, 722, + 722, 723, + 723, 724, + 724, 725, + 725, 726, + 726, 727, + 727, 728, + 728, 729, + 729, 730, + 730, 731, + 731, 732, + 732, 733, + 733, 734, + 734, 735, + 735, 736, + 736, 737, + 737, 738, + 738, 739, + 739, 740, + 740, 741, + 741, 742, + 742, 743, + 743, 744, + 744, 745, + 745, 746, + 746, 747, + 747, 748, + 748, 749, + 749, 750, + 750, 751, + 751, 752, + 752, 753, + 753, 754, + 754, 755, + 755, 756, + 756, 757, + 757, 758, + 758, 759, + 759, 760, + 760, 761, + 761, 762, + 762, 763, + 763, 764, + 764, 765, + 765, 766, + 766, 767, + 767, 768, + 768, 769, + 769, 770, + 770, 771, + 771, 772, + 772, 773, + 773, 774, + 774, 775, + 775, 776, + 776, 777, + 777, 778, + 778, 779, + 779, 780, + 780, 781, + 781, 782, + 782, 783, + 783, 784, + 784, 785, + 785, 786, + 786, 787, + 787, 788, + 788, 789, + 789, 790, + 790, 791, + 791, 528, + 792, 793, + 793, 794, + 794, 795, + 795, 796, + 796, 797, + 797, 798, + 798, 799, + 799, 800, + 800, 801, + 801, 802, + 802, 803, + 803, 804, + 804, 805, + 805, 806, + 806, 807, + 807, 808, + 808, 809, + 809, 810, + 810, 811, + 811, 812, + 812, 813, + 813, 814, + 814, 815, + 815, 816, + 816, 817, + 817, 818, + 818, 819, + 819, 820, + 820, 821, + 821, 822, + 822, 823, + 823, 824, + 824, 825, + 825, 826, + 826, 827, + 827, 828, + 828, 829, + 829, 830, + 830, 831, + 831, 832, + 832, 833, + 833, 834, + 834, 835, + 835, 836, + 836, 837, + 837, 838, + 838, 839, + 839, 840, + 840, 841, + 841, 842, + 842, 843, + 843, 844, + 844, 845, + 845, 846, + 846, 847, + 847, 848, + 848, 849, + 849, 850, + 850, 851, + 851, 852, + 852, 853, + 853, 854, + 854, 855, + 855, 856, + 856, 857, + 857, 858, + 858, 859, + 859, 860, + 860, 861, + 861, 862, + 862, 863, + 863, 864, + 864, 865, + 865, 866, + 866, 867, + 867, 868, + 868, 869, + 869, 870, + 870, 871, + 871, 872, + 872, 873, + 873, 874, + 874, 875, + 875, 876, + 876, 877, + 877, 878, + 878, 879, + 879, 880, + 880, 881, + 881, 882, + 882, 883, + 883, 884, + 884, 885, + 885, 886, + 886, 887, + 887, 888, + 888, 889, + 889, 890, + 890, 891, + 891, 892, + 892, 893, + 893, 894, + 894, 895, + 895, 896, + 896, 897, + 897, 898, + 898, 899, + 899, 900, + 900, 901, + 901, 902, + 902, 903, + 903, 904, + 904, 905, + 905, 906, + 906, 907, + 907, 908, + 908, 909, + 909, 910, + 910, 911, + 911, 912, + 912, 913, + 913, 914, + 914, 915, + 915, 916, + 916, 917, + 917, 918, + 918, 919, + 919, 920, + 920, 921, + 921, 922, + 922, 923, + 923, 924, + 924, 925, + 925, 926, + 926, 927, + 927, 928, + 928, 929, + 929, 930, + 930, 931, + 931, 932, + 932, 933, + 933, 934, + 934, 935, + 935, 936, + 936, 937, + 937, 938, + 938, 939, + 939, 940, + 940, 941, + 941, 942, + 942, 943, + 943, 944, + 944, 945, + 945, 946, + 946, 947, + 947, 948, + 948, 949, + 949, 950, + 950, 951, + 951, 952, + 952, 953, + 953, 954, + 954, 955, + 955, 956, + 956, 957, + 957, 958, + 958, 959, + 959, 960, + 960, 961, + 961, 962, + 962, 963, + 963, 964, + 964, 965, + 965, 966, + 966, 967, + 967, 968, + 968, 969, + 969, 970, + 970, 971, + 971, 972, + 972, 973, + 973, 974, + 974, 975, + 975, 976, + 976, 977, + 977, 978, + 978, 979, + 979, 980, + 980, 981, + 981, 982, + 982, 983, + 983, 984, + 984, 985, + 985, 986, + 986, 987, + 987, 988, + 988, 989, + 989, 990, + 990, 991, + 991, 992, + 992, 993, + 993, 994, + 994, 995, + 995, 996, + 996, 997, + 997, 998, + 998, 999, + 999, 1000, + 1000, 1001, + 1001, 1002, + 1002, 1003, + 1003, 1004, + 1004, 1005, + 1005, 1006, + 1006, 1007, + 1007, 1008, + 1008, 1009, + 1009, 1010, + 1010, 1011, + 1011, 1012, + 1012, 1013, + 1013, 1014, + 1014, 1015, + 1015, 1016, + 1016, 1017, + 1017, 1018, + 1018, 1019, + 1019, 1020, + 1020, 1021, + 1021, 1022, + 1022, 1023, + 1023, 1024, + 1024, 1025, + 1025, 1026, + 1026, 1027, + 1027, 1028, + 1028, 1029, + 1029, 1030, + 1030, 1031, + 1031, 1032, + 1032, 1033, + 1033, 1034, + 1034, 1035, + 1035, 1036, + 1036, 1037, + 1037, 1038, + 1038, 1039, + 1039, 1040, + 1040, 1041, + 1041, 1042, + 1042, 1043, + 1043, 1044, + 1044, 1045, + 1045, 1046, + 1046, 1047, + 1047, 1048, + 1048, 1049, + 1049, 1050, + 1050, 1051, + 1051, 1052, + 1052, 1053, + 1053, 1054, + 1054, 1055, + 1055, 792 +}; +static const unsigned some_segments_properties[3168] = +{ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0 +}; + +#define NB_CIRC 4 +#define CIRC_VRTX_COUNT 264u +#define CIRC_SEG_COUNT 264u + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc2d_device* dev = NULL; + struct senc2d_scene* scn = NULL; + struct context ctx = CONTEXT_NULL__; + unsigned e, count; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); + + /* Create a scene */ + ctx.positions = some_segments_vertices; + ctx.indices = some_segments_segments; + ctx.properties = some_segments_properties; + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + some_segments_segments_count, get_indices, get_media_from_properties, + some_segments_vertices_count, get_position, &ctx, &scn)); + + OK(senc2d_scene_get_vertices_count(scn, &count)); + CHK(count == some_segments_vertices_count); + CHK(count == NB_CIRC * CIRC_VRTX_COUNT); + OK(senc2d_scene_get_segments_count(scn, &count)); + CHK(count == some_segments_segments_count); + CHK(count == NB_CIRC * CIRC_VRTX_COUNT); + + OK(senc2d_scene_get_enclosure_count(scn, &count)); + CHK(count == 1 + NB_CIRC); + FOR_EACH(e, 0, count) { + struct senc2d_enclosure* enclosure; + struct senc2d_enclosure_header header; + OK(senc2d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); + CHK(header.primitives_count == + (e ? CIRC_SEG_COUNT : NB_CIRC * CIRC_SEG_COUNT)); + OK(senc2d_enclosure_ref_put(enclosure)); + } + + OK(senc2d_scene_ref_put(scn)); + OK(senc2d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_senc2d_square_behind_square.c b/src/test_senc2d_square_behind_square.c @@ -13,105 +13,198 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/* This test has been created using the sg2_geometry_dump_as_C_code feature + * of star-geometry-2D. It uses output from test_sg2_square_behind_square. */ + #include "senc2d.h" #include "test_senc2d_utils.h" #include <rsys/double2.h> +/* + cube_2 cube_3 + + +-----------------------+ + | 3 + | | + m1 | m0 | + | | + | | + | | + | |--> N + | | + | | + +-----------------------+ + +------------+ +------------+ + | 2 | 2 + m0 | m1 | m0 | m1 | + | | | | + | |--> N | |--> N + | | | | + +------------+ +------------+ + +-----+ +-----+ + m0 | m1 1 m0 | m1 1 + | |--> N | |--> N + +-----+ +-----+ + */ + +/* Dump of star-geometry-2D 'square_behind_square_2'. */ +static const unsigned square_behind_square_2_vertices_count = 8; +static const double square_behind_square_2_vertices[16] = +{ + 0.1, 0, + 1, 0, + 0, 1.1, + 1, 1, + -0.2, 2, + 2.5, 2, + -0.5, 5.3, + 2.5, 5 +}; +static const unsigned square_behind_square_2_segments_count = 8; +static const unsigned square_behind_square_2_segments[16] = +{ + 0, 2, + 2, 3, + 3, 1, + 1, 0, + 4, 6, + 6, 7, + 7, 5, + 5, 4 +}; +static const unsigned square_behind_square_2_properties[24] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 +}; +/* Dump of star-geometry-2D 'square_behind_square_3'. */ +static const unsigned square_behind_square_3_vertices_count = 12; +static const double square_behind_square_3_vertices[24] = +{ + 0.1, 0, + 1, 0, + 0, 1.1, + 1, 1, + -0.2, 2, + 2.5, 2, + -0.5, 5.3, + 2.5, 5, + -0.5, 6, + 4, 6, + -1, 11.5, + 4, 11 +}; +static const unsigned square_behind_square_3_segments_count = 12; +static const unsigned square_behind_square_3_segments[24] = +{ + 0, 2, + 2, 3, + 3, 1, + 1, 0, + 4, 6, + 6, 7, + 7, 5, + 5, 4, + 8, 10, + 10, 11, + 11, 9, + 9, 8 +}; +static const unsigned square_behind_square_3_properties[36] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0 +}; + int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc2d_descriptor* desc = NULL; struct senc2d_device* dev = NULL; struct senc2d_scene* scn = NULL; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned i, ecount, maxm; (void)argc, (void)argv; - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - CHK(senc2d_device_create - (NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev) == RES_OK); - - /* Create the scene */ - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - - ctx.positions = box_vertices; - ctx.indices = box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - d2(ctx.offset, 0, 0); - ctx.front_media = medium0; - ctx.back_media = medium1; - - /* First square */ - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - /* +Y from the first square, - * big enough to prevent rays from the first square to miss this one */ - d2(ctx.offset, -2, 20); - ctx.scale = 5; - - /* Second square */ - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); + + /* Create a scene with the first and second squares. + * Both squares have medium 1 inside and medium 0 outside, + * the second square is +Y from the first square and is big enough + * to prevent rays from the first square to miss it. */ + ctx.positions = square_behind_square_2_vertices; + ctx.indices = square_behind_square_2_segments; + ctx.properties = square_behind_square_2_properties; + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + square_behind_square_2_segments_count, get_indices, + get_media_from_properties, square_behind_square_2_vertices_count, + get_position, &ctx, &scn)); - CHK(senc2d_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); + OK(senc2d_scene_get_enclosure_count(scn, &ecount)); CHK(ecount == 3); FOR_EACH(i, 0, ecount) { struct senc2d_enclosure* enclosure; struct senc2d_enclosure_header header; - CHK(senc2d_descriptor_get_enclosure(desc, i, &enclosure) == RES_OK); - CHK(senc2d_enclosure_get_header(enclosure, &header) == RES_OK); + OK(senc2d_scene_get_enclosure(scn, i, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); ASSERT(header.enclosed_media_count == 1); - CHK(senc2d_enclosure_ref_put(enclosure) == RES_OK); + OK(senc2d_enclosure_ref_put(enclosure)); } - CHK(senc2d_descriptor_get_max_medium(desc, &maxm) == RES_OK); + OK(senc2d_scene_get_max_medium(scn, &maxm)); CHK(maxm == 1); - check_desc(desc); - - /* Even further in +Y, even bigger */ - d2(ctx.offset, -3, 30); - ctx.scale = 7; - /* Front/back media have been exchanged: external enclosure shows 2 media */ - ctx.front_media = medium1; - ctx.back_media = medium0; - - /* Third square */ - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - if(desc) CHK(senc2d_descriptor_ref_put(desc) == RES_OK); - desc = NULL; - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); - - CHK(senc2d_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); + OK(senc2d_scene_ref_put(scn)); + + /* Create a scene with the 3 squares, same 2 first squares as above + * The third square has medium 0 inside and medium 1 outside and is further + * in +Y and bigger */ + ctx.positions = square_behind_square_3_vertices; + ctx.indices = square_behind_square_3_segments; + ctx.properties = square_behind_square_3_properties; + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + square_behind_square_3_segments_count, get_indices, + get_media_from_properties, square_behind_square_3_vertices_count, + get_position, &ctx, &scn)); + + OK(senc2d_scene_get_enclosure_count(scn, &ecount)); CHK(ecount == 4); FOR_EACH(i, 0, ecount) { struct senc2d_enclosure* enclosure; struct senc2d_enclosure_header header; - CHK(senc2d_descriptor_get_enclosure(desc, i, &enclosure) == RES_OK); - CHK(senc2d_enclosure_get_header(enclosure, &header) == RES_OK); + OK(senc2d_scene_get_enclosure(scn, i, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); + /* Inside enclosures contain 1 single media */ ASSERT(header.enclosed_media_count == (header.is_infinite ? 2u : 1u)); - CHK(senc2d_enclosure_ref_put(enclosure) == RES_OK); + OK(senc2d_enclosure_ref_put(enclosure)); } - CHK(senc2d_descriptor_get_max_medium(desc, &maxm) == RES_OK); + OK(senc2d_scene_get_max_medium(scn, &maxm)); CHK(maxm == 1); - check_desc(desc); - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); - if(desc) CHK(senc2d_descriptor_ref_put(desc) == RES_OK); + OK(senc2d_scene_ref_put(scn)); + OK(senc2d_device_ref_put(dev)); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); diff --git a/src/test_senc2d_square_in_square.c b/src/test_senc2d_square_in_square.c @@ -13,102 +13,198 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/* This test has been created using the sg2_geometry_dump_as_C_code feature + * of star-geometry-2D. It uses output from test_sg2_square_in_square. */ + #include "senc2d.h" #include "test_senc2d_utils.h" #include <rsys/double2.h> +/* + square_2 square_3 + + +-------------------------+ + | B + +-------------+ | +-------------+ | + m1 | m0 M m1 | m1 | m0 M | + | +------+ | | m0 | +------+ | | + | | m1 S | | | | m1 S | | + | | N <--| | | | | N <--| | | + | +------+ | | | +------+ | | + | N <--| | | N <--| | + +-------------+ | +-------------+ | + | N <--| + +-------------------------+ + */ + +/* Dump of star-geometry-2D 'square_in_square_2'. */ +static const unsigned square_in_square_2_vertices_count = 8; +static const double square_in_square_2_vertices[16] = +{ + 0.1, 0, + 1, 0, + 0, 1.1, + 1, 1, + -0.7, -1, + 2, -1, + -1, 2.3, + 2, 2 +}; +static const unsigned square_in_square_2_segments_count = 8; +static const unsigned square_in_square_2_segments[16] = +{ + 0, 2, + 2, 3, + 3, 1, + 1, 0, + 6, 4, + 7, 6, + 5, 7, + 4, 5 +}; +static const unsigned square_in_square_2_properties[24] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 +}; +/* Dump of star-geometry-2D 'square_in_square_3'. */ +static const unsigned square_in_square_3_vertices_count = 12; +static const double square_in_square_3_vertices[24] = +{ + 0.1, 0, + 1, 0, + 0, 1.1, + 1, 1, + -0.7, -1, + 2, -1, + -1, 2.3, + 2, 2, + -3, -4, + 6, -4, + -4, 7, + 6, 6 +}; +static const unsigned square_in_square_3_segments_count = 12; +static const unsigned square_in_square_3_segments[24] = +{ + 0, 2, + 2, 3, + 3, 1, + 1, 0, + 6, 4, + 7, 6, + 5, 7, + 4, 5, + 10, 8, + 11, 10, + 9, 11, + 8, 9 +}; +static const unsigned square_in_square_3_properties[36] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 +}; + int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc2d_descriptor* desc = NULL; struct senc2d_device* dev = NULL; struct senc2d_scene* scn = NULL; - struct context ctx; - unsigned i, ecount, maxm; + struct context ctx = CONTEXT_NULL__; + unsigned e, ecount, maxm, e2; (void)argc, (void)argv; - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - CHK(senc2d_device_create - (NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev) == RES_OK); - - /* Create the scene */ - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - - ctx.positions = box_vertices; - ctx.indices = box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - d2(ctx.offset, 0, 0); - /* Smallest square exterior is medium 0 */ - ctx.front_media = medium0; - /* Smallest square interior is medium 1 */ - ctx.back_media = medium1; - - /* First square */ - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - d2(ctx.offset, -1, -1); - ctx.scale = 3; - /* Bigger square exterior is medium 1 */ - /* Bigger square interior is medium 0 */ - ctx.reverse_vrtx = 1; - - /* Second square */ - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); - - CHK(senc2d_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); + + /* Create a scene with the first and second squares. + * The enclosure in the small contains medium 1, the external enclosure + * contains medium 1, the enclosure between the small and medium squares + * contains medium 0. */ + ctx.positions = square_in_square_2_vertices; + ctx.indices = square_in_square_2_segments; + ctx.properties = square_in_square_2_properties; + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + square_in_square_2_segments_count, get_indices, get_media_from_properties, + square_in_square_2_vertices_count, get_position, &ctx, &scn)); + + OK(senc2d_scene_get_enclosure_count(scn, &ecount)); CHK(ecount == 3); - FOR_EACH(i, 0, ecount) { + FOR_EACH(e, 0, ecount) { struct senc2d_enclosure* enclosure; struct senc2d_enclosure_header header; - CHK(senc2d_descriptor_get_enclosure(desc, i, &enclosure) == RES_OK); - CHK(senc2d_enclosure_get_header(enclosure, &header) == RES_OK); + unsigned m; + OK(senc2d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); ASSERT(header.enclosed_media_count == 1); - CHK(senc2d_enclosure_ref_put(enclosure) == RES_OK); + OK(senc2d_enclosure_get_medium(enclosure, 0, &m)); + ASSERT(m <= 1); + ASSERT((m == 0) == (header.primitives_count == square_in_square_2_segments_count)); + OK(senc2d_enclosure_ref_put(enclosure)); } - CHK(senc2d_descriptor_get_max_medium(desc, &maxm) == RES_OK); + OK(senc2d_scene_get_max_medium(scn, &maxm)); CHK(maxm == 1); - check_desc(desc); - - d2(ctx.offset, -4, -4); - ctx.scale = 10; - ctx.reverse_vrtx = 1; - ctx.reverse_med = 1; - /* Biggest square exterior is medium 1 */ - ctx.front_media = medium1; - /* Biggest square interior is medium 0 - * interior/exterior media have been exchanged: external enclosure shows 2 media */ - ctx.back_media = medium0; - - /* Third square */ - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - if(desc) CHK(senc2d_descriptor_ref_put(desc) == RES_OK); - desc = NULL; - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); - - CHK(senc2d_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); + OK(senc2d_scene_ref_put(scn)); + + /* Create a scene with the 3 squares, same 2 first squares as above. + * The enclosure in the small square contains medium 1, the external enclosure + * contains medium 1, the enclosure between the small and medium squares + * contains medium 0 and the enclosure between the medium and big squares + * contains both media 0 and 1. */ + ctx.positions = square_in_square_3_vertices; + ctx.indices = square_in_square_3_segments; + ctx.properties = square_in_square_3_properties; + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + square_in_square_3_segments_count, get_indices, get_media_from_properties, + square_in_square_3_vertices_count, get_position, &ctx, &scn)); + + OK(senc2d_scene_get_enclosure_count(scn, &ecount)); CHK(ecount == 4); - CHK(senc2d_descriptor_get_max_medium(desc, &maxm) == RES_OK); + e2 = ecount; + FOR_EACH(e, 0, ecount) { + struct senc2d_enclosure* enclosure; + struct senc2d_enclosure_header header; + OK(senc2d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); + ASSERT(header.enclosed_media_count <= 2); + if(header.enclosed_media_count == 2) { + /* A single internal enclosure has 2 media */ + ASSERT(!header.is_infinite); + ASSERT(e2 == ecount); (void)e2; + e2 = e; + } + OK(senc2d_enclosure_ref_put(enclosure)); + } + + OK(senc2d_scene_get_max_medium(scn, &maxm)); CHK(maxm == 1); - check_desc(desc); - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); - if(desc) CHK(senc2d_descriptor_ref_put(desc) == RES_OK); + OK(senc2d_scene_ref_put(scn)); + OK(senc2d_device_ref_put(dev)); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); diff --git a/src/test_senc2d_square_on_square.c b/src/test_senc2d_square_on_square.c @@ -13,6 +13,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/* This test has been created using the sg2_geometry_dump_as_C_code feature + * of star-geometry-2D. It uses output from test_sg2_square_on_square. */ + #define _POSIX_C_SOURCE 200112L /* snprintf */ #include "senc2d.h" @@ -22,108 +25,122 @@ #include <stdio.h> -/* - Y - ^ -4 | +-----------------------+ - | | 3 -3 | | +-----+ | - | m2 | m1 | m0 2 | - | | | | | -2 | | +-----+ | - | | | m0 1 | - | | | | | -1 | | +-----+ | - | | | -0 - +-----------------------+ - - |--------------------------> X - 0 1 2 3 4 -*/ +/* + +-----------------------+ + | 3 + | +------+ | + m2 | m1 | m0 2 | + | | |--> N | + | +------+ | + | | m0 1 | + | | |--> N | + | +------+ | + |--> N | + +-----------------------+ + */ + +/* Dump of star-geometry-2D 'square_on_square'. */ +static const unsigned square_on_square_vertices_count = 10; +static const double square_on_square_vertices[20] = +{ + 1, 1, + 2, 1, + 1, 2, + 2, 2, + 1, 3, + 2, 3, + 0.4, 0, + 4, 0, + 0, 4.4, + 4, 4 +}; +static const unsigned square_on_square_segments_count = 11; +static const unsigned square_on_square_segments[22] = +{ + 0, 2, + 2, 3, + 3, 1, + 1, 0, + 2, 4, + 4, 5, + 5, 3, + 8, 6, + 9, 8, + 7, 9, + 6, 7 +}; +static const unsigned square_on_square_properties[33] = +{ + 1, 0, 0, + 0, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0 +}; int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc2d_descriptor* desc = NULL; struct senc2d_device* dev = NULL; struct senc2d_scene* scn = NULL; - struct context ctx; - unsigned count, i; + struct context ctx = CONTEXT_NULL__; + unsigned count, e; (void)argc, (void)argv; - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - CHK(senc2d_device_create - (NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev) == RES_OK); - - /* Create the scene */ - CHK(senc2d_scene_create(dev, - SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) - == RES_OK); - - ctx.positions = square_vertices; /* Need true squares for squares #1 and #2 */ - ctx.indices = box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - d2(ctx.offset, 1, 1); - /* Small square #1 exterior is medium 1, - * except for the top face where it is 0 */ - ctx.front_media = medium1_front0; - /* Smallest square interior is medium 0 */ - ctx.back_media = medium0; - - /* Add square #1 */ - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - d2(ctx.offset, 1, 2); - ctx.scale = 1; - /* Small square #2 exterior is medium 1, - * except for the bottom face where it is 0 */ - ctx.front_media = medium1_back0; - /* Smallest square interior is medium 0 */ - ctx.back_media = medium0; - - /* Add square #2 (has a duplicate face with square #1) */ - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - ctx.positions = box_vertices; /* Can use distorded square for square #3 */ - d2(ctx.offset, 0, 0); - ctx.scale = 4; - ctx.reverse_vrtx = 1; - ctx.reverse_med = 1; - /* Big square #3 exterior is medium 2 */ - ctx.front_media = medium2; - /* Big square #3 interior is medium 1 */ - ctx.back_media = medium1; - - /* Add square #3 */ - CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx) == RES_OK); - - CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); - - CHK(senc2d_descriptor_get_enclosure_count(desc, &count) == RES_OK); + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); + + /* Create a scene with the squares. + * The enclosures in the small squares contain medium 0, the external enclosure + * contains medium 2, the enclosure between the small and big squares + * contains medium 1. */ + ctx.positions = square_on_square_vertices; + ctx.indices = square_on_square_segments; + ctx.properties = square_on_square_properties; + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + square_on_square_segments_count, get_indices, get_media_from_properties, + square_on_square_vertices_count, get_position, &ctx, &scn)); + + OK(senc2d_scene_get_enclosure_count(scn, &count)); CHK(count == 4); - CHK(senc2d_descriptor_get_global_vertices_count(desc, &count) == RES_OK); - CHK(count == 10); + OK(senc2d_scene_get_vertices_count(scn, &count)); + CHK(count == square_on_square_vertices_count); - CHK(senc2d_descriptor_get_global_segments_count(desc, &count) == RES_OK); - CHK(count == 11); + OK(senc2d_scene_get_segments_count(scn, &count)); + CHK(count == square_on_square_segments_count); - CHK(senc2d_descriptor_get_enclosure_count(desc, &count) == RES_OK); - FOR_EACH(i, 0, count) { - char name[128]; - snprintf(name, sizeof(name), "test2d_square_on_square_%u.obj", i); - dump_enclosure(desc, i, name); + OK(senc2d_scene_get_enclosure_count(scn, &count)); + CHK(count == 4); + FOR_EACH(e, 0, count) { + struct senc2d_enclosure* enclosure; + struct senc2d_enclosure_header header; + unsigned m; + char name[128]; (void)name; + OK(senc2d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); + CHK(header.enclosed_media_count == 1); + OK(senc2d_enclosure_get_medium(enclosure, 0, &m)); + if(header.is_infinite) ASSERT(m == 2); /* External */ + else if(header.primitives_count == 4) ASSERT(m == 0); /* Internal */ + else ASSERT(m == 1); /* In between */ + OK(senc2d_enclosure_ref_put(enclosure)); +#ifdef DUMP_ENCLOSURES + snprintf(name, sizeof(name), "test_square_on_square_%u.obj", e); + dump_enclosure(scn, e, name); +#endif } - CHK(senc2d_scene_ref_put(scn) == RES_OK); - CHK(senc2d_device_ref_put(dev) == RES_OK); - if(desc) CHK(senc2d_descriptor_ref_put(desc) == RES_OK); + OK(senc2d_scene_ref_put(scn)); + OK(senc2d_device_ref_put(dev)); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); diff --git a/src/test_senc2d_undefined_medium.c b/src/test_senc2d_undefined_medium.c @@ -1,279 +0,0 @@ -/* Copyright (C) |Meso|Star> 2018-2020 (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 "senc2d.h" -#include "senc2d_s2d_wrapper.h" -#include "test_senc2d_utils.h" - -#include <rsys/double2.h> - -static void -test(const int convention) -{ - struct mem_allocator allocator; - struct senc2d_descriptor* desc = NULL; - struct senc2d_device* dev = NULL; - struct senc2d_scene* scn = NULL; - struct senc2d_enclosure* enclosure; - struct senc2d_enclosure_header header; - unsigned medium, expected_external_medium, expected_internal_medium; - unsigned gid; - enum senc2d_side side; - struct context ctx; - unsigned i, s, ecount, vcount, scount; - unsigned media[4]; - unsigned rev_box_indices[sizeof(box_indices) / sizeof(*box_indices)]; - int conv_front; - - conv_front = (convention & SENC2D_CONVENTION_NORMAL_FRONT) != 0; - - /* Create a box with reversed segments */ - FOR_EACH(i, 0, sizeof(rev_box_indices) / sizeof(*rev_box_indices)) { - switch (i % 2) { - case 0: rev_box_indices[i] = box_indices[i + 1]; break; - case 1: rev_box_indices[i] = box_indices[i - 1]; break; - } - } - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); - - OK(senc2d_scene_create(dev, convention, &scn)); - - /* A 2D square. - * 2 enclosures (inside, outside) sharing the same segments, - * but opposite sides */ - ctx.positions = box_vertices; - ctx.indices = box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - d2(ctx.offset, 0, 0); - ctx.front_media = media; - ctx.back_media = medium1; - - /* Can add the same segments again defined/undefined media in any order */ - - /* Add geometry with no media information on both sides */ - for(i = 0; i < sizeof(media) / sizeof(*media); i++) - media[i] = SENC2D_UNDEFINED_MEDIUM; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, NULL, NULL, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == 2 * nsegments); - - /* Add geometry with no media information on the front sides */ - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == nsegments); - - /* Analyze with undefined media on the front sides */ - OK(senc2d_scene_analyze(scn, &desc)); - OK(senc2d_descriptor_get_enclosure_count(desc, &ecount)); - CHK(ecount == 2); - - FOR_EACH(i, 0, ecount) { - struct senc2d_enclosure* ee; - struct senc2d_enclosure_header hh; - unsigned cc; - OK(senc2d_descriptor_get_enclosure(desc, i, &enclosure)); - OK(senc2d_enclosure_get_header(enclosure, &header)); - - CHK(header.enclosure_id == i); - CHK(header.enclosed_media_count == 1); - - OK(senc2d_enclosure_get_medium(enclosure, 0, &medium)); - /* Geometrical normals point outside the cube in input segments: - * if convention is front, front medium (undef) is outside, - * that is medium 0's enclosure is infinite */ - expected_external_medium = conv_front ? SENC2D_UNDEFINED_MEDIUM : 1; - expected_internal_medium = conv_front ? 1 : SENC2D_UNDEFINED_MEDIUM; - - CHK(medium == (header.is_infinite - ? expected_external_medium : expected_internal_medium)); - CHK(header.segment_count == nsegments); - CHK(header.unique_segment_count == nsegments); - CHK(header.vertices_count == nvertices); - CHK(header.is_infinite == (i == 0)); - - OK(senc2d_descriptor_get_enclosure_count_by_medium(desc, medium, &cc)); - CHK(cc == 1); - OK(senc2d_descriptor_get_enclosure_by_medium(desc, medium, 0, &ee)); - OK(senc2d_enclosure_get_header(ee, &hh)); - CHK(header.enclosure_id == hh.enclosure_id); - OK(senc2d_enclosure_ref_put(ee)); - - FOR_EACH(s, 0, header.segment_count) { - unsigned ind[2]; - OK(senc2d_enclosure_get_segment_global_id(enclosure, s, &gid, &side)); - CHK(side == (medium == 1) ? SENC2D_BACK : SENC2D_FRONT); - CHK(gid == s); - OK(senc2d_enclosure_get_segment(enclosure, s, ind)); - } - OK(senc2d_enclosure_ref_put(enclosure)); - } - OK(senc2d_descriptor_ref_put(desc)); - - - /* Same geometry, front media are defined for odd segments */ - for(i = 0; i < sizeof(media) / sizeof(*media); i++) - media[i] = (i % 2) ? 0 : SENC2D_UNDEFINED_MEDIUM; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == nsegments / 2); - - /* Analyze with undefined media */ - OK(senc2d_scene_analyze(scn, &desc)); - OK(senc2d_descriptor_ref_put(desc)); - - /* Get the deduplicated geometry without (successful) analyze */ - OK(senc2d_scene_get_unique_vertices_count(scn, &vcount)); - CHK(vcount == nvertices); - OK(senc2d_scene_get_unique_segments_count(scn, &scount)); - CHK(vcount == nsegments); - FOR_EACH(i, 0, vcount) { - int j; - unsigned med[2], ids[2]; - OK(senc2d_scene_get_unique_segment(scn, i, ids)); - OK(senc2d_scene_get_unique_segment_media(scn, i, med)); - CHK(med[0] == ((i % 2) ? 0 : SENC2D_UNDEFINED_MEDIUM) && med[1] == 1); - FOR_EACH(j, 0, 2) { - double pos[2]; - CHK(ids[j] < vcount); - OK(senc2d_scene_get_unique_vertex(scn, ids[j], pos)); - } - } - - /* Same information again, using a reversed box */ - ctx.indices = rev_box_indices; - SWAP(const unsigned*, ctx.front_media, ctx.back_media); - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == nsegments / 2); - - /* Analyze with undefined media */ - OK(senc2d_scene_analyze(scn, &desc)); - OK(senc2d_descriptor_ref_put(desc)); - - /* Define media for remaining segments, using reversed box */ - for(i = 0; i < sizeof(media) / sizeof(*media); i++) - media[i] = (i % 2) ? SENC2D_UNDEFINED_MEDIUM : 0; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == 0); - - /* Get the deduplicated geometry without (successful) analyze */ - OK(senc2d_scene_get_unique_vertices_count(scn, &vcount)); - CHK(vcount == nvertices); - OK(senc2d_scene_get_unique_segments_count(scn, &scount)); - CHK(scount == nsegments); - FOR_EACH(i, 0, scount) { - int j; - unsigned med[2], ids[2]; - OK(senc2d_scene_get_unique_segment(scn, i, ids)); - OK(senc2d_scene_get_unique_segment_media(scn, i, med)); - CHK(med[0] == 0 && med[1] == 1); - FOR_EACH(j, 0, 2) { - double pos[2]; - CHK(ids[j] < vcount); - OK(senc2d_scene_get_unique_vertex(scn, ids[j], pos)); - } - } - - /* Analyze with all media defined */ - OK(senc2d_scene_analyze(scn, &desc)); - OK(senc2d_descriptor_ref_put(desc)); - - /* Define media for all segments, nothing new here */ - for(i = 0; i < sizeof(media) / sizeof(*media); i++) - media[i] = 0; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == 0); - - /* Define incoherent media for some segments */ - for(i = 0; i < sizeof(media) / sizeof(*media); i++) - media[i] = (i % 2); - BA(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, NULL, NULL, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == 0); - - /* Scene is still OK and can be analyzed */ - OK(senc2d_scene_analyze(scn, &desc)); - - OK(senc2d_descriptor_get_global_segments_count(desc, &scount)); - CHK(scount == sizeof(media) / sizeof(*media)); - - OK(senc2d_descriptor_get_enclosure_count(desc, &ecount)); - CHK(ecount == 2); - - FOR_EACH(i, 0, ecount) { - struct senc2d_enclosure* ee; - struct senc2d_enclosure_header hh; - unsigned cc; - OK(senc2d_descriptor_get_enclosure(desc, i, &enclosure)); - OK(senc2d_enclosure_get_header(enclosure, &header)); - - CHK(header.enclosure_id == i); - CHK(header.enclosed_media_count == 1); - OK(senc2d_enclosure_get_medium(enclosure, 0, &medium)); - /* Geometrical normals point outside the cube in input segments: - * if convention is front, front medium (0) is outside, - * that is medium 0's enclosure is infinite */ - CHK(conv_front == ((medium == 0) == header.is_infinite)); - CHK(header.segment_count == nsegments); - CHK(header.unique_segment_count == nsegments); - CHK(header.vertices_count == nvertices); - CHK(header.is_infinite == (i == 0)); - - OK(senc2d_descriptor_get_enclosure_count_by_medium(desc, medium, &cc)); - CHK(cc == 1); - OK(senc2d_descriptor_get_enclosure_by_medium(desc, medium, 0, &ee)); - OK(senc2d_enclosure_get_header(ee, &hh)); - CHK(header.enclosure_id == hh.enclosure_id); - OK(senc2d_enclosure_ref_put(ee)); - - FOR_EACH(s, 0, header.segment_count) { - OK(senc2d_enclosure_get_segment_global_id(enclosure, s, &gid, &side)); - CHK(side == (medium == 1) ? SENC2D_BACK : SENC2D_FRONT); - CHK(gid == s); - } - OK(senc2d_enclosure_ref_put(enclosure)); - } - - SENC2D(scene_ref_put(scn)); - SENC2D(device_ref_put(dev)); - SENC2D(descriptor_ref_put(desc)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); -} - -int -main(int argc, char** argv) -{ - (void)argc, (void)argv; - test(SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE); - test(SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_INSIDE); - test(SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_OUTSIDE); - test(SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_OUTSIDE); - return 0; -} diff --git a/src/test_senc2d_undefined_medium_attr.c b/src/test_senc2d_undefined_medium_attr.c @@ -1,376 +0,0 @@ -/* Copyright (C) |Meso|Star> 2018-2020 (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 "senc2d.h" -#include "senc2d_s2d_wrapper.h" -#include "test_senc2d_utils.h" - -#include <rsys/double2.h> - -#include <limits.h> - -#define INVALID_INTFACE_ID UINT_MAX - -static FINLINE void -set_null_id(struct mem_allocator* alloc, unsigned* data) -{ - ASSERT(data); (void)alloc; - *data = INVALID_INTFACE_ID; -} - -#include <rsys/dynamic_array.h> -#define DARRAY_NAME intface_id -#define DARRAY_FUNCTOR_INIT set_null_id -#define DARRAY_DATA unsigned -#include <rsys/dynamic_array.h> - -/* Manage interface properties */ -struct merge_ctx { - struct darray_intface_id global_interf_data; - const unsigned* current_add_interf_data; -}; - -static res_T -add_seg - (const unsigned global_id, - const unsigned iseg, - void* context) -{ - res_T res = RES_OK; - struct context* ctx = context; - struct merge_ctx* merge_ctx; - unsigned interf; - ASSERT(ctx); - merge_ctx = ctx->custom; - /* Get interface information from ctx */ - interf = merge_ctx->current_add_interf_data[iseg]; - /* Keep data */ - res = darray_intface_id_resize(&merge_ctx->global_interf_data, global_id + 1); - if(res != RES_OK) return res; - darray_intface_id_data_get(&merge_ctx->global_interf_data)[global_id] = interf; - return res; -} - -static res_T -merge_seg - (const unsigned global_id, - const unsigned iseg, - const int reversed_segment, - const unsigned segment_media[2], - const unsigned merge_media[2], - void* context) -{ - res_T res = RES_OK; - struct context* ctx = context; - struct merge_ctx* merge_ctx; - int need_merge; - unsigned interf; - unsigned* interf_data; - int i, compat; - ASSERT(ctx); (void)reversed_segment; - /* Check media compatibility */ - compat = 1; - FOR_EACH(i, 0, 2) - compat &= (segment_media[i] == SENC2D_UNDEFINED_MEDIUM - || merge_media[i] == SENC2D_UNDEFINED_MEDIUM - || segment_media[i] == merge_media[i]); - if(!compat) return RES_BAD_ARG; - merge_ctx = ctx->custom; - res = darray_intface_id_resize(&merge_ctx->global_interf_data, global_id + 1); - if(res != RES_OK) return res; - /* Get interface information from ctx */ - interf = merge_ctx->current_add_interf_data[iseg]; - interf_data = darray_intface_id_data_get(&merge_ctx->global_interf_data); - - need_merge = (interf_data[global_id] != INVALID_INTFACE_ID); - if(need_merge) { - if(interf_data[global_id] != interf) - /* Previous interface id is different: no possible merge */ - return RES_BAD_ARG; - } else { - /* Segment is known, but without interface information: create */ - interf_data[global_id] = interf; - } - /* Same data: no merge needed */ - return RES_OK; -} - -static void -test(const int convention) -{ - struct mem_allocator allocator; - struct senc2d_descriptor* desc = NULL; - struct senc2d_device* dev = NULL; - struct senc2d_scene* scn = NULL; - struct senc2d_enclosure* enclosure; - struct senc2d_enclosure_header header; - unsigned medium, expected_external_medium, expected_internal_medium; - unsigned gid; - enum senc2d_side side; - struct context ctx; - unsigned i, s, ecount, vcount, scount; - unsigned media[4], interface_ids[4] = { 0, 0, 1, 1, }; - unsigned rev_box_indices[sizeof(box_indices) / sizeof(*box_indices)]; - struct merge_ctx merge_ctx; - int conv_front = (convention & SENC2D_CONVENTION_NORMAL_FRONT) != 0; - - darray_intface_id_init(&allocator, &merge_ctx.global_interf_data); - merge_ctx.current_add_interf_data = interface_ids; - - /* Create a box with reversed segments */ - FOR_EACH(i, 0, sizeof(rev_box_indices) / sizeof(*rev_box_indices)) { - switch (i % 2) { - case 0: rev_box_indices[i] = box_indices[i + 1]; break; - case 1: rev_box_indices[i] = box_indices[i - 1]; break; - } - } - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); - - OK(senc2d_scene_create(dev, convention, &scn)); - - /* A 2D square. - * 2 enclosures (inside, outside) sharing the same segments, - * but opposite sides */ - ctx.positions = box_vertices; - ctx.indices = box_indices; - ctx.scale = 1; - ctx.reverse_vrtx = 0; - ctx.reverse_med = 0; - d2(ctx.offset, 0, 0); - ctx.front_media = media; - ctx.back_media = medium1; - ctx.custom = &merge_ctx; - - /* Can add the same segments again defined/undefined media in any order */ - - /* Add geometry with no media information on both sides */ - for(i = 0; i < sizeof(media) / sizeof(*media); i++) - media[i] = SENC2D_UNDEFINED_MEDIUM; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == 2 * nsegments); - - /* If merge fails, add geometry fails */ - interface_ids[0] = 6; - BA(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, - nvertices, get_position, add_seg, merge_seg, &ctx)); - interface_ids[0] = 0; - - /* Add geometry with no media information on the front sides */ - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, add_seg, merge_seg, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == nsegments); - - /* Analyze with undefined media on the front sides */ - OK(senc2d_scene_analyze(scn, &desc)); - OK(senc2d_descriptor_get_enclosure_count(desc, &ecount)); - CHK(ecount == 2); - - FOR_EACH(i, 0, ecount) { - struct senc2d_enclosure* ee; - struct senc2d_enclosure_header hh; - unsigned cc; - OK(senc2d_descriptor_get_enclosure(desc, i, &enclosure)); - OK(senc2d_enclosure_get_header(enclosure, &header)); - - CHK(header.enclosure_id == i); - CHK(header.enclosed_media_count == 1); - - OK(senc2d_enclosure_get_medium(enclosure, 0, &medium)); - /* Geometrical normals point outside the cube in input segments: - * if convention is front, front medium (undef) is outside, - * that is medium 0's enclosure is infinite */ - expected_external_medium = conv_front ? SENC2D_UNDEFINED_MEDIUM : 1; - expected_internal_medium = conv_front ? 1 : SENC2D_UNDEFINED_MEDIUM; - - CHK(medium == (header.is_infinite - ? expected_external_medium : expected_internal_medium)); - CHK(header.segment_count == nsegments); - CHK(header.unique_segment_count == nsegments); - CHK(header.vertices_count == nvertices); - CHK(header.is_infinite == (i == 0)); - - OK(senc2d_descriptor_get_enclosure_count_by_medium(desc, medium, &cc)); - CHK(cc == 1); - OK(senc2d_descriptor_get_enclosure_by_medium(desc, medium, 0, &ee)); - OK(senc2d_enclosure_get_header(ee, &hh)); - CHK(header.enclosure_id == hh.enclosure_id); - OK(senc2d_enclosure_ref_put(ee)); - - FOR_EACH(s, 0, header.segment_count) { - unsigned ind[2]; - OK(senc2d_enclosure_get_segment_global_id(enclosure, s, &gid, &side)); - CHK(gid == s); - CHK(side == (medium == 1) ? SENC2D_BACK : SENC2D_FRONT); - OK(senc2d_enclosure_get_segment(enclosure, s, ind)); - } - OK(senc2d_enclosure_ref_put(enclosure)); - } - OK(senc2d_descriptor_ref_put(desc)); - - /* Same geometry, front media are defined for odd segments */ - for(i = 0; i < sizeof(media) / sizeof(*media); i++) - media[i] = (i % 2) ? 0 : SENC2D_UNDEFINED_MEDIUM; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, add_seg, merge_seg, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == nsegments / 2); - - /* Analyze with undefined media */ - OK(senc2d_scene_analyze(scn, &desc)); - OK(senc2d_descriptor_ref_put(desc)); - - /* Get the deduplicated geometry without (successful) analyze */ - OK(senc2d_scene_get_unique_vertices_count(scn, &vcount)); - CHK(vcount == nvertices); - OK(senc2d_scene_get_unique_segments_count(scn, &scount)); - CHK(scount == nsegments); - FOR_EACH(i, 0, scount) { - int j; - unsigned med[2], ids[2]; - OK(senc2d_scene_get_unique_segment(scn, i, ids)); - OK(senc2d_scene_get_unique_segment_media(scn, i, med)); - CHK(med[0] == ((i % 2) ? 0 : SENC2D_UNDEFINED_MEDIUM) && med[1] == 1); - FOR_EACH(j, 0, 2) { - double pos[2]; - CHK(ids[j] < vcount); - OK(senc2d_scene_get_unique_vertex(scn, ids[j], pos)); - } - } - - /* Same information again, using a reversed box */ - ctx.indices = rev_box_indices; - SWAP(const unsigned*, ctx.front_media, ctx.back_media); - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, add_seg, merge_seg, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == nsegments / 2); - - /* Analyze with undefined media */ - OK(senc2d_scene_analyze(scn, &desc)); - OK(senc2d_descriptor_ref_put(desc)); - - /* Define media for remaining segments, using reversed box */ - for(i = 0; i < sizeof(media) / sizeof(*media); i++) - media[i] = (i % 2) ? SENC2D_UNDEFINED_MEDIUM : 0; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, add_seg, merge_seg, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == 0); - - /* Get the deduplicated geometry without (successful) analyze */ - OK(senc2d_scene_get_unique_vertices_count(scn, &vcount)); - CHK(vcount == nvertices); - OK(senc2d_scene_get_unique_segments_count(scn, &scount)); - CHK(scount == nsegments); - FOR_EACH(i, 0, scount) { - int j; - unsigned med[2], ids[2]; - OK(senc2d_scene_get_unique_segment(scn, i, ids)); - OK(senc2d_scene_get_unique_segment_media(scn, i, med)); - CHK(med[0] == 0 && med[1] == 1); - FOR_EACH(j, 0, 2) { - double pos[2]; - CHK(ids[j] < vcount); - OK(senc2d_scene_get_unique_vertex(scn, ids[j], pos)); - } - } - - /* Analyze with all media defined */ - OK(senc2d_scene_analyze(scn, &desc)); - OK(senc2d_descriptor_ref_put(desc)); - - /* Define media for all segments, nothing new here */ - for(i = 0; i < sizeof(media) / sizeof(*media); i++) - media[i] = 0; - OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, add_seg, merge_seg, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == 0); - - /* Define incoherent media for some segments */ - for(i = 0; i < sizeof(media) / sizeof(*media); i++) - media[i] = (i % 2); - BA(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, - nvertices, get_position, add_seg, merge_seg, &ctx)); - OK(senc2d_scene_get_unique_sides_without_medium_count(scn, &scount)); - CHK(scount == 0); - - /* Scene is still OK and can be analyzed */ - OK(senc2d_scene_analyze(scn, &desc)); - - OK(senc2d_descriptor_get_global_segments_count(desc, &scount)); - CHK(scount == sizeof(media) / sizeof(*media)); - - OK(senc2d_descriptor_get_enclosure_count(desc, &ecount)); - CHK(ecount == 2); - - FOR_EACH(i, 0, ecount) { - struct senc2d_enclosure* ee; - struct senc2d_enclosure_header hh; - unsigned cc; - OK(senc2d_descriptor_get_enclosure(desc, i, &enclosure)); - OK(senc2d_enclosure_get_header(enclosure, &header)); - - CHK(header.enclosure_id == i); - CHK(header.enclosed_media_count == 1); - OK(senc2d_enclosure_get_medium(enclosure, 0, &medium)); - /* Geometrical normals point outside the cube in input segments: - * if convention is front, front medium (0) is outside, - * that is medium 0's enclosure is infinite */ - CHK(conv_front == ((medium == 0) == header.is_infinite)); - CHK(header.segment_count == nsegments); - CHK(header.unique_segment_count == nsegments); - CHK(header.vertices_count == nvertices); - CHK(header.is_infinite == (i == 0)); - - OK(senc2d_descriptor_get_enclosure_count_by_medium(desc, medium, &cc)); - CHK(cc == 1); - OK(senc2d_descriptor_get_enclosure_by_medium(desc, medium, 0, &ee)); - OK(senc2d_enclosure_get_header(ee, &hh)); - CHK(header.enclosure_id == hh.enclosure_id); - OK(senc2d_enclosure_ref_put(ee)); - - FOR_EACH(s, 0, header.segment_count) { - OK(senc2d_enclosure_get_segment_global_id(enclosure, s, &gid, &side)); - CHK(gid == s); - CHK(side == (medium == 1) ? SENC2D_BACK : SENC2D_FRONT); - } - OK(senc2d_enclosure_ref_put(enclosure)); - } - - SENC2D(scene_ref_put(scn)); - SENC2D(device_ref_put(dev)); - SENC2D(descriptor_ref_put(desc)); - darray_intface_id_release(&merge_ctx.global_interf_data); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); -} - -int -main(int argc, char** argv) -{ - (void)argc, (void)argv; - test(SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE); - test(SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_INSIDE); - test(SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_OUTSIDE); - test(SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_OUTSIDE); - return 0; -} diff --git a/src/test_senc2d_unspecified_medium.c b/src/test_senc2d_unspecified_medium.c @@ -0,0 +1,267 @@ +/* Copyright (C) |Meso|Star> 2018-2020 (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/>. */ + +/* This test has been created using the sg2_geometry_dump_as_C_code feature + * of star-geometry-2D. It uses output from test_sg2_unspecified_properties. + * This test is similar to test_senc2d_many_enclosures that creates a huge + * geometry by program. */ + +#include "senc2d.h" +#include "senc2d_sXd_helper.h" +#include "test_senc2d_utils.h" + +#include <rsys/double2.h> + +#define SG2_UNSPECIFIED_PROPERTY UINT_MAX + +/* Dump of star-geometry-2D 'front_unspecified'. */ +static const unsigned front_unspecified_vertices_count = 4; +static const double front_unspecified_vertices[8] = +{ + 0.1, 0, + 1, 0, + 0, 1.1, + 1, 1 +}; +static const unsigned front_unspecified_segments_count = 4; +static const unsigned front_unspecified_segments[8] = +{ + 0, 2, + 2, 3, + 3, 1, + 1, 0 +}; +static const unsigned front_unspecified_properties[12] = +{ + SG2_UNSPECIFIED_PROPERTY, 1, SG2_UNSPECIFIED_PROPERTY, + SG2_UNSPECIFIED_PROPERTY, 1, SG2_UNSPECIFIED_PROPERTY, + SG2_UNSPECIFIED_PROPERTY, 1, SG2_UNSPECIFIED_PROPERTY, + SG2_UNSPECIFIED_PROPERTY, 1, SG2_UNSPECIFIED_PROPERTY +}; +/* Dump of star-geometry-2D 'front_half_unspecified'. */ +static const unsigned front_half_unspecified_vertices_count = 4; +static const double front_half_unspecified_vertices[8] = +{ + 0.1, 0, + 1, 0, + 0, 1.1, + 1, 1 +}; +static const unsigned front_half_unspecified_segments_count = 4; +static const unsigned front_half_unspecified_segments[8] = +{ + 0, 2, + 2, 3, + 3, 1, + 1, 0 +}; +static const unsigned front_half_unspecified_properties[12] = +{ + SG2_UNSPECIFIED_PROPERTY, 1, SG2_UNSPECIFIED_PROPERTY, + 0, 1, 0, + SG2_UNSPECIFIED_PROPERTY, 1, SG2_UNSPECIFIED_PROPERTY, + 0, 1, 0 +}; +/* Dump of star-geometry-2D 'all_defined'. */ +static const unsigned all_defined_vertices_count = 4; +static const double all_defined_vertices[8] = +{ + 0.1, 0, + 1, 0, + 0, 1.1, + 1, 1 +}; +static const unsigned all_defined_segments_count = 4; +static const unsigned all_defined_segments[8] = +{ + 0, 2, + 2, 3, + 3, 1, + 1, 0 +}; +static const unsigned all_defined_properties[12] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 +}; + +static void +test(const int convention) +{ + struct mem_allocator allocator; + struct senc2d_device* dev = NULL; + struct senc2d_scene* scn = NULL; + struct senc2d_enclosure* enclosure; + struct senc2d_enclosure_header header; + unsigned medium, expected_external_medium, expected_internal_medium; + unsigned gid; + enum senc2d_side side; + struct context ctx = CONTEXT_NULL__; + unsigned i, s, ecount; + const int conv_front = (convention & SENC2D_CONVENTION_NORMAL_FRONT) != 0; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); + + /* Geometry with no media information on both sides */ + ctx.positions = front_unspecified_vertices; + ctx.indices = front_unspecified_segments; + ctx.properties = front_unspecified_properties; + OK(senc2d_scene_create(dev, convention, front_unspecified_segments_count, + get_indices, get_media_from_properties, front_unspecified_vertices_count, + get_position, &ctx, &scn)); + + OK(senc2d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 2); + + FOR_EACH(i, 0, ecount) { + struct senc2d_enclosure* ee; + struct senc2d_enclosure_header hh; + unsigned cc; + OK(senc2d_scene_get_enclosure(scn, i, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); + + CHK(header.enclosure_id == i); + CHK(header.enclosed_media_count == 1); + + OK(senc2d_enclosure_get_medium(enclosure, 0, &medium)); + /* Geometrical normals point outside the square in input segments: + * if convention is front, front medium (undef) is outside, + * that is medium 0's enclosure is infinite */ + expected_external_medium = conv_front ? SENC2D_UNSPECIFIED_MEDIUM : 1; + expected_internal_medium = conv_front ? 1 : SENC2D_UNSPECIFIED_MEDIUM; + + CHK(medium == (header.is_infinite + ? expected_external_medium : expected_internal_medium)); + CHK(header.primitives_count == nsegments); + CHK(header.unique_primitives_count == nsegments); + CHK(header.vertices_count == nvertices); + CHK(header.is_infinite == (i == 0)); + + OK(senc2d_scene_get_enclosure_count_by_medium(scn, medium, &cc)); + CHK(cc == 1); + OK(senc2d_scene_get_enclosure_by_medium(scn, medium, 0, &ee)); + OK(senc2d_enclosure_get_header(ee, &hh)); + CHK(header.enclosure_id == hh.enclosure_id); + OK(senc2d_enclosure_ref_put(ee)); + + FOR_EACH(s, 0, header.primitives_count) { + unsigned ind[2]; + OK(senc2d_enclosure_get_segment_id(enclosure, s, &gid, &side)); + CHK(gid == s); + CHK(side == (medium == 1) ? SENC2D_BACK : SENC2D_FRONT); + OK(senc2d_enclosure_get_segment(enclosure, s, ind)); + } + OK(senc2d_enclosure_ref_put(enclosure)); + } + OK(senc2d_scene_ref_put(scn)); + + /* Same geometry, front media are defined for odd segments */ + ctx.positions = front_half_unspecified_vertices; + ctx.indices = front_half_unspecified_segments; + ctx.properties = front_half_unspecified_properties; + OK(senc2d_scene_create(dev, convention, front_half_unspecified_segments_count, + get_indices, get_media_from_properties, front_half_unspecified_vertices_count, + get_position, &ctx, &scn)); + + OK(senc2d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 2); + + FOR_EACH(i, 0, ecount) { + unsigned expected_external_media_count, expected_internal_media_count, + expected_media_count; + OK(senc2d_scene_get_enclosure(scn, i, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); + + CHK(header.enclosure_id == i); + + OK(senc2d_enclosure_get_medium(enclosure, 0, &medium)); + /* Geometrical normals point outside the square in input segments: + * if convention is front, front medium is outside and the enclosure + * contains 2 media */ + expected_external_media_count = conv_front ? 2 : 1; + expected_internal_media_count = conv_front ? 1 : 2; + expected_media_count = header.is_infinite + ? expected_external_media_count : expected_internal_media_count; + CHK(header.enclosed_media_count == expected_media_count); + OK(senc2d_enclosure_ref_put(enclosure)); + } + OK(senc2d_scene_ref_put(scn)); + + /* Same geometry, all media are defined */ + ctx.positions = all_defined_vertices; + ctx.indices = all_defined_segments; + ctx.properties = all_defined_properties; + OK(senc2d_scene_create(dev, convention, all_defined_segments_count, + get_indices, get_media_from_properties, all_defined_vertices_count, + get_position, &ctx, &scn)); + + OK(senc2d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 2); + + FOR_EACH(i, 0, ecount) { + struct senc2d_enclosure* ee; + struct senc2d_enclosure_header hh; + unsigned cc; + OK(senc2d_scene_get_enclosure(scn, i, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); + + CHK(header.enclosure_id == i); + CHK(header.enclosed_media_count == 1); + OK(senc2d_enclosure_get_medium(enclosure, 0, &medium)); + /* Geometrical normals point outside the square in input segments: + * if convention is front, front medium (0) is outside, + * that is medium 0's enclosure is infinite */ + CHK(conv_front == ((medium == 0) == header.is_infinite)); + CHK(header.primitives_count == nsegments); + CHK(header.unique_primitives_count == nsegments); + CHK(header.vertices_count == nvertices); + CHK(header.is_infinite == (i == 0)); + + OK(senc2d_scene_get_enclosure_count_by_medium(scn, medium, &cc)); + CHK(cc == 1); + OK(senc2d_scene_get_enclosure_by_medium(scn, medium, 0, &ee)); + OK(senc2d_enclosure_get_header(ee, &hh)); + CHK(header.enclosure_id == hh.enclosure_id); + OK(senc2d_enclosure_ref_put(ee)); + + FOR_EACH(s, 0, header.primitives_count) { + OK(senc2d_enclosure_get_segment_id(enclosure, s, &gid, &side)); + CHK(gid == s); + CHK(side == (medium == 1) ? SENC2D_BACK : SENC2D_FRONT); + } + OK(senc2d_enclosure_ref_put(enclosure)); + } + + SENC2D(scene_ref_put(scn)); + SENC2D(device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); +} + +int +main(int argc, char** argv) +{ + (void)argc, (void)argv; + test(SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE); + test(SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_INSIDE); + test(SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_OUTSIDE); + test(SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_OUTSIDE); + return 0; +} diff --git a/src/test_senc2d_utils.h b/src/test_senc2d_utils.h @@ -13,8 +13,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef TEST_UTILS2_H -#define TEST_UTILS2_H +#ifndef TEST_SENC2_UTILS_H +#define TEST_SENC2_UTILS_H #include <rsys/rsys.h> #include <rsys/mem_allocator.h> @@ -26,18 +26,20 @@ #define OK(Expr) CHK((Expr) == RES_OK) #define BA(Expr) CHK((Expr) == RES_BAD_ARG) -/******************************************************************************* +/****************************************************************************** * Geometry - ******************************************************************************/ - /* Distorded square */ -static double box_vertices[4/*#vertices*/*2/*#coords per vertex*/] = { + *****************************************************************************/ +/* Distorded square */ +static const double +box_vertices[4/*#vertices*/ * 2/*#coords per vertex*/] = { 0.1, 0.0, 1.0, 0.0, 0.0, 1.1, 1.0, 1.0 }; /* Need a true square for some tests */ -static double square_vertices[4/*#vertices*/ * 2/*#coords per vertex*/] = { +static const double +square_vertices[4/*#vertices*/ * 2/*#coords per vertex*/] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, @@ -56,8 +58,8 @@ STATIC_ASSERT(sizeof(box_vertices) == sizeof(square_vertices), * | | * 0----1 */ -static unsigned -box_indices[4/*#segments*/*2/*#indices per segment*/] = { +static const unsigned +box_indices[4/*#segments*/ * 2/*#indices per segment*/] = { 0, 2, 2, 3, 3, 1, @@ -67,15 +69,19 @@ static const unsigned nsegments = sizeof(box_indices) / (2 * sizeof(*box_indices)); struct context { - double* positions; - unsigned* indices; + const double* positions; + const unsigned* indices; const unsigned* front_media; const unsigned* back_media; + const unsigned* properties; void* custom; double offset[2]; double scale; char reverse_vrtx, reverse_med; }; +#define CONTEXT_NULL__ {\ + NULL, NULL, NULL, NULL, NULL, NULL, {0,0}, 1, 0, 0\ +} static const unsigned medium0[4] = { 0, 0, 0, 0 }; static const unsigned medium1[4] = { 1, 1, 1, 1 }; @@ -111,41 +117,49 @@ get_media(const unsigned iseg, unsigned medium[2], void* context) medium[ctx->reverse_med ? 0 : 1] = ctx->back_media[iseg]; } -/******************************************************************************* +static INLINE void +get_media_from_properties(const unsigned iseg, unsigned medium[2], void* context) +{ + const struct context* ctx = context; + ASSERT(medium && ctx); + medium[ctx->reverse_med ? 1 : 0] = ctx->properties[3 * iseg + 0]; + medium[ctx->reverse_med ? 0 : 1] = ctx->properties[3 * iseg + 1]; +} + +/****************************************************************************** * Miscellaneous - ******************************************************************************/ + *****************************************************************************/ static INLINE void dump_global - (struct senc2d_descriptor* desc, + (struct senc2d_scene* scn, const char* name) { FILE* stream; - unsigned segment_count, vertices_count, i; + unsigned segments_count, vertices_count, i; - ASSERT(desc && name); + ASSERT(scn && name); - CHK(senc2d_descriptor_get_global_vertices_count(desc, &vertices_count) == RES_OK); - CHK(senc2d_descriptor_get_global_segments_count(desc, &segment_count) == RES_OK); + OK(senc2d_scene_get_vertices_count(scn, &vertices_count)); + OK(senc2d_scene_get_segments_count(scn, &segments_count)); stream = fopen(name, "w"); CHK(stream); FOR_EACH(i, 0, vertices_count) { double tmp[2]; - CHK(senc2d_descriptor_get_global_vertex(desc, i, tmp) == RES_OK); - fprintf(stream, "v %g %g 0\n", SPLIT2(tmp)); + OK(senc2d_scene_get_vertex(scn, i, tmp)); + fprintf(stream, "v %g %g\n", SPLIT2(tmp)); } - FOR_EACH(i, 0, segment_count) { + FOR_EACH(i, 0, segments_count) { unsigned indices[2]; - CHK(senc2d_descriptor_get_global_segment(desc, i, indices) == RES_OK); - fprintf(stream, "l %lu %lu\n", - (unsigned long)(1 + indices[0]), (unsigned long)(1 + indices[1])); + OK(senc2d_scene_get_segment(scn, i, indices)); + fprintf(stream, "l %u %u\n", 1 + indices[0], 1 + indices[1]); } fclose(stream); } static INLINE void dump_enclosure - (struct senc2d_descriptor* desc, + (struct senc2d_scene* scn, const unsigned enc, const char* name) { @@ -154,27 +168,26 @@ dump_enclosure FILE* stream; unsigned count, i; - ASSERT(desc && name); + ASSERT(scn && name); - SENC2D(descriptor_get_enclosure_count(desc, &count)); + SENC2D(scene_get_enclosure_count(scn, &count)); ASSERT(enc < count); - CHK(senc2d_descriptor_get_enclosure(desc, enc, &enclosure) == RES_OK); - CHK(senc2d_enclosure_get_header(enclosure, &header) == RES_OK); + OK(senc2d_scene_get_enclosure(scn, enc, &enclosure)); + OK(senc2d_enclosure_get_header(enclosure, &header)); stream = fopen(name, "w"); CHK(stream); FOR_EACH(i, 0, header.vertices_count) { double tmp[2]; - CHK(senc2d_enclosure_get_vertex(enclosure, i, tmp) == RES_OK); - fprintf(stream, "v %g %g 0\n", SPLIT2(tmp)); + OK(senc2d_enclosure_get_vertex(enclosure, i, tmp)); + fprintf(stream, "v %g %g\n", SPLIT2(tmp)); } - FOR_EACH(i, 0, header.segment_count) { + FOR_EACH(i, 0, header.primitives_count) { unsigned indices[2]; - CHK(senc2d_enclosure_get_segment(enclosure, i, indices) == RES_OK); - fprintf(stream, "l %lu %lu\n", - (unsigned long)(1+indices[0]), (unsigned long)(1+indices[1])); + OK(senc2d_enclosure_get_segment(enclosure, i, indices)); + fprintf(stream, "l %u %u\n", 1+indices[0], 1+indices[1]); } - CHK(senc2d_enclosure_ref_put(enclosure) == RES_OK); + OK(senc2d_enclosure_ref_put(enclosure)); fclose(stream); } @@ -189,10 +202,10 @@ check_memory_allocator(struct mem_allocator* allocator) } } -/******************************************************************************* +/****************************************************************************** * Circle functions - ******************************************************************************/ -static INLINE void + *****************************************************************************/ +static INLINE void create_circle (const double radius, const unsigned nslices, @@ -201,6 +214,8 @@ create_circle double step_theta; unsigned itheta; unsigned islice; + double* d = NULL; + unsigned* u = NULL; ASSERT(radius > 0 && nslices >= 3 && ctx); step_theta = 2 * PI / (double)nslices; @@ -208,16 +223,18 @@ create_circle const double theta = (double)itheta * step_theta; const double x = cos(theta); const double y = sin(theta); - sa_push(ctx->positions, x*radius); - sa_push(ctx->positions, y*radius); + sa_push(d, x * radius); + sa_push(d, y * radius); } + ctx->positions = d; FOR_EACH(islice, 0, nslices) { const unsigned v0 = islice; const unsigned v1 = ((islice + 1) % nslices); - sa_push(ctx->indices, v0); - sa_push(ctx->indices, v1); + sa_push(u, v0); + sa_push(u, v1); } + ctx->indices = u; } static INLINE void @@ -230,44 +247,9 @@ circle_release(struct context* ctx) ctx->indices = NULL; } - -/******************************************************************************* +/****************************************************************************** * Check functions - ******************************************************************************/ -static INLINE void check_desc(struct senc2d_descriptor* desc) -{ - unsigned maxm, ecount, i; - size_t e_cpt = 0; - CHK(senc2d_descriptor_get_max_medium(desc, &maxm) == RES_OK); - CHK(senc2d_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); - for(i = 0; i <= maxm; i++) { - unsigned j, ecount_bym; - unsigned found = 0; - CHK(senc2d_descriptor_get_enclosure_count_by_medium(desc, i, &ecount_bym) == RES_OK); - /* Can be 0 if media numbering is not compact */ - FOR_EACH(j, 0, ecount_bym) { - struct senc2d_enclosure* enc; - struct senc2d_enclosure_header h; - unsigned k; - int f = 0; - CHK(senc2d_descriptor_get_enclosure_by_medium(desc, i, j, &enc) == RES_OK); - CHK(senc2d_enclosure_get_header(enc, &h) == RES_OK); - ASSERT(h.enclosed_media_count); - FOR_EACH(k, 0, h.enclosed_media_count) { - unsigned m; - CHK(senc2d_enclosure_get_medium(enc, k, &m) == RES_OK); - found += (m == i); - f += (m == i); - } - ASSERT(f == 1); /* Single reference expected */ - CHK(senc2d_enclosure_ref_put(enc) == RES_OK); - } - ASSERT(found == ecount_bym); /* All the enclosures enclose medim i */ - e_cpt += ecount_bym; - } - ASSERT(e_cpt >= ecount); /* Every enc has been visited at least once */ -} - + *****************************************************************************/ /* Compare the iseg-th segment of enclosure with a segment described by seg2 & vertices2 */ static INLINE void cmp_seg @@ -286,9 +268,9 @@ cmp_seg ASSERT(enclosure && seg2 && vertices2 && seg_eq && seg_reversed); - CHK(senc2d_enclosure_get_segment(enclosure, iseg, seg1) == RES_OK); + OK(senc2d_enclosure_get_segment(enclosure, iseg, seg1)); FOR_EACH(i, 0, 2) { - CHK(senc2d_enclosure_get_vertex(enclosure, seg1[i], s1[i]) == RES_OK); + OK(senc2d_enclosure_get_vertex(enclosure, seg1[i], s1[i])); d2_set(s2[i], vertices2 + (2 * seg2[i])); } FOR_EACH(i, 0, 2) { @@ -316,4 +298,4 @@ cmp_seg ASSERT(*seg_reversed == (1 != seg1_eq[1])); } -#endif /* TEST_UTILS2_H */ +#endif /* TEST_SENC2_UTILS_H */ diff --git a/src/test_senc2d_utils2.h b/src/test_senc2d_utils2.h @@ -0,0 +1,109 @@ +/* Copyright (C) |Meso|Star> 2018-2020 (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/>. */ + +#ifndef TEST_SENC2_UTILS2_H +#define TEST_SENC2_UTILS2_H + +#if !defined(NB_CIRC_X) || !defined(NB_CIRC_Y) || !defined(NB_CIRC_Z) | !defined(NB_CIRC) +#error "Macro definitions are missing" +#endif + +#include "test_senc2d_utils.h" + +#include <rsys/double2.h> +#include <rsys/stretchy_array.h> + +static void +get_ctx_indices(const unsigned iseg, unsigned ids[2], void* context) +{ + struct context* ctx = context; + unsigned template_iseg, circ_idx, v_offset; + unsigned circ_seg_count, circ_vrtx_count; + ASSERT(ids && ctx); + /* Get circ_idx along with the template vertice index */ + circ_seg_count = (unsigned)sa_size(ctx->indices) / 2; + circ_vrtx_count = (unsigned)sa_size(ctx->positions) / 2; + ASSERT(iseg < NB_CIRC * circ_seg_count); + template_iseg = iseg % circ_seg_count; + circ_idx = iseg / circ_seg_count; + ASSERT(ctx->indices[template_iseg * 2 + 0] <= UINT_MAX + && ctx->indices[template_iseg * 2 + 1] <= UINT_MAX); + /* Compute the vertex index in the user numbering + * from circ_idx and template data; vertex related getters + * will have to get the template index back */ + v_offset = circ_idx * circ_vrtx_count; + ids[ctx->reverse_vrtx ? 1 : 0] + = v_offset + (unsigned)ctx->indices[template_iseg * 2 + 0]; + ids[ctx->reverse_vrtx ? 0 : 1] + = v_offset + (unsigned)ctx->indices[template_iseg * 2 + 1]; +} + +static void +get_ctx_position(const unsigned ivert, double pos[2], void* context) +{ + struct context* ctx = context; + unsigned ctx_ivert, circ_idx; + unsigned circ_seg_count, circ_vrtx_count; + int i, j, k; + double offset[2], tmp[2]; + double center_x, center_y, scale, misalignment = 0; + ASSERT(pos && ctx); (void)circ_vrtx_count; + /* Get circ_idx and circle imbrication along with the vertice index */ + circ_seg_count = (unsigned)sa_size(ctx->indices) / 2; + circ_vrtx_count = (unsigned)sa_size(ctx->positions) / 2; + ASSERT(ivert < NB_CIRC * circ_vrtx_count); + ctx_ivert = ivert % circ_seg_count; + circ_idx = ivert / circ_seg_count; + /* k th circle of the imbrication at grid position i,j */ + i = (int)circ_idx / (NB_CIRC_Y * NB_CIRC_Z); + j = (circ_idx / NB_CIRC_Z) % NB_CIRC_Y; + k = circ_idx % NB_CIRC_Z; + ASSERT(i < NB_CIRC_X && j < NB_CIRC_Y && k < NB_CIRC_Z); + ASSERT((unsigned)(i * NB_CIRC_Y * NB_CIRC_Z + j * NB_CIRC_Z + k) + * circ_vrtx_count + ctx_ivert == ivert); + center_x = 2 * (1 + NB_CIRC_Z) * (i - NB_CIRC_X / 2); + center_y = 2 * (1 + NB_CIRC_Z) * (j - NB_CIRC_Y / 2); + /* Compute scale and offset from imbrication */ + scale = k + 1; +#ifdef MITIGATE_EMBREE_181 + /* Mitigate Embree issue #181 + * We cannot keep perfect alignment of circles + * or some hits are missed */ + misalignment = (k % 2) ? -0.01 : +0.01; +#endif + d2(offset, center_x + misalignment, center_y + misalignment); + d2_add(pos, d2_muld(tmp, ctx->positions + ctx_ivert * 2, scale), + offset); +} + +static void +get_ctx_media(const unsigned iseg, unsigned medium[2], void* context) +{ + struct context* ctx = context; + unsigned circ_idx; + unsigned circ_seg_count; + int k; + ASSERT(medium && ctx); + /* Get circ_idx */ + circ_seg_count = (unsigned)sa_size(ctx->indices) / 2; + ASSERT(iseg < NB_CIRC * circ_seg_count); + circ_idx = iseg / circ_seg_count; + /* k th circle of the imbrication at some grid position */ + k = circ_idx % NB_CIRC_Z; + medium[ctx->reverse_med ? SENC2D_BACK : SENC2D_FRONT] = (unsigned)k; + medium[ctx->reverse_med ? SENC2D_FRONT : SENC2D_BACK] = (unsigned)(k + 1); +} + +#endif /* TEST_SENC2_UTILS2_H */