From f50046b31bc2b8c7ef36e21778cf5e889e945d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 20 May 2021 19:44:12 +0200 Subject: [PATCH 1/4] Modified streaming interface in miniz library to use ZIP64 extension only for files exciding the limits. The modification is based on a preallocation space in the Extra field using a phony custom block in the Local file header. This space is eventually overwritten by the ZIP64 extension if the file exceeds 4GiB. Also were fixed differences from PKZip specification in the streaming interface. --- src/miniz/miniz.c | 119 ++++++++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 51 deletions(-) diff --git a/src/miniz/miniz.c b/src/miniz/miniz.c index 08126f441..cff9aa5d3 100644 --- a/src/miniz/miniz.c +++ b/src/miniz/miniz.c @@ -5953,17 +5953,16 @@ static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) { - (void)pZip; memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, (pZip->m_pState->m_zip64) ? 0x002D : (method ? 0x0014 : 0x0000)); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX)); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX)); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, (pZip->m_pState->m_zip64 || comp_size > MZ_UINT32_MAX) ? MZ_UINT32_MAX : comp_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, (pZip->m_pState->m_zip64 || uncomp_size > MZ_UINT32_MAX) ? MZ_UINT32_MAX : uncomp_size); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); return MZ_TRUE; @@ -5975,10 +5974,12 @@ static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_ mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) { - (void)pZip; + mz_zip_internal_state *pState = pZip->m_pState; + mz_bool is_zip64_needed = uncomp_size >= MZ_UINT32_MAX || comp_size >= MZ_UINT32_MAX; memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_MADE_BY_OFS, is_zip64_needed ? 0x002D : (method ? 0x0014 : 0x0000)); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, is_zip64_needed ? 0x002D : (method ? 0x0014 : 0x0000)); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); @@ -6675,6 +6676,15 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA return MZ_TRUE; } +static mz_uint32 mz_zip_writer_preallocate_extra_data(mz_uint8 *pBuf, mz_uint32 extra_data_size) +{ + mz_uint8 *pDst = pBuf; + MZ_WRITE_LE16(pDst + 0, 0x9999); + MZ_WRITE_LE16(pDst + 2, extra_data_size); + memset(pDst + 4, 0, extra_data_size); + return 2 * sizeof(mz_uint16) + extra_data_size; +} + mz_bool mz_zip_writer_add_staged_open(mz_zip_archive* pZip, mz_zip_writer_staged_context* pContext, const char* pArchive_name, mz_uint64 max_size, const MZ_TIME_T* pFile_time, const void* pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char* user_extra_data, mz_uint user_extra_data_len, const char* user_extra_data_central, mz_uint user_extra_data_central_len) { @@ -6708,13 +6718,6 @@ mz_bool mz_zip_writer_add_staged_open(mz_zip_archive* pZip, mz_zip_writer_staged pState = pZip->m_pState; - if ((!pState->m_zip64) && (max_size > MZ_UINT32_MAX)) - { - /* Source file is too large for non-zip64 */ - /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ - pState->m_zip64 = MZ_TRUE; - } - /* We could support this, but why? */ if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); @@ -6778,55 +6781,45 @@ mz_bool mz_zip_writer_add_staged_open(mz_zip_archive* pZip, mz_zip_writer_staged MZ_ASSERT((pContext->cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } + if (!pState->m_zip64 && (pContext->local_dir_header_ofs >= MZ_UINT32_MAX)) { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ + } + MZ_CLEAR_OBJ(local_dir_header); if (pState->m_zip64) { - if (max_size >= MZ_UINT32_MAX || pContext->local_dir_header_ofs >= MZ_UINT32_MAX) - { - pContext->pExtra_data = pContext->extra_data; - pContext->extra_size = mz_zip_writer_create_zip64_extra_data(pContext->extra_data, (max_size >= MZ_UINT32_MAX) ? &pContext->uncomp_size : NULL, - (max_size >= MZ_UINT32_MAX) ? &pContext->comp_size : NULL, (pContext->local_dir_header_ofs >= MZ_UINT32_MAX) ? &pContext->local_dir_header_ofs : NULL); - } + pContext->pExtra_data = pContext->extra_data; + pContext->extra_size = mz_zip_writer_create_zip64_extra_data(pContext->extra_data, &pContext->uncomp_size, &pContext->comp_size, + (pContext->local_dir_header_ofs >= MZ_UINT32_MAX) ? &pContext->local_dir_header_ofs : NULL); + } + else if (!pState->m_zip64 && max_size > MZ_UINT32_MAX) + { + pContext->pExtra_data = pContext->extra_data; + pContext->extra_size = mz_zip_writer_preallocate_extra_data(pContext->extra_data, 2 * sizeof(mz_uint64)); + } - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)pContext->archive_name_size, (mz_uint16)(pContext->extra_size + user_extra_data_len), 0, 0, 0, pContext->method, pContext->gen_flags, pContext->dos_time, pContext->dos_date)) - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)pContext->archive_name_size, (mz_uint16)(pContext->extra_size + user_extra_data_len), 0, 0, 0, pContext->method, pContext->gen_flags, pContext->dos_time, pContext->dos_date)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - pContext->cur_archive_file_ofs += sizeof(local_dir_header); + pContext->cur_archive_file_ofs += sizeof(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, pArchive_name, pContext->archive_name_size) != pContext->archive_name_size) - { - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } + if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, pArchive_name, pContext->archive_name_size) != pContext->archive_name_size) + { + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } - pContext->cur_archive_file_ofs += pContext->archive_name_size; + pContext->cur_archive_file_ofs += pContext->archive_name_size; + if (pState->m_zip64 || max_size >= MZ_UINT32_MAX) { if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, pContext->extra_data, pContext->extra_size) != pContext->extra_size) return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); pContext->cur_archive_file_ofs += pContext->extra_size; } - else - { - if ((pContext->comp_size > MZ_UINT32_MAX) || (pContext->cur_archive_file_ofs > MZ_UINT32_MAX)) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)pContext->archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, pContext->method, pContext->gen_flags, pContext->dos_time, pContext->dos_date)) - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - pContext->cur_archive_file_ofs += sizeof(local_dir_header); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, pArchive_name, pContext->archive_name_size) != pContext->archive_name_size) - { - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - - pContext->cur_archive_file_ofs += pContext->archive_name_size; - } if (user_extra_data_len > 0) { @@ -6898,17 +6891,40 @@ mz_bool mz_zip_writer_add_staged_finish(mz_zip_writer_staged_context *pContext) pContext->pZip->m_pFree(pContext->pZip->m_pAlloc_opaque, pContext->pCompressor); pContext->pCompressor = NULL; + // Rewrite preallocated phony custom block in local dir header by ZIP64 extension. Also, other values are adjusted in the header. + if (pContext->file_ofs >= MZ_UINT32_MAX || pContext->add_state.m_comp_size >= MZ_UINT32_MAX) { + mz_uint64 local_dir_header_ofs = pContext->local_dir_header_ofs; + pContext->pExtra_data = pContext->extra_data; + pContext->extra_size = mz_zip_writer_create_zip64_extra_data(pContext->extra_data, &pContext->uncomp_size, &pContext->comp_size, (pContext->local_dir_header_ofs >= MZ_UINT32_MAX) ? &pContext->local_dir_header_ofs : NULL); + + mz_uint8 min_version[2] = {0x2D, 0x00}; + mz_uint8 comp_uncomp_size[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + if (pContext->pZip->m_pWrite(pContext->pZip->m_pIO_opaque, local_dir_header_ofs + MZ_ZIP_LDH_VERSION_NEEDED_OFS, min_version, sizeof(min_version)) != sizeof(min_version)) + return mz_zip_set_error(pContext->pZip, MZ_ZIP_FILE_WRITE_FAILED); + if (pContext->pZip->m_pWrite(pContext->pZip->m_pIO_opaque, local_dir_header_ofs + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_uncomp_size, sizeof(comp_uncomp_size)) != sizeof(comp_uncomp_size)) + return mz_zip_set_error(pContext->pZip, MZ_ZIP_FILE_WRITE_FAILED); + if (pContext->pZip->m_pWrite(pContext->pZip->m_pIO_opaque, local_dir_header_ofs + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, comp_uncomp_size, sizeof(comp_uncomp_size)) != sizeof(comp_uncomp_size)) + return mz_zip_set_error(pContext->pZip, MZ_ZIP_FILE_WRITE_FAILED); + if (pContext->pZip->m_pWrite(pContext->pZip->m_pIO_opaque, local_dir_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + pContext->archive_name_size, pContext->extra_data, pContext->extra_size) != pContext->extra_size) + return mz_zip_set_error(pContext->pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + pContext->uncomp_size = pContext->file_ofs; pContext->comp_size = pContext->add_state.m_comp_size; pContext->cur_archive_file_ofs = pContext->add_state.m_cur_archive_file_ofs; + // Clean pContext->pExtra_data, pContext->extra_data and pContext->extra_size after calling mz_zip_writer_add_staged_open + pContext->pExtra_data = NULL; + pContext->extra_size = 0; + memset(pContext->extra_data, 0, sizeof(mz_uint8) * MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE); + { mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64]; mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32; MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); MZ_WRITE_LE32(local_dir_footer + 4, pContext->uncomp_crc32); - if (pContext->pExtra_data == NULL) + if (pContext->uncomp_size < MZ_UINT32_MAX && pContext->comp_size < MZ_UINT32_MAX) { if (pContext->comp_size > MZ_UINT32_MAX) return mz_zip_set_error(pContext->pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); @@ -6929,10 +6945,11 @@ mz_bool mz_zip_writer_add_staged_finish(mz_zip_writer_staged_context *pContext) pContext->cur_archive_file_ofs += local_dir_footer_size; } - if (pContext->pExtra_data != NULL) + if (pContext->file_ofs >= MZ_UINT32_MAX || pContext->add_state.m_comp_size >= MZ_UINT32_MAX) { + pContext->pExtra_data = pContext->extra_data; pContext->extra_size = mz_zip_writer_create_zip64_extra_data(pContext->extra_data, (pContext->uncomp_size >= MZ_UINT32_MAX) ? &pContext->uncomp_size : NULL, - (pContext->uncomp_size >= MZ_UINT32_MAX) ? &pContext->comp_size : NULL, (pContext->local_dir_header_ofs >= MZ_UINT32_MAX) ? &pContext->local_dir_header_ofs : NULL); + (pContext->comp_size >= MZ_UINT32_MAX) ? &pContext->comp_size : NULL, (pContext->local_dir_header_ofs >= MZ_UINT32_MAX) ? &pContext->local_dir_header_ofs : NULL); } if (!mz_zip_writer_add_to_central_dir(pContext->pZip, pContext->pArchive_name, (mz_uint16)pContext->archive_name_size, pContext->pExtra_data, (mz_uint16)pContext->extra_size, pContext->pComment, pContext->comment_size, From ed9c93f85a8eafd27779cf49ab2406b8f791cd86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Fri, 21 May 2021 07:42:37 +0200 Subject: [PATCH 2/4] Added missing includes (GCC 9.3) --- src/libslic3r/TriangleMeshSlicer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libslic3r/TriangleMeshSlicer.cpp b/src/libslic3r/TriangleMeshSlicer.cpp index ea9eb5ff2..a3123ea76 100644 --- a/src/libslic3r/TriangleMeshSlicer.cpp +++ b/src/libslic3r/TriangleMeshSlicer.cpp @@ -23,6 +23,8 @@ #endif #include +#include +#include #if defined(SLIC3R_DEBUG) || defined(SLIC3R_DEBUG_SLICE_PROCESSING) #include "SVG.hpp" From 90be278d981d60faff8cb00a165687656fdcbfeb Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 21 May 2021 10:14:13 +0200 Subject: [PATCH 3/4] Attempt to fix unit test for 2D convex hull of sinking object on RasperryPi --- tests/libslic3r/test_3mf.cpp | 44 +++++++++++++++++------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/tests/libslic3r/test_3mf.cpp b/tests/libslic3r/test_3mf.cpp index d6d3686d9..c7c30daf6 100644 --- a/tests/libslic3r/test_3mf.cpp +++ b/tests/libslic3r/test_3mf.cpp @@ -30,23 +30,23 @@ SCENARIO("Export+Import geometry to/from 3mf file cycle", "[3mf]") { load_stl(src_file.c_str(), &src_model); src_model.add_default_instances(); - ModelObject* src_object = src_model.objects[0]; + ModelObject* src_object = src_model.objects.front(); // apply generic transformation to the 1st volume Geometry::Transformation src_volume_transform; - src_volume_transform.set_offset(Vec3d(10.0, 20.0, 0.0)); - src_volume_transform.set_rotation(Vec3d(Geometry::deg2rad(25.0), Geometry::deg2rad(35.0), Geometry::deg2rad(45.0))); - src_volume_transform.set_scaling_factor(Vec3d(1.1, 1.2, 1.3)); - src_volume_transform.set_mirror(Vec3d(-1.0, 1.0, -1.0)); - src_object->volumes[0]->set_transformation(src_volume_transform); + src_volume_transform.set_offset({ 10.0, 20.0, 0.0 }); + src_volume_transform.set_rotation({ Geometry::deg2rad(25.0), Geometry::deg2rad(35.0), Geometry::deg2rad(45.0) }); + src_volume_transform.set_scaling_factor({ 1.1, 1.2, 1.3 }); + src_volume_transform.set_mirror({ -1.0, 1.0, -1.0 }); + src_object->volumes.front()->set_transformation(src_volume_transform); // apply generic transformation to the 1st instance Geometry::Transformation src_instance_transform; - src_instance_transform.set_offset(Vec3d(5.0, 10.0, 0.0)); - src_instance_transform.set_rotation(Vec3d(Geometry::deg2rad(12.0), Geometry::deg2rad(13.0), Geometry::deg2rad(14.0))); - src_instance_transform.set_scaling_factor(Vec3d(0.9, 0.8, 0.7)); - src_instance_transform.set_mirror(Vec3d(1.0, -1.0, -1.0)); - src_object->instances[0]->set_transformation(src_instance_transform); + src_instance_transform.set_offset({ 5.0, 10.0, 0.0 }); + src_instance_transform.set_rotation({ Geometry::deg2rad(12.0), Geometry::deg2rad(13.0), Geometry::deg2rad(14.0) }); + src_instance_transform.set_scaling_factor({ 0.9, 0.8, 0.7 }); + src_instance_transform.set_mirror({ 1.0, -1.0, -1.0 }); + src_object->instances.front()->set_transformation(src_instance_transform); WHEN("model is saved+loaded to/from 3mf file") { // save the model to 3mf file @@ -67,16 +67,9 @@ SCENARIO("Export+Import geometry to/from 3mf file cycle", "[3mf]") { dst_mesh.repair(); bool res = src_mesh.its.vertices.size() == dst_mesh.its.vertices.size(); - if (res) - { - for (size_t i = 0; i < dst_mesh.its.vertices.size(); ++i) - { + if (res) { + for (size_t i = 0; i < dst_mesh.its.vertices.size(); ++i) { res &= dst_mesh.its.vertices[i].isApprox(src_mesh.its.vertices[i]); - if (!res) - { - Vec3f diff = dst_mesh.its.vertices[i] - src_mesh.its.vertices[i]; - std::cout << i << ": diff " << to_string((Vec3d)diff.cast()) << "\n"; - } } } THEN("world vertices coordinates after load match") { @@ -95,11 +88,11 @@ SCENARIO("2D convex hull of sinking object", "[3mf]") { model.add_default_instances(); WHEN("model is rotated, scaled and set as sinking") { - ModelObject* object = model.objects[0]; + ModelObject* object = model.objects.front(); object->center_around_origin(false); // set instance's attitude so that it is rotated, scaled and sinking - ModelInstance* instance = object->instances[0]; + ModelInstance* instance = object->instances.front(); instance->set_rotation(Y, -M_PI / 4.0); instance->set_offset(Vec3d::Zero()); instance->set_scaling_factor({ 2.0, 2.0, 2.0 }); @@ -116,7 +109,12 @@ SCENARIO("2D convex hull of sinking object", "[3mf]") { { -4244, 19502998 }, { -4242640, -8537523 } }; - bool res = hull_2d.points == result; + bool res = hull_2d.points.size() == result.size(); + if (res) { + for (size_t i = 0; i < hull_2d.points.size(); ++i) { + res &= hull_2d.points[i].isApprox(result[i]); + } + } THEN("2D convex hull should match with reference") { REQUIRE(res); From 49f29e835334d0033771d25ff341c06b1b564b9b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 21 May 2021 11:56:10 +0200 Subject: [PATCH 4/4] Added debug output to help fixing unit test for 2D convex hull of sinking object on RasperryPi --- tests/libslic3r/test_3mf.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/libslic3r/test_3mf.cpp b/tests/libslic3r/test_3mf.cpp index c7c30daf6..e865b1d78 100644 --- a/tests/libslic3r/test_3mf.cpp +++ b/tests/libslic3r/test_3mf.cpp @@ -109,11 +109,13 @@ SCENARIO("2D convex hull of sinking object", "[3mf]") { { -4244, 19502998 }, { -4242640, -8537523 } }; - bool res = hull_2d.points.size() == result.size(); - if (res) { - for (size_t i = 0; i < hull_2d.points.size(); ++i) { - res &= hull_2d.points[i].isApprox(result[i]); - } + + bool res = hull_2d.points == result; + + std::cout << "hull_2d vertices count: " << hull_2d.points.size() << "\n"; + std::cout << "hull_2d vertices:\n"; + for (size_t i = 0; i < hull_2d.points.size(); ++i) { + std::cout << hull_2d.points[i].x() << ", " << hull_2d.points[i].y() << "\n"; } THEN("2D convex hull should match with reference") {