diff --git a/freetype263/src/gzip/zconf.h b/freetype263/src/gzip/zconf.h index 3abf0ba0..68f7f283 100644 --- a/freetype263/src/gzip/zconf.h +++ b/freetype263/src/gzip/zconf.h @@ -215,9 +215,9 @@ # define FAR #endif -#if !defined(MACOS) && !defined(TARGET_OS_MAC) +//#if !defined(MACOS) && !defined(TARGET_OS_MAC) typedef unsigned char Byte; /* 8 bits */ -#endif +//#endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ diff --git a/opennurbs_archive.h b/opennurbs_archive.h index 9ef909e7..197117aa 100644 --- a/opennurbs_archive.h +++ b/opennurbs_archive.h @@ -1894,6 +1894,12 @@ public: class ON_CLASS ON_BinaryArchive // use for generic serialization of binary data { public: + /* + * You might want to initialize this class before using it + * by calling SetArchive3dmVersion with + * ON_BinaryArchive::CurrentArchiveVersion() and + * SetOpenNURBS3dmVersion with ON::Version(). + */ ON_BinaryArchive( ON::archive_mode ); virtual ~ON_BinaryArchive(); diff --git a/opennurbs_array.cpp b/opennurbs_array.cpp index 81cc69c4..8017d342 100644 --- a/opennurbs_array.cpp +++ b/opennurbs_array.cpp @@ -13,6 +13,8 @@ #include "opennurbs.h" +#include + #if !defined(ON_COMPILING_OPENNURBS) // This check is included in all opennurbs source .c and .cpp files to insure // ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled. @@ -1187,6 +1189,282 @@ ON_UuidPtr* ON_UuidPtrList::SearchHelper(const ON_UUID* uuid) const return p; } +static_assert(sizeof(ON_UuidPairList) == sizeof(ON_UuidPairList2), "ON_UuidPairList and ON_UuidPairList2 are not the same size"); +static_assert(sizeof(ON_UuidPtrList) == sizeof(ON_UuidPtrList2), "ON_UuidPtrList and ON_UuidPtrList2 are not the same size"); +static_assert(sizeof(ON_UuidIndexList) == sizeof(ON_UuidIndexList2), "ON_UuidIndexList and ON_UuidIndexList2 are not the same size"); + +template +struct ON_UuidList2_Private +{ + struct UuidHasher + { + inline size_t operator()(const ON_UUID& uuid) const + { + // We have to copy two 32-bit words into a 64-bit word. Just casting to size_t can cause + // a problem on Mac because size_t is required to be aligned on an 8-byte boundary and UUID + // is only aligned on a 4-byte boundary. + const ON__UINT32* d = reinterpret_cast(&uuid.Data1); + return (size_t(d[0]) << 32) | size_t(d[1]); + } + }; + + std::unordered_map map; +}; + +class ON_UuidPtrList2_Private : public ON_UuidList2_Private{}; +class ON_UuidPairList2_Private : public ON_UuidList2_Private {}; +class ON_UuidIndexList2_Private : public ON_UuidList2_Private {}; + +ON_UuidPtrList2::ON_UuidPtrList2() : m_private(new ON_UuidPtrList2_Private) {} +ON_UuidPairList2::ON_UuidPairList2() : m_private(new ON_UuidPairList2_Private) {} +ON_UuidIndexList2::ON_UuidIndexList2() : m_private(new ON_UuidIndexList2_Private) {} + +ON_UuidPtrList2::~ON_UuidPtrList2() = default; +ON_UuidPairList2::~ON_UuidPairList2() = default; +ON_UuidIndexList2::~ON_UuidIndexList2() = default; + +ON_UuidPtrList2::ON_UuidPtrList2(const ON_UuidPtrList2& src) { *this = src; } +ON_UuidPairList2::ON_UuidPairList2(const ON_UuidPairList2& src) { *this = src;} +ON_UuidIndexList2::ON_UuidIndexList2(const ON_UuidIndexList2& src) { *this = src; } + +ON_UuidPtrList2& ON_UuidPtrList2::operator=(const ON_UuidPtrList2& src) +{ + if (this != &src) + { + m_private.reset(new ON_UuidPtrList2_Private(*src.m_private)); + } + return *this; +} + +ON_UuidPairList2& ON_UuidPairList2::operator=(const ON_UuidPairList2& src) +{ + if (this != &src) + { + m_private.reset(new ON_UuidPairList2_Private(*src.m_private)); + } + return *this; +} + +ON_UuidIndexList2& ON_UuidIndexList2::operator=(const ON_UuidIndexList2& src) +{ + if (this != &src) + { + m_private.reset(new ON_UuidIndexList2_Private(*src.m_private)); + } + return *this; +} + + +bool ON_UuidPtrList2::AddUuidPtr(const ON_UUID& uuid, ON__UINT_PTR ptr) +{ + return m_private->map.insert(std::make_pair(uuid, ptr)).second; +} + +bool ON_UuidPairList2::AddPair(const ON_UUID& id1, const ON_UUID& id2) +{ + return m_private->map.insert(std::make_pair(id1, id2)).second; +} + +bool ON_UuidIndexList2::AddUuidIndex(const ON_UUID& uuid, int index) +{ + return m_private->map.insert(std::make_pair(uuid, index)).second; +} + +unsigned int ON_UuidPtrList2::Count() const +{ + return (int)m_private->map.size(); +} + +unsigned int ON_UuidPairList2::Count() const +{ + return (int)m_private->map.size(); +} + +unsigned int ON_UuidIndexList2::Count() const +{ + return (int)m_private->map.size(); +} + +void ON_UuidPairList2::Empty() +{ + m_private->map.clear(); +} + +void ON_UuidPtrList2::RemoveAll() +{ + m_private->map.clear(); +} + +void ON_UuidIndexList2::RemoveAll() +{ + m_private->map.clear(); +} + +void ON_UuidPtrList2::Reserve(size_t capacity){} +void ON_UuidPairList2::Reserve(size_t capacity) {} +void ON_UuidIndexList2::Reserve(size_t capacity) {} + +bool ON_UuidPtrList2::RemoveUuid(const ON_UUID& id1) +{ + return 1 == m_private->map.erase(id1); +} + +bool ON_UuidIndexList2::RemoveUuid(const ON_UUID& id1) +{ + return 1 == m_private->map.erase(id1); +} + +bool ON_UuidPairList2::RemovePair(const ON_UUID& id1) +{ + return 1 == m_private->map.erase(id1); +} + +bool ON_UuidPairList2::RemovePair(const ON_UUID& id1, const ON_UUID& id2) +{ + const auto it = m_private->map.find(id1); + if (it != m_private->map.end() && it->second == id2) + { + return RemovePair(id1); + } + return false; +} + +bool ON_UuidPtrList2::FindUuid(const ON_UUID& uuid) const +{ + return FindUuid(uuid, nullptr); +} + +bool ON_UuidIndexList2::FindUuid(const ON_UUID& uuid) const +{ + return FindUuid(uuid, nullptr); +} + +bool ON_UuidPtrList2::FindUuid(const ON_UUID& uuid, ON__UINT_PTR* index) const +{ + const auto it = m_private->map.find(uuid); + + if (it != m_private->map.end()) + { + if (index) + { + *index = it->second; + } + return true; + } + return false; +} + +bool ON_UuidPairList2::FindId1(const ON_UUID& id1, ON_UUID* id2) const +{ + const auto it = m_private->map.find(id1); + + if (it != m_private->map.end()) + { + if (id2) + { + *id2 = it->second; + } + return true; + } + return false; +} + +bool ON_UuidIndexList2::FindUuid(const ON_UUID& uuid, int* index) const +{ + const auto it = m_private->map.find(uuid); + + if (it != m_private->map.end()) + { + if (index) + { + *index = it->second; + } + return true; + } + return false; +} + +bool ON_UuidPtrList2::FindUuidPtr(const ON_UUID& uuid, ON__UINT_PTR ptr) const +{ + const auto it = m_private->map.find(uuid); + + return it != m_private->map.end() && it->second == ptr; +} + +bool ON_UuidIndexList2::FindUuidIndex(const ON_UUID& uuid, int ptr) const +{ + const auto it = m_private->map.find(uuid); + + return it != m_private->map.end() && it->second == ptr; +} + +bool ON_UuidPairList2::FindPair(const ON_UUID& id1, const ON_UUID& id2) const +{ + const auto it = m_private->map.find(id1); + + return it != m_private->map.end() && it->second == id2; +} + +unsigned int ON_UuidPtrList2::GetUuids(ON_SimpleArray& uuid_list) const +{ + uuid_list.Reserve(Count()); + + int i = 0; + for (const auto& pair : m_private->map) + { + uuid_list.Append(pair.first); + i++; + } + return i; +} + +int ON_UuidPairList2::GetId1s(ON_SimpleArray& uuid_list) const +{ + uuid_list.Reserve(Count()); + + int i = 0; + for (const auto& pair : m_private->map) + { + uuid_list.Append(pair.first); + i++; + } + return i; +} + +unsigned int ON_UuidIndexList2::GetUuids(ON_SimpleArray& uuid_list) const +{ + uuid_list.Reserve(Count()); + + int i = 0; + for (const auto& pair : m_private->map) + { + uuid_list.Append(pair.first); + i++; + } + return i; +} + +void ON_UuidPairList2::ImproveSearchSpeed() {} +void ON_UuidPtrList2::ImproveSearchSpeed() {} +void ON_UuidIndexList2::ImproveSearchSpeed() {} + + + + + + + + + + + + + + + + + + ON_UuidPairList::ON_UuidPairList() @@ -1832,3 +2110,38 @@ bool ON_2dexMap::RemoveIndex( int i ) return (0 != e); } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opennurbs_array.h b/opennurbs_array.h index 37725090..46053ece 100644 --- a/opennurbs_array.h +++ b/opennurbs_array.h @@ -1154,6 +1154,11 @@ private: }; + + + + + /* Description: The ON_UuidList class provides a tool @@ -1277,6 +1282,109 @@ private: }; +class ON_CLASS ON_UuidPtrList2 +{ +public: + ON_UuidPtrList2(); + ~ON_UuidPtrList2(); + ON_UuidPtrList2(const ON_UuidPtrList2& src); + ON_UuidPtrList2& operator=(const ON_UuidPtrList2& src); + + unsigned int Count() const; + void RemoveAll(); + void Reserve(size_t capacity); + bool AddUuidPtr(const ON_UUID& uuid, ON__UINT_PTR ptr); + bool RemoveUuid(const ON_UUID& uuid); + bool FindUuid(const ON_UUID& uuid) const; + bool FindUuid(const ON_UUID& uuid, ON__UINT_PTR* ptr) const; + bool FindUuidPtr(const ON_UUID& uuid, ON__UINT_PTR index) const; + unsigned int GetUuids(ON_SimpleArray& uuid_list) const; + void ImproveSearchSpeed(); + +private: +#pragma warning (push) +#pragma warning (disable : 4251) + std::unique_ptr m_private; + unsigned int padding[2]; +#if defined (ON_RUNTIME_ANDROID) //Android has 32-bit pointers? + unsigned char padding_array[12]; +#else + unsigned char padding_array[16]; +#endif +#pragma warning (pop) +}; + +class ON_CLASS ON_UuidPairList2 +{ +public: + ON_UuidPairList2(); + ~ON_UuidPairList2(); + ON_UuidPairList2(const ON_UuidPairList2& src); + ON_UuidPairList2& operator=(const ON_UuidPairList2& src); + + static const ON_UuidPairList2 EmptyList; + + unsigned int Count() const; + void Empty(); + void Reserve(size_t capacity); + bool AddPair(const ON_UUID& id1, const ON_UUID& id2); + bool RemovePair(const ON_UUID& id1); + bool RemovePair(const ON_UUID& id1, const ON_UUID& id2); + bool FindId1(const ON_UUID& id1, ON_UUID* id2 = 0) const; + bool FindPair(const ON_UUID& id1, const ON_UUID& id2) const; + int GetId1s(ON_SimpleArray& uuid_list) const; + + void ImproveSearchSpeed(); + +private: +#pragma warning (push) +#pragma warning (disable : 4251) + std::unique_ptr m_private; + unsigned int padding[2]; +#if defined (ON_RUNTIME_ANDROID) //Android has 32-bit pointers? + unsigned char padding_array[12]; +#else + unsigned char padding_array[16]; +#endif +#pragma warning (pop) +}; + +class ON_CLASS ON_UuidIndexList2 +{ +public: + ON_UuidIndexList2(); + ~ON_UuidIndexList2(); + ON_UuidIndexList2(const ON_UuidIndexList2& src); + ON_UuidIndexList2& operator=(const ON_UuidIndexList2& src); + + unsigned int Count() const; + void RemoveAll(); + void Reserve(size_t capacity); + bool AddUuidIndex(const ON_UUID& uuid, int index); + bool RemoveUuid(const ON_UUID& uuid); + bool FindUuid(const ON_UUID& uuid) const; + bool FindUuid(const ON_UUID& uuid, int* index) const; + bool FindUuidIndex(const ON_UUID& uuid, int index) const; + unsigned int GetUuids(ON_SimpleArray& uuid_list) const; + void ImproveSearchSpeed(); + +private: +#pragma warning (push) +#pragma warning (disable : 4251) + std::unique_ptr m_private; + unsigned int padding[2]; +#if defined (ON_RUNTIME_ANDROID) //Android has 32-bit pointers? + unsigned char padding_array[12]; +#else + unsigned char padding_array[16]; +#endif +#pragma warning (pop) +}; + + + + + /* Description: The ON_UuidPairList class provides a tool @@ -1426,6 +1534,9 @@ private: unsigned int m_removed_count; }; + + + class ON_CLASS ON_2dexMap : private ON_SimpleArray { public: diff --git a/opennurbs_file_utilities.cpp b/opennurbs_file_utilities.cpp index d11ba5ec..3ca4c3da 100644 --- a/opennurbs_file_utilities.cpp +++ b/opennurbs_file_utilities.cpp @@ -4104,10 +4104,11 @@ void ON_FileReference::SetFullPath( else if (bFullPathChanged) { m_content_hash = ON_ContentHash::Unset; - m_full_path_status - = ON_FileSystem::IsFile(m_full_path) - ? ON_FileReference::Status::FullPathValid - : ON_FileReference::Status::FileNotFound; + + //https://mcneel.myjetbrains.com/youtrack/issue/RH-85181 + //This used to check whether the file was there, eagerly, but this can be a big performance hit, especially on Google Drive. + //And the accessor for this property is basically never called. + m_full_path_status = ON_FileReference::Status::Unknown; } } } diff --git a/opennurbs_instance.cpp b/opennurbs_instance.cpp index 3e1b37b3..7030c91a 100644 --- a/opennurbs_instance.cpp +++ b/opennurbs_instance.cpp @@ -226,7 +226,7 @@ private: // and used in BeforeLinkedDefinitionWriteImpl(). // It has no other use and is not saved in files because the // 2nd id is a runtime value that can change every time a file is read. - ON_UuidPairList m_runtime_layer_id_map; + ON_UuidPairList2 m_runtime_layer_id_map; private: static void InternalDestroyLayerArray( diff --git a/opennurbs_material.cpp b/opennurbs_material.cpp index 009281a0..1c111dc3 100644 --- a/opennurbs_material.cpp +++ b/opennurbs_material.cpp @@ -249,6 +249,9 @@ bool ON_Material::Read( ON_BinaryArchive& archive ) if ( !archive.ReadColor( m_reflection ) ) break; if ( !archive.ReadColor( m_transparent ) ) break; + //https://mcneel.myjetbrains.com/youtrack/issue/RH-85216/ONMaterial-diffuse-color-is-ONColorUnsetColor + RemoveColorAlphaValues(); + if ( !archive.ReadDouble( &m_index_of_refraction ) ) break; if ( !archive.ReadDouble( &m_reflectivity ) ) break; if ( !archive.ReadDouble( &m_shine ) ) break; @@ -8833,6 +8836,25 @@ ON_UUID ON_Material::PhysicallyBasedUserdataId(void) return id; } + +static int OnlyRGB(const ON_Color& c) +{ + const int col = (int)(unsigned int)c; + + return col & 0x00FFFFFF; +} + +void ON_Material::RemoveColorAlphaValues(void) +{ + m_ambient = OnlyRGB(m_ambient); + m_diffuse = OnlyRGB(m_diffuse); + m_emission = OnlyRGB(m_emission); + m_specular = OnlyRGB(m_specular); + m_reflection = OnlyRGB(m_reflection); + m_transparent = OnlyRGB(m_transparent); + +} + ON_OBJECT_IMPLEMENT(ON_PhysicallyBasedMaterialUserData, ON_UserData, "5694E1AC-40E6-44F4-9CA9-3B6D0E8C4440"); class ON_PhysicallyBasedMaterial::Impl diff --git a/opennurbs_material.h b/opennurbs_material.h index 84d9bdc8..20993a67 100644 --- a/opennurbs_material.h +++ b/opennurbs_material.h @@ -307,6 +307,11 @@ public: ON_Color m_reflection = ON_Color::White; ON_Color m_transparent = ON_Color::White; + //The values all of the colors above do not support alpha values, and Rhino will not work correctly + //if there is a value other than 0 in that fourth byte. This function cleans this up. + //https://mcneel.myjetbrains.com/youtrack/issue/RH-85216/ONMaterial-diffuse-color-is-ONColorUnsetColor + void RemoveColorAlphaValues(void); + private: bool m_bShareable = false; diff --git a/opennurbs_public_version.h b/opennurbs_public_version.h index 5ad423ef..cbdd0060 100644 --- a/opennurbs_public_version.h +++ b/opennurbs_public_version.h @@ -6,7 +6,7 @@ // To update version numbers, edit ..\build\build_dates.msbuild #define RMA_VERSION_MAJOR 8 -#define RMA_VERSION_MINOR 15 +#define RMA_VERSION_MINOR 16 //////////////////////////////////////////////////////////////// // @@ -14,8 +14,8 @@ // first step in each build. // #define RMA_VERSION_YEAR 2025 -#define RMA_VERSION_MONTH 1 -#define RMA_VERSION_DATE 19 +#define RMA_VERSION_MONTH 2 +#define RMA_VERSION_DATE 11 #define RMA_VERSION_HOUR 13 #define RMA_VERSION_MINUTE 0 @@ -35,8 +35,8 @@ // 3 = build system release build #define RMA_VERSION_BRANCH 0 -#define VERSION_WITH_COMMAS 8,15,25019,13000 -#define VERSION_WITH_PERIODS 8.15.25019.13000 +#define VERSION_WITH_COMMAS 8,16,25042,13000 +#define VERSION_WITH_PERIODS 8.16.25042.13000 #define COPYRIGHT "Copyright (C) 1993-2025, Robert McNeel & Associates. All Rights Reserved." #define SPECIAL_BUILD_DESCRIPTION "Public OpenNURBS C++ 3dm file IO library." @@ -44,11 +44,11 @@ #define RMA_VERSION_NUMBER_MAJOR_WSTRING L"8" #define RMA_PREVIOUS_VERSION_NUMBER_MAJOR_WSTRING L"7" -#define RMA_VERSION_NUMBER_SR_STRING "SR15" -#define RMA_VERSION_NUMBER_SR_WSTRING L"SR15" +#define RMA_VERSION_NUMBER_SR_STRING "SR16" +#define RMA_VERSION_NUMBER_SR_WSTRING L"SR16" -#define RMA_VERSION_WITH_PERIODS_STRING "8.15.25019.13000" -#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.15.25019.13000" +#define RMA_VERSION_WITH_PERIODS_STRING "8.16.25042.13000" +#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.16.25042.13000" diff --git a/opennurbs_statics.cpp b/opennurbs_statics.cpp index cd048a59..25e8a1ee 100644 --- a/opennurbs_statics.cpp +++ b/opennurbs_statics.cpp @@ -588,6 +588,7 @@ const ON_UUID ON_opennurbs8_id = { 0x50ede5c9, 0x1487, 0x4b4c, { 0xb3, 0xaa, 0x6 const ON_UUID ON_opennurbs_id = ON_opennurbs8_id; const ON_UuidPairList ON_UuidPairList::EmptyList; +const ON_UuidPairList2 ON_UuidPairList2::EmptyList; const ON_COMPONENT_INDEX ON_COMPONENT_INDEX::UnsetComponentIndex; const ON_COMPONENT_INDEX ON_COMPONENT_INDEX::WholeObject; diff --git a/opennurbs_subd.cpp b/opennurbs_subd.cpp index 7c83bdb1..196083f5 100644 --- a/opennurbs_subd.cpp +++ b/opennurbs_subd.cpp @@ -3034,9 +3034,15 @@ const ON_SubDComponentPoint ON_SubDComponentPoint::BestPickPoint( // type_bias = -1 if B is a vertex and A is an edge/face or B is an edge and A is a face. const int type_bias = (ON_SubDComponentPtr::CompareComponentPtrType(A_component_type, B_component_type)) <= 0 ? 1 : -1; + // 17 Dec 2024, Mikko, RH-85024: + // Skip the following section if either component is a face. + // In that case it gives the wrong answer if you click on an opaque shaded SubD face, + // and at the same time hit an edge/vertex of the same face behind the shaded part. if ( ON_PickType::PointPick == pick_type && ((type_bias >= 0) ? Internal_FirstIsPartOfSecond(A, B) : Internal_FirstIsPartOfSecond(B, A)) + && ON_SubDComponentPtr::Type::Face != A_component_type + && ON_SubDComponentPtr::Type::Face != B_component_type ) { // A point pick is occurring and best is a vertex on an edge/face or best is an edge on a face. diff --git a/opennurbs_subd_archive.cpp b/opennurbs_subd_archive.cpp index 9f3ea9a1..5595509a 100644 --- a/opennurbs_subd_archive.cpp +++ b/opennurbs_subd_archive.cpp @@ -357,73 +357,84 @@ static bool ReadBase( return ON_SUBD_RETURN_ERROR(false); } -static bool Internal_WriteSavedLimitPointList( - unsigned int vertex_face_count, - bool bHaveLimitPoint, - const ON_SubDSectorSurfacePoint& limit_point, - ON_BinaryArchive& archive - ) -{ - unsigned int limit_point_count = 0; - const ON_SubDSectorSurfacePoint* p; +// Dale Lear 2024-12-18 Rhino 8.x +// Due to a bug in v7, the saved limit points were read but nuever used. +// So I'm simply not writing the limit points anymore. +//static bool Internal_WriteSavedLimitPointList( +// unsigned int vertex_face_count, +// bool bHaveLimitPoint, +// const ON_SubDSectorSurfacePoint& limit_point, +// ON_BinaryArchive& archive +// ) +//{ +// unsigned int limit_point_count = 0; +// const ON_SubDSectorSurfacePoint* p; +// +// if (bHaveLimitPoint) +// { +// for (p = &limit_point; nullptr != p && limit_point_count <= vertex_face_count; p = p->m_next_sector_limit_point) +// { +// if (!ON_IsValid(p->m_limitP[0])) +// break; +// if (limit_point_count > 0 && nullptr == p->m_sector_face) +// break; +// limit_point_count++; +// } +// if (limit_point_count > vertex_face_count || nullptr != p) +// limit_point_count = 0; +// +// if (limit_point_count > vertex_face_count) +// limit_point_count = 0; +// } +// if (0 == limit_point_count) +// bHaveLimitPoint = false; +// +// for (;;) +// { +// unsigned char c = bHaveLimitPoint ? 4 : 0; +// if (!archive.WriteChar(c)) +// break; +// +// if (0 == c) +// return true; +// +// if (!archive.WriteInt(limit_point_count)) +// break; +// +// p = &limit_point; +// for (unsigned int i = 0; i < limit_point_count; i++, p = p->m_next_sector_limit_point ) +// { +// if (!Internal_WriteDouble3(limit_point.m_limitP, archive)) +// break; +// if (!Internal_WriteDouble3(limit_point.m_limitT1, archive)) +// break; +// if (!Internal_WriteDouble3(limit_point.m_limitT2, archive)) +// break; +// if (!Internal_WriteDouble3(limit_point.m_limitN, archive)) +// break; +// if (!Internal_WriteArchiveIdAndFlags(limit_point.m_sector_face ? limit_point.m_sector_face->ArchiveId() : 0, 0, archive)) +// break; +// } +// return true; +// } +// return ON_SUBD_RETURN_ERROR(false); +//} - if (bHaveLimitPoint) - { - for (p = &limit_point; nullptr != p && limit_point_count <= vertex_face_count; p = p->m_next_sector_limit_point) - { - if (!ON_IsValid(p->m_limitP[0])) - break; - if (limit_point_count > 0 && nullptr == p->m_sector_face) - break; - limit_point_count++; - } - if (limit_point_count > vertex_face_count || nullptr != p) - limit_point_count = 0; - - if (limit_point_count > vertex_face_count) - limit_point_count = 0; - } - if (0 == limit_point_count) - bHaveLimitPoint = false; - - for (;;) - { - unsigned char c = bHaveLimitPoint ? 4 : 0; - if (!archive.WriteChar(c)) - break; - - if (0 == c) - return true; - - if (!archive.WriteInt(limit_point_count)) - break; - - p = &limit_point; - for (unsigned int i = 0; i < limit_point_count; i++, p = p->m_next_sector_limit_point ) - { - if (!Internal_WriteDouble3(limit_point.m_limitP, archive)) - break; - if (!Internal_WriteDouble3(limit_point.m_limitT1, archive)) - break; - if (!Internal_WriteDouble3(limit_point.m_limitT2, archive)) - break; - if (!Internal_WriteDouble3(limit_point.m_limitN, archive)) - break; - if (!Internal_WriteArchiveIdAndFlags(limit_point.m_sector_face ? limit_point.m_sector_face->ArchiveId() : 0, 0, archive)) - break; - } - return true; - } - return ON_SUBD_RETURN_ERROR(false); -} - -static bool Internal_ReadSavedLimitPointList( +// Dale Lear 2024-12-18 Rhino 8.x +// Due to a bug (missing & limit_points so the array was by value rather than by reference) +// on that's been in this code since v7, the saved +// limit points were read but never used. +// This function reads and discards the information that was never used +// but which exists in millions of older 3dm files. +// It appears recalculating the limit point information has been fast enough +// for many years, so I'm making it clear that this is legacy code. +static bool Internal_IgnoreSavedLimitPointList( ON_BinaryArchive& archive, - unsigned int vertex_face_count, - ON_SimpleArray< ON_SubDSectorSurfacePoint > limit_points + unsigned int vertex_face_count + //ON_SimpleArray< ON_SubDSectorSurfacePoint > limit_points // NOTE MISSING & means this array was by value and not by reference ) { - limit_points.SetCount(0); + //limit_points.SetCount(0); for (;;) { @@ -444,9 +455,9 @@ static bool Internal_ReadSavedLimitPointList( if (limit_point_count > vertex_face_count) break; - limit_points.Reserve(limit_point_count); - - for ( unsigned int i = 0; i < limit_point_count; i++ ) + //limit_points.Reserve(limit_point_count); + unsigned int i = 0; + for ( /*empty init*/; i < limit_point_count; i++) { ON_SubDSectorSurfacePoint limit_point = ON_SubDSectorSurfacePoint::Unset; if (!Internal_ReadDouble3(archive,limit_point.m_limitP)) @@ -460,14 +471,14 @@ static bool Internal_ReadSavedLimitPointList( ON_SubDFacePtr fptr = ON_SubDFacePtr::Null; if (!Internal_ReadArchiveIdAndFlagsIntoComponentPtr(archive,fptr.m_ptr)) break; - limit_points.Append(limit_point); + //limit_points.Append(limit_point); } - if (limit_point_count != limit_points.UnsignedCount() ) + if (limit_point_count != i ) break; - if (4 != c) - limit_points.SetCount(0); + //if (4 != c) + // limit_points.SetCount(0); return true; } @@ -727,8 +738,19 @@ bool ON_SubDVertex::Write( break; if (!archive.WriteShort(m_face_count)) break; - if (!Internal_WriteSavedLimitPointList(m_face_count, this->SurfacePointIsSet(), m_limit_point, archive)) + + // Dale Lear 2024-12-18 + // Due to a bug in ON_SubDVertex::Read(), the limit points written + // by Internal_WriteSavedLimitPointList() were read but never used. + // It appears that recalculating the limit points every time the + // file is read is working out just fine. So writing a zero byte + // here means that old code will be able to read new files and + // we wont' waste time and disk space saving limit points. + if (!archive.WriteChar((unsigned char)0)) break; + //if (!Internal_WriteSavedLimitPointList(m_face_count, this->SurfacePointIsSet(), m_limit_point, archive)) + // break; + if (!Internal_WriteEdgePtrList(m_edge_count,m_edge_capacity,m_edges,0,nullptr, archive)) break; if (!Internal_WriteFacePtrList(m_face_count,m_face_capacity,(const ON_SubDFacePtr*)m_faces,0,nullptr, archive)) @@ -770,7 +792,7 @@ bool ON_SubDVertex::Read( unsigned short edge_count = 0; unsigned short face_count = 0; - ON_SimpleArray limit_points; + //ON_SimpleArray limit_points; if (!ReadBase(archive,base)) break; @@ -783,7 +805,7 @@ bool ON_SubDVertex::Read( if (!archive.ReadShort(&face_count)) break; - if (!Internal_ReadSavedLimitPointList(archive, face_count, limit_points)) + if (!Internal_IgnoreSavedLimitPointList(archive, face_count)) break; ON_SubDVertex* v = subdimple->AllocateVertex( @@ -808,16 +830,16 @@ bool ON_SubDVertex::Read( break; v->m_face_count = face_count; - for (unsigned int i = 0; i < limit_points.UnsignedCount(); i++) - { - ON_SubDSectorSurfacePoint limit_point = limit_points[i]; - limit_point.m_next_sector_limit_point = (const ON_SubDSectorSurfacePoint*)1U; // skips checks - if (false == v->SetSavedSurfacePoint( true, limit_point)) - { - v->ClearSavedSurfacePoints(); - break; - } - } + //for (unsigned int i = 0; i < limit_points.UnsignedCount(); i++) + //{ + // ON_SubDSectorSurfacePoint limit_point = limit_points[i]; + // limit_point.m_next_sector_limit_point = (const ON_SubDSectorSurfacePoint*)1U; // skips checks + // if (false == v->SetSavedSurfacePoint( true, limit_point)) + // { + // v->ClearSavedSurfacePoints(); + // break; + // } + //} vertex = v; diff --git a/opennurbs_subd_copy.cpp b/opennurbs_subd_copy.cpp index e0cd05d6..014df9a0 100644 --- a/opennurbs_subd_copy.cpp +++ b/opennurbs_subd_copy.cpp @@ -560,38 +560,38 @@ bool ON_SubDArchiveIdMap::AddComponentPtr(ON_SubDComponentPtr eptr, unsigned int ON_SubDComponentPtr* p = (ON_SubDComponentPtr*)m_fsp.AllocateElement(); *p = eptr; -#if defined(ON_DEBUG) - if (0 != archive_id) - { - const ON_SubDComponentPtr* p1 = (const ON_SubDComponentPtr*)m_fsp.Element(archive_id); - unsigned int archive_id1 = 0; - if (p1 == p) - { - switch (p1->ComponentType()) - { - case ON_SubDComponentPtr::Type::Vertex: - archive_id1 = p1->Vertex()->ArchiveId(); - break; - case ON_SubDComponentPtr::Type::Edge: - archive_id1 = p1->Edge()->ArchiveId(); - break; - case ON_SubDComponentPtr::Type::Face: - archive_id1 = p1->Face()->ArchiveId(); - break; - default: - ON_ERROR("invalid element type"); - break; - } - } - if (archive_id1 != archive_id) - { - // break here and then see what went wrong - ON_SubDIncrementErrorCount(); - m_fsp.Element(archive_id); - m_fsp.Element(archive_id); - } - } -#endif +////#if defined(ON_DEBUG) +//// if (0 != archive_id) +//// { +//// const ON_SubDComponentPtr* p1 = (const ON_SubDComponentPtr*)m_fsp.Element(archive_id); +//// unsigned int archive_id1 = 0; +//// if (p1 == p) +//// { +//// switch (p1->ComponentType()) +//// { +//// case ON_SubDComponentPtr::Type::Vertex: +//// archive_id1 = p1->Vertex()->ArchiveId(); +//// break; +//// case ON_SubDComponentPtr::Type::Edge: +//// archive_id1 = p1->Edge()->ArchiveId(); +//// break; +//// case ON_SubDComponentPtr::Type::Face: +//// archive_id1 = p1->Face()->ArchiveId(); +//// break; +//// default: +//// ON_ERROR("invalid element type"); +//// break; +//// } +//// } +//// if (archive_id1 != archive_id) +//// { +//// // break here and then see what went wrong +//// ON_SubDIncrementErrorCount(); +//// m_fsp.Element(archive_id); +//// m_fsp.Element(archive_id); +//// } +//// } +////#endif m_element_count++; return true; diff --git a/opennurbs_subd_heap.cpp b/opennurbs_subd_heap.cpp index ad13d439..ac6c32a1 100644 --- a/opennurbs_subd_heap.cpp +++ b/opennurbs_subd_heap.cpp @@ -1023,14 +1023,14 @@ class ON_SubDComponentBase* ON_SubDHeap::Internal_AllocateComponentAndSetId( } else { -#if defined(ON_DEBUG) - // TEMPORARY ERROR CHECK added Feb 2020 to test new code. Can be removed in April 2020 or earlier if needed. - // Ask Dale Lear if confused. - if (0 != candidate_id) - { - ON_SUBD_ERROR("Unable to assign candidate_id"); - } -#endif + ////#if defined(ON_DEBUG) + //// // TEMPORARY ERROR CHECK added Feb 2020 to test new code. Can be removed in April 2020 or earlier if needed. + //// // Ask Dale Lear if confused. + //// if (0 != candidate_id) + //// { + //// ON_SUBD_ERROR("Unable to assign candidate_id"); + //// } + ////#endif // otherwise assign the next id to this component. candidate_id = ++max_id; } diff --git a/opennurbs_sum.cpp b/opennurbs_sum.cpp index f127ba6b..067f0029 100644 --- a/opennurbs_sum.cpp +++ b/opennurbs_sum.cpp @@ -46,6 +46,15 @@ void ON_Sum::Begin( double starting_value ) m_neg_count = 0; m_zero_count = 0; + // initialize memory. Fixes https://mcneel.myjetbrains.com/youtrack/issue/RH-85423 + memset(m_pos_sum1, 0, sizeof(double) * sum1_max_count); + memset(m_pos_sum2, 0, sizeof(double) * sum2_max_count); + memset(m_pos_sum3, 0, sizeof(double) * sum3_max_count); + + memset(m_neg_sum1, 0, sizeof(double) * sum1_max_count); + memset(m_neg_sum2, 0, sizeof(double) * sum2_max_count); + memset(m_neg_sum3, 0, sizeof(double) * sum3_max_count); + if ( starting_value > 0.0 ) { m_pos_sum = starting_value; @@ -70,7 +79,9 @@ double ON_Sum::SortAndSum( int count, double* a ) //double a1 = fabs(a[count-1]); m_sum_err += ON_EPSILON*( fabs(a[count-1]) + count*fabs(a[0]) ); } - if ( a[count] < 0.0 ) + // test first item in the array for sign + // fixes https://mcneel.myjetbrains.com/youtrack/issue/RH-85423 + if ( a[0] < 0.0 ) { a += count-1; while (count--) diff --git a/opennurbs_textlog.h b/opennurbs_textlog.h index 56fd9562..d1315b82 100644 --- a/opennurbs_textlog.h +++ b/opennurbs_textlog.h @@ -578,7 +578,7 @@ private: bool m_bApplyIdRemap = false; ON_UUID m_remap_id = ON_nil_uuid; - ON_UuidPairList m_remap_id_list; + ON_UuidPairList2 m_remap_id_list; ON_StringMapType m_string_map_type = ON_StringMapType::Identity; ON_StringMapOrdinalType m_string_map_ordinal_type = ON_StringMapOrdinalType::Identity;