diff --git a/opennurbs_mesh.cpp b/opennurbs_mesh.cpp index 78b5af50..614dd7e7 100644 --- a/opennurbs_mesh.cpp +++ b/opennurbs_mesh.cpp @@ -4363,25 +4363,24 @@ void ON_Mesh::ClearVertexColors() bool ON_Mesh::SetDraftAngleColorAnalysisColors( bool bLazy, - ON_3dVector up, - ON_Interval angle_range_in_radians, - ON_Interval hue_range_in_radians + ON_SurfaceDraftAngleColorMapping draft_angle_colors ) { - const ON_MappingTag Ctag = ON_MappingTag::DraftAngleColorAnalysisTag(up, angle_range_in_radians, hue_range_in_radians); - if (bLazy && HasVertexColors() && this->m_Ctag == Ctag) + const bool bSetColors = draft_angle_colors.IsSet() && this->HasVertexNormals(); + const ON_MappingTag Ctag = draft_angle_colors.ColorMappingTag(); + if (bSetColors && bLazy && this->m_Ctag == Ctag) return true; this->ClearVertexColors(); - if (false == this->HasVertexNormals()) + if (false == bSetColors) return false; const unsigned count = this->m_N.Count(); this->m_C.Reserve(count); for (unsigned i = 0; i < count; ++i) { - const ON_Color c = ON_MappingTag::DraftAngleColor(up, angle_range_in_radians, hue_range_in_radians, ON_3dVector(this->m_N[i])); + const ON_Color c = draft_angle_colors.Color(ON_3dVector(this->m_N[i])); this->m_C.Append(c); } this->m_Ctag = Ctag; @@ -4391,25 +4390,25 @@ bool ON_Mesh::SetDraftAngleColorAnalysisColors( bool ON_Mesh::SetCurvatureColorAnalysisColors( bool bLazy, - const ON::curvature_style kappa_style, - ON_Interval kappa_range, - ON_Interval hue_range_in_radians + ON_SurfaceCurvatureColorMapping kappa_colors ) { - const ON_MappingTag Ctag = ON_MappingTag::CurvatureColorAnalysisTag(kappa_style, kappa_range, hue_range_in_radians); - if (bLazy && HasVertexColors() && this->m_Ctag == Ctag) + const bool bSetColors = kappa_colors.IsSet() && this->HasPrincipalCurvatures(); + const ON_MappingTag Ctag = kappa_colors.ColorMappingTag(); + if (bSetColors && bLazy && HasVertexColors() && this->m_Ctag == Ctag) return true; this->ClearVertexColors(); - if (false == this->HasPrincipalCurvatures()) + if (false == bSetColors) return false; const unsigned count = this->m_K.Count(); + this->m_C.SetCount(0); this->m_C.Reserve(count); for (unsigned i = 0; i < count; ++i) { - const ON_Color c = ON_MappingTag::CurvatureColor(kappa_style, kappa_range, hue_range_in_radians, this->m_K[i]); + const ON_Color c = kappa_colors.Color(this->m_K[i]); this->m_C.Append(c); } this->m_Ctag = Ctag; @@ -9380,24 +9379,21 @@ double ON_SurfaceCurvature::KappaValue(ON::curvature_style kappa_style) const return k; } -const ON_Color ON_MappingTag::CurvatureColor( - ON::curvature_style kappa_style, - ON_Interval kappa_range, - ON_Interval hue_range_in_radians, +const ON_Color ON_SurfaceCurvatureColorMapping::Color( ON_SurfaceCurvature K -) +) const { // This is the curvature analysis color used by the current version of Rhino. // The code can be updated as the method for assigning a color to surface curvatures changes. - const double k = K.KappaValue(kappa_style); + const double k = K.KappaValue(this->m_kappa_style); if (ON_IS_NAN(k)) return ON_Color::UnsetColor; // convert k to hue - const double mn = kappa_range.m_t[0]; - const double mx = kappa_range.m_t[1]; + const double mn = this->m_kappa_range.m_t[0]; + const double mx = this->m_kappa_range.m_t[1]; double f; if (mn != mx) { @@ -9422,11 +9418,82 @@ const ON_Color ON_MappingTag::CurvatureColor( if (f >= 0.0 && f <= 1.0) - return ON_Color::FromHueInRadians(hue_range_in_radians.ParameterAt(f)); + return ON_Color::FromHueInRadians(this->m_hue_range_in_radians.ParameterAt(f)); return ON_Color::UnsetColor; } +bool ON_SurfaceCurvatureColorMapping::IsSet() const +{ + if (1 == this->m_is_set) + return true; + if (0 == this->m_is_set) + return false; + for (;;) + { + if ((int)(this->m_kappa_style) <= (int)(ON::curvature_style::unknown_curvature_style)) + break; + if ((int)(this->m_kappa_style) >= (int)(ON::curvature_style::curvature_style_count)) + break; + if (false == m_kappa_range.IsValid()) + break; + if (false == m_hue_range_in_radians.IsValid()) + break; + this->m_is_set = 1; + return true; + } + this->m_is_set = 0; + return false; +} + +bool ON_SurfaceCurvatureColorMapping::IsUnset() const +{ + return this->IsSet() ? false : true; +} + +bool operator==(const ON_SurfaceCurvatureColorMapping& lhs, const ON_SurfaceCurvatureColorMapping& rhs) +{ + // if any double is a nan, this compare must be false. + const ON::curvature_style cs[2] = { lhs.KappaStyle(), rhs.KappaStyle() }; + if (cs[0] == cs[1]) + { + const ON_Interval kr[2] = { lhs.KappaRange() ,rhs.KappaRange() }; + if (kr[0].m_t[0] == kr[1].m_t[0] && kr[0].m_t[1] == kr[1].m_t[1]) + { + const ON_Interval hr[2] = { lhs.HueRangeInRadians() ,rhs.HueRangeInRadians() }; + if (hr[0].m_t[0] == hr[1].m_t[0] && hr[0].m_t[1] == hr[1].m_t[1]) + return true; + } + } + return false; +} + +bool operator!=(const ON_SurfaceCurvatureColorMapping& lhs, const ON_SurfaceCurvatureColorMapping& rhs) +{ + // if any double is a nan, this compare must be false. + const ON::curvature_style cs[2] = { lhs.KappaStyle(), rhs.KappaStyle() }; + if (cs[0] != cs[1]) + { + const ON_Interval kr[2] = { lhs.KappaRange() ,rhs.KappaRange() }; + if (kr[0].m_t[0] != kr[1].m_t[0] || kr[0].m_t[1] != kr[1].m_t[1]) + { + const ON_Interval hr[2] = { lhs.HueRangeInRadians() ,rhs.HueRangeInRadians() }; + if (hr[0].m_t[0] != hr[1].m_t[0] || hr[0].m_t[1] != hr[1].m_t[1]) + { + // any compare involving nans is false + if (ON_IS_NAN(kr[0].m_t[0]) || ON_IS_NAN(kr[0].m_t[1]) || ON_IS_NAN(kr[1].m_t[0]) || ON_IS_NAN(kr[1].m_t[1])) + return false; + if (ON_IS_NAN(hr[0].m_t[0]) || ON_IS_NAN(hr[0].m_t[1]) || ON_IS_NAN(hr[1].m_t[0]) || ON_IS_NAN(hr[1].m_t[1])) + return false; + + return true; + } + } + } + return false; +} + + bool ON_SurfaceCurvature::IsSet() const { return (ON_UNSET_VALUE < k1&& k1 < ON_UNSET_POSITIVE_VALUE&& ON_UNSET_VALUE < k2&& k2 < ON_UNSET_POSITIVE_VALUE); @@ -12282,156 +12349,283 @@ const ON_Xform ON_MappingTag::Transform() const return TransformIsIdentity() ? ON_Xform::IdentityTransformation : m_mesh_xform; } -const ON_SHA1_Hash ON_MappingTag::CurvatureColorAnalysisParametersHash( +ON_SurfaceCurvatureColorMapping::ON_SurfaceCurvatureColorMapping( + ON::curvature_style kappa_style, + ON_Interval kappa_range +) + : m_is_set(2) + , m_kappa_style(ON::CurvatureStyle((int)(kappa_style))) + , m_kappa_range(kappa_range.IsValid() ? kappa_range : ON_Interval::Nan) +{} + +ON_SurfaceCurvatureColorMapping::ON_SurfaceCurvatureColorMapping( ON::curvature_style kappa_style, ON_Interval kappa_range, ON_Interval hue_range_in_radians ) + : m_is_set(2) + , m_kappa_style(ON::CurvatureStyle((int)(kappa_style))) + , m_kappa_range(kappa_range.IsValid() ? kappa_range : ON_Interval::Nan) + , m_hue_range_in_radians(hue_range_in_radians.IsValid() ? hue_range_in_radians : ON_Interval::Nan) +{} + +const ON_SHA1_Hash ON_SurfaceCurvatureColorMapping::Hash() const { - ON_SHA1 sha1; + if (this->IsSet()) + { + ON_SHA1 sha1; - // The uuid is accumulated because an int,double,double could easily - // be the intput data int many unrelated contexts. This sha1 is used - // to avoid expensive recalculations of curvatures and their false colors. - const ON_UUID uniqueness_boost = ON_MappingTag::CurvatureColorAnalysisId; - sha1.AccumulateId(uniqueness_boost); + // The uuid is accumulated because an int,double,double could easily + // be the intput data int many unrelated contexts. This sha1 is used + // to avoid expensive recalculations of curvatures and their false colors. + const ON_UUID uniqueness_boost = ON_SurfaceCurvatureColorMapping::Id; + sha1.AccumulateId(uniqueness_boost); - const unsigned u = (unsigned)kappa_style; - sha1.AccumulateInteger32(u); + const unsigned u = (unsigned)this->m_kappa_style; + sha1.AccumulateInteger32(u); - sha1.AccumulateDoubleArray(2, kappa_range.m_t); + sha1.AccumulateDoubleArray(2, this->m_kappa_range.m_t); - sha1.AccumulateDoubleArray(2, hue_range_in_radians.m_t); + sha1.AccumulateDoubleArray(2, this->m_hue_range_in_radians.m_t); - return sha1.Hash(); + return sha1.Hash(); + } + return ON_SHA1_Hash::EmptyContentHash; } -ON__UINT32 ON_MappingTag::CurvatureColorAnalysisParametersCRC32( - ON::curvature_style kappa_style, - ON_Interval kappa_range, - ON_Interval hue_range_in_radians -) +ON__UINT32 ON_SurfaceCurvatureColorMapping::CRC32() const { - return ON_MappingTag::CurvatureColorAnalysisParametersHash(kappa_style,kappa_range, hue_range_in_radians).CRC32(0); + return this->IsSet() ? this->Hash().CRC32(0) : 0; } -const ON_MappingTag ON_MappingTag::CurvatureColorAnalysisTag( - ON::curvature_style kappa_style, - ON_Interval kappa_range, - ON_Interval hue_range_in_radians -) +const ON_MappingTag ON_SurfaceCurvatureColorMapping::ColorMappingTag() const { ON_MappingTag mt = ON_MappingTag::Unset; + if (this->IsSet()) + { - mt.m_mapping_id = ON_MappingTag::CurvatureColorAnalysisId; - mt.m_mapping_type = ON_TextureMapping::TYPE::false_colors; + mt.m_mapping_id = ON_SurfaceCurvatureColorMapping::Id; + mt.m_mapping_type = ON_TextureMapping::TYPE::false_colors; - // DO NOT INCLUDE anything in the crc that does not directly control vertex colors. - // This value is used to determine when the parameters used to calculate the vertex - // colors have changed. - mt.m_mapping_crc = ON_MappingTag::CurvatureColorAnalysisParametersCRC32(kappa_style, kappa_range, hue_range_in_radians); + // DO NOT INCLUDE anything in the crc that does not directly control vertex colors. + // This value is used to determine when the parameters used to calculate the vertex + // colors have changed. + mt.m_mapping_crc = this->CRC32(); - // The m_mesh_xform in meaningless for false color curvature analysis, - // but setting it to the identity greases the wheels when downstream - // code looks at it for unknown reasons. - mt.m_mesh_xform = ON_Xform::IdentityTransformation; + // The m_mesh_xform in meaningless for false color curvature analysis, + // but setting it to the identity greases the wheels when downstream + // code looks at it for unknown reasons. + mt.m_mesh_xform = ON_Xform::IdentityTransformation; + } return mt; } -const ON_SHA1_Hash ON_MappingTag::DraftAngleColorAnalysisParametersHash( - ON_3dVector up, - ON_Interval angle_range_in_radians, - ON_Interval hue_range_in_radians -) +ON::curvature_style ON_SurfaceCurvatureColorMapping::KappaStyle() const { - ON_SHA1 sha1; - - // The uuid is accumulated because an int,double,double could easily - // be the intput data int many unrelated contexts. This sha1 is used - // to avoid expensive recalculations of curvatures and their false colors. - const ON_UUID uniqueness_boost = ON_MappingTag::DraftAngleColorAnalysisId; - sha1.AccumulateId(uniqueness_boost); - sha1.AccumulateDoubleArray(3, &up.x); - sha1.AccumulateDoubleArray(2, angle_range_in_radians.m_t); - sha1.AccumulateDoubleArray(2, hue_range_in_radians.m_t); - return sha1.Hash(); + return m_kappa_style; } -ON__UINT32 ON_MappingTag::DraftAngleColorAnalysisParametersCRC32( +const ON_Interval ON_SurfaceCurvatureColorMapping::KappaRange() const +{ + return m_kappa_range; +} + +const ON_Interval ON_SurfaceCurvatureColorMapping::HueRangeInRadians() const +{ + return m_hue_range_in_radians; +} + +ON_SurfaceDraftAngleColorMapping::ON_SurfaceDraftAngleColorMapping( + ON_3dVector up, + ON_Interval angle_range_in_radians +) + : m_is_set(2) + , m_up(up.IsValid() ? up : ON_3dVector::NanVector) + , m_angle_range_in_radians(angle_range_in_radians.IsValid() ? angle_range_in_radians : ON_Interval::Nan) + , m_hue_range_in_radians(ON_SurfaceDraftAngleColorMapping::DefaultHueRangeRadians) +{} + +ON_SurfaceDraftAngleColorMapping::ON_SurfaceDraftAngleColorMapping( ON_3dVector up, ON_Interval angle_range_in_radians, ON_Interval hue_range_in_radians ) + : m_is_set(2) + , m_up(up.IsValid() ? up : ON_3dVector::NanVector) + , m_angle_range_in_radians(angle_range_in_radians.IsValid() ? angle_range_in_radians : ON_Interval::Nan) + , m_hue_range_in_radians(hue_range_in_radians.IsValid() ? hue_range_in_radians : ON_Interval::Nan) +{} + +const ON_3dVector ON_SurfaceDraftAngleColorMapping::Up() const { - return ON_MappingTag::DraftAngleColorAnalysisParametersHash(up, angle_range_in_radians, hue_range_in_radians).CRC32(0); + return this->m_up; +} + +const ON_Interval ON_SurfaceDraftAngleColorMapping::AngleRangeInRadians() const +{ + return this->m_angle_range_in_radians; +} + +const ON_Interval ON_SurfaceDraftAngleColorMapping::HueRangeInRadians() const +{ + return this->m_hue_range_in_radians; } -const ON_MappingTag ON_MappingTag::DraftAngleColorAnalysisTag( - ON_3dVector up, - ON_Interval angle_range_in_radians, - ON_Interval hue_range_in_radians -) +const ON_SHA1_Hash ON_SurfaceDraftAngleColorMapping::Hash() const +{ + if (this->IsSet()) + { + ON_SHA1 sha1; // The uuid is accumulated because an int,double,double could easily + // be the intput data int many unrelated contexts. This sha1 is used + // to avoid expensive recalculations of curvatures and their false colors. + const ON_UUID uniqueness_boost = ON_SurfaceDraftAngleColorMapping::Id; + sha1.AccumulateId(uniqueness_boost); + sha1.AccumulateDoubleArray(3, &this->m_up.x); + sha1.AccumulateDoubleArray(2, this->m_angle_range_in_radians.m_t); + sha1.AccumulateDoubleArray(2, this->m_hue_range_in_radians.m_t); + return sha1.Hash(); + } + return ON_SHA1_Hash::EmptyContentHash; +} + +ON__UINT32 ON_SurfaceDraftAngleColorMapping::CRC32() const +{ + return this->IsSet() ? this->Hash().CRC32(0) : 0; +} + + +const ON_MappingTag ON_SurfaceDraftAngleColorMapping::ColorMappingTag() const { ON_MappingTag mt = ON_MappingTag::Unset; - mt.m_mapping_id = ON_MappingTag::DraftAngleColorAnalysisId; - mt.m_mapping_type = ON_TextureMapping::TYPE::false_colors; + if (this->IsSet()) + { + mt.m_mapping_id = ON_SurfaceDraftAngleColorMapping::Id; + mt.m_mapping_type = ON_TextureMapping::TYPE::false_colors; - // DO NOT INCLUDE anything in the crc that does not directly control vertex colors. - // This value is used to determine when the parameters used to calculate the vertex - // colors have changed. - mt.m_mapping_crc = ON_MappingTag::DraftAngleColorAnalysisParametersCRC32(up, angle_range_in_radians, hue_range_in_radians); + // DO NOT INCLUDE anything in the crc that does not directly control vertex colors. + // This value is used to determine when the parameters used to calculate the vertex + // colors have changed. + mt.m_mapping_crc = this->CRC32(); - // The m_mesh_xform in meaningless for false color curvature analysis, - // but setting it to the identity greases the wheels when downstream - // code looks at it for unknown reasons. - mt.m_mesh_xform = ON_Xform::IdentityTransformation; + // The m_mesh_xform in meaningless for false color curvature analysis, + // but setting it to the identity greases the wheels when downstream + // code looks at it for unknown reasons. + mt.m_mesh_xform = ON_Xform::IdentityTransformation; + } return mt; } -const ON_Color ON_MappingTag::DraftAngleColor( - ON_3dVector up, - ON_Interval draft_angle_range_in_radians, - ON_Interval hue_range_in_radians, +bool ON_SurfaceDraftAngleColorMapping::IsSet() const +{ + if (1 == this->m_is_set) + return true; + if (0 == this->m_is_set) + return false; + for (;;) + { + if (false == this->m_up.IsValid()) + break; + if (false == this->m_angle_range_in_radians.IsValid()) + break; + if (false == this->m_hue_range_in_radians.IsValid()) + break; + this->m_is_set = 1; + return true; + } + this->m_is_set = 0; + return false; +} + +bool ON_SurfaceDraftAngleColorMapping::IsUnset() const +{ + return this->IsSet() ? false : true; +} + +bool operator==(const ON_SurfaceDraftAngleColorMapping& lhs, const ON_SurfaceDraftAngleColorMapping& rhs) +{ + // if any double is a nan, this compare must be false. + if (lhs.IsSet() == rhs.IsSet()) + { + const ON_3dVector up[2] = { lhs.Up(), rhs.Up() }; + if (up[0] == up[1]) + { + const ON_Interval ar[2] = { lhs.AngleRangeInRadians() ,rhs.AngleRangeInRadians() }; + if (ar[0].m_t[0] == ar[1].m_t[0] && ar[0].m_t[1] == ar[1].m_t[1]) + { + const ON_Interval hr[2] = { lhs.HueRangeInRadians() ,rhs.HueRangeInRadians() }; + if (hr[0].m_t[0] == hr[1].m_t[0] && hr[0].m_t[1] == hr[1].m_t[1]) + return true; + } + } + } + return false; +} + +bool operator!=(const ON_SurfaceDraftAngleColorMapping& lhs, const ON_SurfaceDraftAngleColorMapping& rhs) +{ + // if any double is a nan, this compare must be false. + const ON_3dVector up[2] = { lhs.Up(), rhs.Up() }; + if (up[0] != up[1]) + { + const ON_Interval ar[2] = { lhs.AngleRangeInRadians() ,rhs.AngleRangeInRadians() }; + if (ar[0].m_t[0] != ar[1].m_t[0] || ar[0].m_t[1] != ar[1].m_t[1]) + { + const ON_Interval hr[2] = { lhs.HueRangeInRadians() ,rhs.HueRangeInRadians() }; + if (hr[0].m_t[0] != hr[1].m_t[0] || hr[0].m_t[1] != hr[1].m_t[1]) + { + // any compare involving nans is false + if (ON_IS_NAN(ar[0].m_t[0]) || ON_IS_NAN(ar[0].m_t[1]) || ON_IS_NAN(ar[1].m_t[0]) || ON_IS_NAN(ar[1].m_t[1])) + return false; + if (ON_IS_NAN(hr[0].m_t[0]) || ON_IS_NAN(hr[0].m_t[1]) || ON_IS_NAN(hr[1].m_t[0]) || ON_IS_NAN(hr[1].m_t[1])) + return false; + + return true; + } + } + } + return false; +} + + +const ON_Color ON_SurfaceDraftAngleColorMapping::Color( ON_3dVector surface_normal -) +) const { for (;;) { - if (false == ON_IsValid(draft_angle_range_in_radians.m_t[0])) - break; - if (false == ON_IsValid(draft_angle_range_in_radians.m_t[1])) + if (false == IsSet()) break; - const double a0 = ON_HALFPI - draft_angle_range_in_radians[0]; - const double a1 = ON_HALFPI - draft_angle_range_in_radians[1]; + const double a0 = ON_HALFPI - this->m_angle_range_in_radians[0]; + const double a1 = ON_HALFPI - this->m_angle_range_in_radians[1]; const double mn = cos(a0); const double mx = cos(a1); - const double n_dot_up = surface_normal * up; + const double n_dot_up = surface_normal * this->m_up; double h; if (fabs(mn - mx) <= 1e-8) { if (n_dot_up < mn && n_dot_up < mx) - h = hue_range_in_radians[0]; + h = this->m_hue_range_in_radians[0]; else if (n_dot_up > mn && n_dot_up > mx) - h = hue_range_in_radians[1]; + h = this->m_hue_range_in_radians[1]; else - h = hue_range_in_radians.ParameterAt(0.5); + h = this->m_hue_range_in_radians.ParameterAt(0.5); } else if (mn != mx) { double t = (n_dot_up - mn) / (mx - mn); if (t <= 0.0) - h = hue_range_in_radians[0]; + h = this->m_hue_range_in_radians[0]; else if (t >= 1.0) - h = hue_range_in_radians[1]; + h = this->m_hue_range_in_radians[1]; else - h = hue_range_in_radians.ParameterAt(t); + h = this->m_hue_range_in_radians.ParameterAt(t); } else break; @@ -12540,10 +12734,10 @@ void ON_MappingTag::Dump( ON_TextLog& text_log ) const text_log.Print(m_mapping_id); if (m_mapping_id == ON_MappingTag::SurfaceParameterMapping.m_mapping_id) text_log.Print(" = ON_MappingTag::SurfaceParameterMapping.m_mapping_id"); - else if (m_mapping_id == ON_MappingTag::CurvatureColorAnalysisId) - text_log.Print(" = ON_MappingTag::CurvatureColorAnalysisId"); - else if (m_mapping_id == ON_MappingTag::DraftAngleColorAnalysisId) - text_log.Print(" = ON_MappingTag::DraftAngleColorAnalysisId"); + else if (m_mapping_id == ON_SurfaceCurvatureColorMapping::Id) + text_log.Print(" = ON_SurfaceCurvatureColorMapping::Id"); + else if (m_mapping_id == ON_SurfaceDraftAngleColorMapping::Id) + text_log.Print(" = ON_SurfaceDraftAngleColorMapping::Id"); text_log.PrintNewLine(); text_log.Print("mapping crc: %08x\n", m_mapping_crc); diff --git a/opennurbs_mesh.h b/opennurbs_mesh.h index f0e697d2..ea68dcc4 100644 --- a/opennurbs_mesh.h +++ b/opennurbs_mesh.h @@ -3068,197 +3068,6 @@ public: /// static const ON_MappingTag SurfaceParameterMapping; - // {639E9144-1C1A-4bba-8248-D330F50D7B69} - static const ON_UUID CurvatureColorAnalysisId; - - /// - /// - /// - /// - /// When in doubt, use ON_MappingTag::CurvatureColorHueRangeDefault. - /// - /// - /// The SHA1 hash used to indentify the parameters used to - /// convert the surface principal curvatures to a color. - /// - static const ON_SHA1_Hash CurvatureColorAnalysisParametersHash( - ON::curvature_style kappa_style, - ON_Interval kappa_range, - ON_Interval hue_range_in_radians - ); - - /// - /// - /// - /// - /// When in doubt, use ON_MappingTag::CurvatureColorHueRangeDefault. - /// - /// - /// The 32 bit CRC used to indentify the parameters used to - /// convert the surface principal curvatures to a color. - /// - static ON__UINT32 CurvatureColorAnalysisParametersCRC32( - ON::curvature_style kappa_style, - ON_Interval kappa_range, - ON_Interval hue_range_in_radians - ); - - /// - /// Get the mapping tag used to identify meshes whose vertex colors - /// are set by converting surface principal curvatures to a color. - /// - /// - /// - /// - /// When in doubt, use ON_MappingTag::CurvatureColorHueRangeDefault. - /// - /// - /// A mapping tag that has id = ON_MappingTag::CurvatureAnalysisId - /// and a CRC that depends on kappa_style and kappa_range. - /// - static const ON_MappingTag CurvatureColorAnalysisTag( - ON::curvature_style kappa_style, - ON_Interval kappa_range, - ON_Interval hue_range_in_radians - ); - - /// - /// The default curvature color analysis hue range used - /// by the Rhino CurvatureAnalysis command. - /// - /// 0 to 4pi/3 (red to blue) - static const ON_Interval CurvatureColorHueRangeDefault; - - /// - /// Used to convert a curvature value to a color. - /// - /// - /// Specifies what curvature value to used. - /// - /// - /// A range that is used to convert kappa values to colors. - /// This interval may be increasing, decreasing, or a singleton. - /// A kappa value equal to kappa_range[0] is mapped to hue_range[0]. - /// A kappa value equal to kappa_range[1] is mapped to hue_range[1]. - /// A kappa value k in between kappa_range[0] and kappa_range[1] - /// is mapped to the saturated color with - /// hue = hue_range.ParameterAt(kappa_range.NormalizedParameterAt(k)). - /// Kappa values outside the kappa_range inteval are mapped to the hue - /// assigned to the nearest end of the kappa_range interval. - /// - /// - /// When in doubt, pass ON_MappingTag::CurvatureHueRangeDefault. - /// The range of color hues in radians corresponding to kappa_range. - /// This interval may be increasing or decreasing. - /// A kappa value k in between kappa_range[0] and kappa_range[1] - /// is mapped to the saturated color with - /// hue = hue_range.ParameterAt(kappa_range.NormalizedParameterAt(k)). - /// If k is outside the range specified by kappa_range, - /// the appropriate - /// - /// - /// The color used by the current Rhino CurvatureAnalysis command. - /// - static const ON_Color CurvatureColor( - ON::curvature_style kappa_style, - ON_Interval kappa_range, - ON_Interval hue_range_in_radians, - ON_SurfaceCurvature K - ); - - // {F08463F4-22E2-4cf1-B810-F01925446D71} - static const ON_UUID DraftAngleColorAnalysisId; - - /// - /// - /// - /// - /// When in doubt, use ON_MappingTag::DraftAngleColorHueRangeDefault. - /// - /// - /// The SHA1 hash used to indentify the parameters used to - /// convert the surface normal to a draft angle analysis color. - /// - static const ON_SHA1_Hash DraftAngleColorAnalysisParametersHash( - ON_3dVector up, - ON_Interval angle_range_in_radians, - ON_Interval hue_range_in_radians - ); - - /// - /// - /// - /// - /// When in doubt, use ON_MappingTag::DraftAngleColorHueRangeDefault. - /// - /// - /// The 32 bit CRC used to indentify the parameters used to - /// convert the surface normal to a draft angle analysis color. - /// - static ON__UINT32 DraftAngleColorAnalysisParametersCRC32( - ON_3dVector up, - ON_Interval angle_range_in_radians, - ON_Interval hue_range_in_radians - ); - - /// - /// Get the mapping tag used to identify meshes whose vertex colors - /// are set by converting surface normal to a draft angle color. - /// - /// - /// - /// - /// When in doubt, use ON_MappingTag::DraftAngleColorHueRangeDefault. - /// - /// - /// A mapping tag that has id = ON_MappingTag::DraftAngleMappingTag - /// and a CRC that depends on up and angle_range_in_radians. - /// - static const ON_MappingTag DraftAngleColorAnalysisTag( - ON_3dVector up, - ON_Interval angle_range_in_radians, - ON_Interval hue_range_in_radians - ); - - /// - /// The default draft angle color analysis hue range used - /// by the Rhino CraftAngleAnalysis command. - /// - /// - /// 0 to 4pi/3 (red to blue) - /// - static const ON_Interval DraftAngleColorHueRangeDefault; - - /// - /// Used to get the color the current Rhino DraftAngleAnalysis command - /// assigns to a specified surface normal. - /// - /// - /// A unit vector (length = 1) that specifies the up direction. - /// - /// - /// An draft angle of 0 corresponds to the up vector and a surface normal being orthogonal. - /// Draft angles > 0 correspond to to a surface normal and up having a positive dot product. - /// Draft angles < 0 correspond to to a surface normal and up having a negative dot product. - /// A draft angle of pi/2 (90 degrees) occurs when the surface normal and up are parallel. - /// A draft angle of -pi/2 (-90 degrees) occurs when the surface normal and up are antiparallel. - /// - /// - /// hue range in radians. - /// 0 = red, pi/3 = yellow, 2pi/3 = green, pi = cyan, - /// 4pi/3 = blue, 5pi/3 = magenta, 2pi = red - /// A draft angle = draft_angle_range_in_radians[0] is assigned a color hue = hue_range_in_radians[0] - /// and a draft angle = draft_angle_range_in_radians[1] is assigned a color hue = hue_range_in_radians[1]. - /// - /// - /// - static const ON_Color DraftAngleColor( - ON_3dVector up, - ON_Interval draft_angle_range_in_radians, - ON_Interval hue_range_in_radians, - ON_3dVector surface_normal - ); - void Default(); bool Write(ON_BinaryArchive&) const; bool Read(ON_BinaryArchive&); @@ -3377,6 +3186,366 @@ ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; #endif +class ON_CLASS ON_SurfaceCurvatureColorMapping +{ +public: + /// + /// {639E9144-1C1A-4bba-8248-D330F50D7B69} + /// The id ON_SurfaceCurvatureColorMapping::Id identifies + /// the surface curvature color analysis used by the Rhino CurvatureAnalysis command + /// and is used as the id for mapping tags that indicate per vertex colors + /// were set from surface principal curvatures. + /// + static const ON_UUID Id; + + /// + /// The default surface curvature color analysis hue range used + /// by the Rhino CurvatureAnalysis command is + /// 0 to 4pi/3 (red to blue) + /// + static const ON_Interval DefaultHueRangeRadians; + + static const ON_SurfaceCurvatureColorMapping Unset; + +public: + ON_SurfaceCurvatureColorMapping() = default; + ~ON_SurfaceCurvatureColorMapping() = default; + ON_SurfaceCurvatureColorMapping(const ON_SurfaceCurvatureColorMapping&) = default; + ON_SurfaceCurvatureColorMapping& operator=(const ON_SurfaceCurvatureColorMapping&) = default; + + /// + /// Construce a ON_SurfaceCurvatureColorMapping for cnverting a specified + /// range of curvatures to a color. + /// + /// + /// Specifies what curvature value to used. + /// + /// + /// A range that is used to convert kappa values to colors. + /// This interval may be increasing, decreasing, or a singleton. + /// A kappa value equal to kappa_range[0] is mapped to + /// ON_SurfaceCurvatureColorMapping::DefaultHueRangeRadians[0]. + /// A kappa value equal to kappa_range[1] is mapped to + /// ON_SurfaceCurvatureColorMapping::DefaultHueRangeRadians[1]. + /// A kappa value k in between kappa_range[0] and kappa_range[1] + /// is mapped to the saturated color with + /// hue = ON_SurfaceCurvatureColorMapping::DefaultHueRangeRadians.ParameterAt(kappa_range.NormalizedParameterAt(k)). + /// Kappa values outside the kappa_range inteval are mapped to the hue + /// assigned to the nearest end of the kappa_range interval. + /// + ON_SurfaceCurvatureColorMapping( + ON::curvature_style m_kappa_style, + ON_Interval kappa_range + ); + + /// + /// Construce a ON_SurfaceCurvatureColorMapping for cnverting a specified + /// range of curvatures to a color. + /// + /// + /// Specifies what curvature value to used. + /// + /// + /// A range that is used to convert kappa values to colors. + /// This interval may be increasing, decreasing, or a singleton. + /// A kappa value equal to kappa_range[0] is mapped to hue_range_in_radians[0]. + /// A kappa value equal to kappa_range[1] is mapped to hue_range_in_radians[1]. + /// A kappa value k in between kappa_range[0] and kappa_range[1] + /// is mapped to the saturated color with + /// hue = hue_range_in_radians.ParameterAt(kappa_range.NormalizedParameterAt(k)). + /// Kappa values outside the kappa_range inteval are mapped to the hue + /// assigned to the nearest end of the kappa_range interval. + /// + /// + /// When in doubt, pass ON_SurfaceCurvatureColorMapping::DefaultHueRangeRadians. + /// This paramter specifies the range of color hues (in radians) assigned + /// to the kappa_range interval. + /// This interval may be increasing or decreasing. + /// + ON_SurfaceCurvatureColorMapping( + ON::curvature_style kappa_style, + ON_Interval kappa_range, + ON_Interval hue_range_in_radians + ); + + /// + /// If the curvature type, range, and hure range are set and valid, then true is returned. + /// Otherwise false is returned. + /// + bool IsSet() const; + + /// + /// If one or more of the curvature type, range, and hure range are not set or are not valid, + /// valid, then true is returned. + /// Otherwise false is returned. + /// + bool IsUnset() const; + + /// + /// Get the color the the settings in this ON_SurfaceCurvatureColorMapping assign + /// to a pair of principal surface curvatures. + /// + /// + /// principal surface curvatures + /// + /// + /// If K and this->IsSet() is true, then the color assigned to the principal curvatures K is returned. + /// Otherwise ON_Color::UnsetColor is returned. + /// + const ON_Color Color( + ON_SurfaceCurvature K + ) const; + + /// + /// Get a SHA1 hash that uniquely identifies the + /// settings in this ON_SurfaceCurvatureColorMapping. + /// This hash is ideal for use as a SubD fragment colors hash. + /// + /// + /// If this->IsSet() is true, a SHA1 hash that uniquely identifies the + /// settings in this ON_SurfaceCurvatureColorMapping is returned. + /// Otherwise ON_SHA1_Hash::EmptyContentHash() is returned. + /// + const ON_SHA1_Hash Hash() const; + + /// + /// Get a 32 bit CRC hash that identifies the + /// settings in this ON_SurfaceCurvatureColorMapping. + /// + /// + /// If this->IsSet() is true, this->Hash()CRC32(0) is returned. + /// Otherwise 0 is returned. + /// + ON__UINT32 CRC32() const; + + /// + /// The returned mapping tag is ideal for setting the ON_SubD fragment and ON_Mesh + /// per vertex color tag when the colors are set by calling this->Color() + /// on the per vertex principal surface curvatures. + /// + /// + /// If this->ISSet() is true, a mapping tag with + /// type = ON_TextureMapping::TYPE::false_colors, + /// id = ON_SurfaceCurvatureColorMapping::Id, + /// crc = this->CRC32() + /// xform = identity + /// is returned. Otherwise ON_MappingTag::Unset is returned. + /// + const ON_MappingTag ColorMappingTag() const; + + ON::curvature_style KappaStyle() const; + + const ON_Interval KappaRange() const; + + const ON_Interval HueRangeInRadians() const; + +private: + mutable unsigned char m_is_set = 0; // 0 = not set, 1 = this is valid and set, 2 = unknown + ON__UINT8 m_reserved1 = 0; + ON__UINT16 m_reserved2 = 0; + ON::curvature_style m_kappa_style = ON::curvature_style::unknown_curvature_style; + ON_Interval m_kappa_range = ON_Interval::Nan; + ON_Interval m_hue_range_in_radians = ON_SurfaceCurvatureColorMapping::DefaultHueRangeRadians; +}; + +/// +/// Returns true if all properties of lhs and rhs are identical and no double is a nan. +/// +ON_DECL +bool operator==(const ON_SurfaceCurvatureColorMapping& lhs, const ON_SurfaceCurvatureColorMapping& rhs); + +/// +/// Returns true if some property of lhs and rhs is different and no double is a nan. +/// +ON_DECL +bool operator!=(const ON_SurfaceCurvatureColorMapping& lhs, const ON_SurfaceCurvatureColorMapping& rhs); + + +class ON_CLASS ON_SurfaceDraftAngleColorMapping +{ +public: + /// + /// // {F08463F4-22E2-4cf1-B810-F01925446D71} + /// The id ON_SurfaceDraftAngleColorMapping::Id identifies + /// the surface draft angle color analysis used by the Rhino DraftAngleAnalysis command + /// and is used as the id for mapping tags that indicate per vertex colors + /// were set from surface normal draft angles. + /// + static const ON_UUID Id; + + /// + /// The default surface draft angle color analysis hue range used + /// by the Rhino DraftAngleAnalysis command is + /// 0 to 4pi/3 (red to blue) + /// + static const ON_Interval DefaultHueRangeRadians; + + static const ON_SurfaceDraftAngleColorMapping Unset; + +public: + ON_SurfaceDraftAngleColorMapping() = default; + ~ON_SurfaceDraftAngleColorMapping() = default; + ON_SurfaceDraftAngleColorMapping(const ON_SurfaceDraftAngleColorMapping&) = default; + ON_SurfaceDraftAngleColorMapping& operator=(const ON_SurfaceDraftAngleColorMapping&) = default; + + /// + /// Construce a ON_SurfaceDraftAngleColorMapping for cnverting a specified + /// range of draft angles to a color. + /// + /// + /// Specify the up direction used to caluclate the draft angle. + /// The draft angle of a surface normal N is 0 if N is perpendicular to up, + /// pi/2 (90 degrees) if N an up piont the same direction, + /// and -pi/2 (-90 degrees) if N and up point opposite directions. + /// + /// + /// A range that is used to convert draft angles to colors. + /// This interval may be increasing, decreasing, or a singleton. + /// A draft angle equal to angle_range_in_radians[0] is mapped to + /// ON_SurfaceDraftAngleColorMapping::DefaultHueRangeRadians[0]. + /// A draft angle equal to angle_range_in_radians[1] is mapped to + /// ON_SurfaceDraftAngleColorMapping::DefaultHueRangeRadians[1]. + /// A draft angle a in between angle_range_in_radians[0] and angle_range_in_radians[1] + /// is mapped to the saturated color with + /// hue = ON_SurfaceDraftAngleColorMapping::DefaultHueRangeRadians.ParameterAt(angle_range_in_radians.NormalizedParameterAt(a)). + /// Draft angles outside the angle_range_in_radians interval are mapped to the hue + /// assigned to the nearest end of the angle_range_in_radians interval. + /// + ON_SurfaceDraftAngleColorMapping( + ON_3dVector up, + ON_Interval angle_range_in_radians + ); + + /// + /// Construce a ON_SurfaceDraftAngleColorMapping for cnverting a specified + /// range of draft angles to a color. + /// + /// + /// Specify the up direction used to caluclate the draft angle. + /// The draft angle of a surface normal N is 0 if N is perpendicular to up, + /// pi/2 (90 degrees) if N an up piont the same direction, + /// and -pi/2 (-90 degrees) if N and up point opposite directions. + /// + /// + /// A range that is used to convert draft angles to colors. + /// This interval may be increasing, decreasing, or a singleton. + /// A draft angle equal to angle_range_in_radians[0] is mapped to + /// hue_range_in_radianss[0]. + /// A draft angle equal to angle_range_in_radians[1] is mapped to + /// hue_range_in_radians[1]. + /// A draft angle a in between angle_range_in_radians[0] and angle_range_in_radians[1] + /// is mapped to the saturated color with + /// hue = hue_range_in_radians.ParameterAt(angle_range_in_radians.NormalizedParameterAt(a)). + /// Draft angles outside the angle_range_in_radians interval are mapped to the hue + /// assigned to the nearest end of the angle_range_in_radians interval. + /// + /// + /// When in doubt, pass ON_SurfaceDraftAngleColorMapping::DefaultHueRangeRadians. + /// This paramter specifies the range of color hues (in radians) assigned + /// to the angle_range_in_radians interval. + /// The hue interval may be increasing or decreasing. + /// + ON_SurfaceDraftAngleColorMapping( + ON_3dVector up, + ON_Interval angle_range_in_radians, + ON_Interval hue_range_in_radians + ); + + /// + /// If the draft angle up, angle range, and hue range are set and valid, then true is returned. + /// Otherwise false is returned. + /// + bool IsSet() const; + + /// + /// If one or more of the up vector, angle range, and hue range are not set or are not valid, + /// valid, then true is returned. + /// Otherwise false is returned. + /// + bool IsUnset() const; + + /// + /// Get the color the the settings in this ON_SurfaceDraftAngleColorMapping assign + /// to a surface normal. + /// + /// + /// Unit length normal to the surface. + /// + /// + /// If surface_normal is set and this->IsSet() is true, + /// then the color assigned to the resulting draft angle is returned. + /// Otherwise ON_Color::UnsetColor is returned. + /// + const ON_Color Color( + ON_3dVector surface_normal + ) const; + + /// + /// Get a SHA1 hash that uniquely identifies the + /// settings in this ON_SurfaceDraftAngleColorMapping. + /// This hash is ideal for use as a SubD fragment colors hash. + /// + /// + /// If this->IsSet() is true, a SHA1 hash that uniquely identifies the + /// settings in this ON_SurfaceDraftAngleColorMapping is returned. + /// Otherwise ON_SHA1_Hash::EmptyContentHash() is returned. + /// + const ON_SHA1_Hash Hash() const; + + /// + /// Get a 32 bit CRC hash that identifies the + /// settings in this ON_SurfaceDraftAngleColorMapping. + /// + /// + /// If this->IsSet() is true, this->Hash()CRC32(0) is returned. + /// Otherwise 0 is returned. + /// + ON__UINT32 CRC32() const; + + /// + /// The returned mapping tag is ideal for setting the ON_SubD fragment and ON_Mesh + /// per vertex color tag when the colors are set by calling this->Color() + /// on the per vertex principal surface curvatures. + /// + /// + /// If this->IsSet() is true, a mapping tag with + /// type = ON_TextureMapping::TYPE::false_colors, + /// id = ON_SurfaceDraftAngleColorMapping::Id, + /// crc = this->CRC32() + /// xform = identity + /// is returned. Otherwise ON_MappingTag::Unset is returned. + /// + const ON_MappingTag ColorMappingTag() const; + + const ON_3dVector Up() const; + + const ON_Interval AngleRangeInRadians() const; + + const ON_Interval HueRangeInRadians() const; + +private: + mutable unsigned char m_is_set = 0; // 0 = not set, 1 = this is valid and set, 2 = unknown + ON__UINT8 m_reserved1 = 0; + ON__UINT16 m_reserved2 = 0; + ON__UINT32 m_reserved3 = 0; + ON_3dVector m_up = ON_3dVector::NanVector; + ON_Interval m_angle_range_in_radians = ON_Interval::Nan; + ON_Interval m_hue_range_in_radians = ON_SurfaceDraftAngleColorMapping::DefaultHueRangeRadians; +}; + +/// +/// Returns true if all properties of lhs and rhs are identical and no double is a nan. +/// +ON_DECL +bool operator==(const ON_SurfaceDraftAngleColorMapping& lhs, const ON_SurfaceDraftAngleColorMapping& rhs); + +/// +/// Returns true if some property of lhs and rhs is different and no double is a nan. +/// +ON_DECL +bool operator!=(const ON_SurfaceDraftAngleColorMapping& lhs, const ON_SurfaceDraftAngleColorMapping& rhs); + + class ON_CLASS ON_Mesh : public ON_Geometry { ON_OBJECT_DECLARE(ON_Mesh); @@ -3834,35 +4003,30 @@ Returns: /// /// /// - /// - /// - /// - /// When in doubt, use ON_MappingTag::DraftAngleColorHueRangeDefault. - /// + /// /// bool SetDraftAngleColorAnalysisColors( bool bLazy, - ON_3dVector up, - ON_Interval draft_angle_range_in_radians, - ON_Interval hue_range_in_radians + ON_SurfaceDraftAngleColorMapping draft_angle_colors ); /// - /// + /// Set the mesh's per vertex colors in m_C[] + /// from the surface principal curvatures in m_K[] /// - /// - /// - /// - /// - /// When in doubt, use ON_MappingTag::CurvatureColorHueRangeDefault. + /// + /// If bLazy is true, the mesh has curvatures and per vertex colors, + /// and m_Ctag == kappa_colors.ColorMappingTag(), then m_C[] is assumed to + /// be set correctly and no calculations are performed. + /// + /// + /// m_C[i] = kappa_colors.Color(m_K[i]) /// /// bool SetCurvatureColorAnalysisColors( bool bLazy, - const ON::curvature_style kappa_style, - ON_Interval kappa_range, - ON_Interval hue_range_in_radians + ON_SurfaceCurvatureColorMapping kappa_colors ); /* diff --git a/opennurbs_pointcloud.cpp b/opennurbs_pointcloud.cpp index 5a5edd1a..fd17d81c 100644 --- a/opennurbs_pointcloud.cpp +++ b/opennurbs_pointcloud.cpp @@ -680,3 +680,84 @@ ON_PointCloud* ON_PointCloud::RandomSubsample( return destination_point_cloud; } + +int ON_PointCloud::RemoveRange(const ON_SimpleArray& indices) +{ + return RemoveRange(indices.Count(), indices.Array()); +} + +int ON_PointCloud::RemoveRange(int count, const int* pIndices) +{ + const unsigned int point_count = m_P.UnsignedCount(); + if (0 == point_count || count <= 0 || nullptr == pIndices) + return 0; + + ON_SimpleArray indices(count); + indices.Append(count, pIndices); + indices.QuickSortAndRemoveDuplicates(ON_CompareDecreasing); + + const unsigned int index_count = indices.Count(); + if (index_count <= 0) + return 0; + + const bool bHaveNormals = point_count == m_N.UnsignedCount(); + const bool bHaveColors = point_count == m_C.UnsignedCount(); + const bool bHaveValues = point_count == m_V.UnsignedCount(); + const bool bHaveHidden = point_count == m_H.UnsignedCount(); + + unsigned int points_removed = 0; + unsigned int last_point_count = point_count; + for (unsigned int i = 0; i < index_count; i++) + { + const unsigned int point_index = indices[i]; + if (point_index >= 0 && point_index < point_count) + { + m_P.Swap(point_index, last_point_count - 1); + if (bHaveNormals) + m_N.Swap(point_index, last_point_count - 1); + if (bHaveColors) + m_C.Swap(point_index, last_point_count - 1); + if (bHaveValues) + m_V.Swap(point_index, last_point_count - 1); + if (bHaveHidden) + m_H.Swap(point_index, last_point_count - 1); + + points_removed++; + last_point_count--; + if (last_point_count <= 0) + break; + } + } + + m_P.SetCount(last_point_count); + m_P.Shrink(); + if (bHaveNormals) + { + m_N.SetCount(last_point_count); + m_N.Shrink(); + } + if (bHaveColors) + { + m_C.SetCount(last_point_count); + m_C.Shrink(); + } + if (bHaveValues) + { + m_V.SetCount(last_point_count); + m_V.Shrink(); + } + if (bHaveHidden) + { + m_H.SetCount(last_point_count); + m_H.Shrink(); + m_hidden_count = 0; + for (unsigned int i = 0; i < m_H.UnsignedCount(); i++) + { + if (m_H[i]) + m_hidden_count++; + } + InvalidateBoundingBox(); + } + + return points_removed; +} diff --git a/opennurbs_pointcloud.h b/opennurbs_pointcloud.h index 40ad12ee..7e5e40e3 100644 --- a/opennurbs_pointcloud.h +++ b/opennurbs_pointcloud.h @@ -228,6 +228,27 @@ public: ON_Terminator* terminator ); + /* + Description: + Removes points at given indices. + Parameters: + indices - [in] An array of indices of the points to remove. + Returns: + The number of points removed from the point cloud. + */ + int RemoveRange(const ON_SimpleArray& indices); + + /* + Description: + Removes points at given indices. + Parameters: + count - [in] The number of indices of the points to remove. + indices - [in] An array of indices of the points to remove. + Returns: + The number of points removed from the point cloud. + */ + int RemoveRange(int count, const int* indices); + ///////////////////////////////////////////////////////////////// // Implementation diff --git a/opennurbs_public_version.h b/opennurbs_public_version.h index 54e6365e..6f80424b 100644 --- a/opennurbs_public_version.h +++ b/opennurbs_public_version.h @@ -15,9 +15,9 @@ // #define RMA_VERSION_YEAR 2023 #define RMA_VERSION_MONTH 8 -#define RMA_VERSION_DATE 21 -#define RMA_VERSION_HOUR 4 -#define RMA_VERSION_MINUTE 30 +#define RMA_VERSION_DATE 22 +#define RMA_VERSION_HOUR 12 +#define RMA_VERSION_MINUTE 13 //////////////////////////////////////////////////////////////// // @@ -35,8 +35,8 @@ // 3 = build system release build #define RMA_VERSION_BRANCH 0 -#define VERSION_WITH_COMMAS 8,0,23233,4300 -#define VERSION_WITH_PERIODS 8.0.23233.04300 +#define VERSION_WITH_COMMAS 8,0,23234,12130 +#define VERSION_WITH_PERIODS 8.0.23234.12130 #define COPYRIGHT "Copyright (C) 1993-2023, Robert McNeel & Associates. All Rights Reserved." #define SPECIAL_BUILD_DESCRIPTION "Public OpenNURBS C++ 3dm file IO library." @@ -47,8 +47,8 @@ #define RMA_VERSION_NUMBER_SR_STRING "SR0" #define RMA_VERSION_NUMBER_SR_WSTRING L"SR0" -#define RMA_VERSION_WITH_PERIODS_STRING "8.0.23233.04300" -#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.0.23233.04300" +#define RMA_VERSION_WITH_PERIODS_STRING "8.0.23234.12130" +#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.0.23234.12130" diff --git a/opennurbs_render_content.cpp b/opennurbs_render_content.cpp index 8b524c80..7dca43c7 100644 --- a/opennurbs_render_content.cpp +++ b/opennurbs_render_content.cpp @@ -1653,7 +1653,7 @@ ON_Texture ON_RenderTexture::ToOnTexture(void) const if (p.GetParam(ON_TEXTURE_SIMULATION_OFFSET, v)) { - ON_3dVector offset, rotation, repeat; + ON_3dVector offset, repeat, rotation; tex.m_uvw.DecomposeTextureMapping(offset, repeat, rotation); const auto pt = v.As2dPoint(); offset.x = pt[0]; @@ -1663,7 +1663,7 @@ ON_Texture ON_RenderTexture::ToOnTexture(void) const if (p.GetParam(ON_TEXTURE_SIMULATION_REPEAT, v)) { - ON_3dVector offset, rotation, repeat; + ON_3dVector offset, repeat, rotation; tex.m_uvw.DecomposeTextureMapping(offset, repeat, rotation); const auto pt = v.As2dPoint(); repeat.x = pt[0]; @@ -1673,10 +1673,10 @@ ON_Texture ON_RenderTexture::ToOnTexture(void) const if (p.GetParam(ON_TEXTURE_SIMULATION_ROTATION, v)) { - ON_3dVector offset, rotation, repeat; + ON_3dVector offset, repeat, rotation; tex.m_uvw.DecomposeTextureMapping(offset, repeat, rotation); - const auto pt = v.As2dPoint(); // 'pt' is in degrees. - rotation.z = pt[0] * ON_DEGREES_TO_RADIANS; + const auto angle = v.AsDouble(); // 'angle' is in degrees. + rotation.z = angle * ON_DEGREES_TO_RADIANS; tex.m_uvw = ON_Xform::TextureMapping(offset, repeat, rotation); } diff --git a/opennurbs_statics.cpp b/opennurbs_statics.cpp index c57c9d3b..9c5b225b 100644 --- a/opennurbs_statics.cpp +++ b/opennurbs_statics.cpp @@ -1628,25 +1628,28 @@ const ON_MappingTag ON_MappingTag::Unset; const ON_MappingTag ON_MappingTag::SurfaceParameterMapping(ON_TextureMapping::SurfaceParameterTextureMapping,nullptr); // {639E9144-1C1A-4bba-8248-D330F50D7B69} -// RHINO_CURVATURE_COLOR_ANALYSIS_MODE_ID and ON_MappingTag::CurvatureColorAnalysisId +// RHINO_CURVATURE_COLOR_ANALYSIS_MODE_ID and ON_SurfaceCurvatureColorMapping::Id // are identical ids and must never be changed. -const ON_UUID ON_MappingTag::CurvatureColorAnalysisId = +const ON_UUID ON_SurfaceCurvatureColorMapping::Id = { 0x639e9144, 0x1c1a, 0x4bba, { 0x82, 0x48, 0xd3, 0x30, 0xf5, 0xd, 0x7b, 0x69 } }; // Hue range used by the Rhino surface curvature color analysis. // Currently red to blue. -const ON_Interval ON_MappingTag::CurvatureColorHueRangeDefault(0.0, 4.0 * ON_PI / 3.0); +const ON_Interval ON_SurfaceCurvatureColorMapping::DefaultHueRangeRadians(0.0, 4.0 * ON_PI / 3.0); +const ON_SurfaceCurvatureColorMapping ON_SurfaceCurvatureColorMapping::Unset; // {F08463F4-22E2-4cf1-B810-F01925446D71} -// RHINO_DRAFT_ANGLE_ANALYSIS_MODE_ID and ON_MappingTag::DraftAngleColorAnalysisId +// RHINO_DRAFT_ANGLE_ANALYSIS_MODE_ID and ON_SurfaceDraftAngleColorMapping::Id // are identical ids and must never be changed. -const ON_UUID ON_MappingTag::DraftAngleColorAnalysisId = +const ON_UUID ON_SurfaceDraftAngleColorMapping::Id = { 0xf08463f4, 0x22e2, 0x4cf1, { 0xb8, 0x10, 0xf0, 0x19, 0x25, 0x44, 0x6d, 0x71 } }; // Hue range used by the Rhino draft angle color analysis. // Currently red to blue. -const ON_Interval ON_MappingTag::DraftAngleColorHueRangeDefault(0.0, 4.0 * ON_PI / 3.0); +const ON_Interval ON_SurfaceDraftAngleColorMapping::DefaultHueRangeRadians(0.0, 4.0 * ON_PI / 3.0); + +const ON_SurfaceDraftAngleColorMapping ON_SurfaceDraftAngleColorMapping::Unset; const ON_LinetypeSegment ON_LinetypeSegment::Unset; const ON_LinetypeSegment ON_LinetypeSegment::OneMillimeterLine(1.0, ON_LinetypeSegment::eSegType::stLine); diff --git a/opennurbs_subd_fragment.cpp b/opennurbs_subd_fragment.cpp index ab7590ae..6eb9f2fd 100644 --- a/opennurbs_subd_fragment.cpp +++ b/opennurbs_subd_fragment.cpp @@ -730,14 +730,21 @@ void ON_SubD::ClearFragmentColors( const ON_SubDimple* subdimple = this->SubDimple(); if (nullptr != subdimple) { + bool bFragmentsChanged = false; ON_SubDMeshFragmentIterator fragit(*this); for (const ON_SubDMeshFragment* frag = fragit.FirstFragment(); nullptr != frag; frag = fragit.NextFragment()) + { + if (false == bFragmentsChanged && frag->ColorCount() > 0) + bFragmentsChanged = true; frag->SetColorsExistForExperts(false); + } if (bClearFragmentColorsMappingTag) { subdimple->Internal_SetFragmentColorsSettingsHash(ON_SHA1_Hash::EmptyContentHash); this->SetFragmentColorsMappingTag(ON_MappingTag::Unset); } + if (bFragmentsChanged) + this->ChangeRenderContentSerialNumber(); } } diff --git a/opennurbs_xform.cpp b/opennurbs_xform.cpp index 098462e2..d5f646c1 100644 --- a/opennurbs_xform.cpp +++ b/opennurbs_xform.cpp @@ -1834,9 +1834,61 @@ double ON_Xform::Determinant( double* pivot ) const *pivot = p; if (d != 0.0 ) d = 1.0/d; + return d; } +int ON_Xform::SignOfDeterminant(bool bFastTest) const +{ + if (bFastTest) + { + if ( + (0.0 == m_xform[3][0] && 0.0 == m_xform[3][1] && 0.0 == m_xform[3][2]) + || + (0.0 == m_xform[0][3] && 0.0 == m_xform[1][3] && 0.0 == m_xform[2][3]) + ) + { + // vast majority of the 4x4 cases in practice. + + if (0.0 == m_xform[3][3]) + { + return 0; // 100% accurate result. + } + + // Use the simple 3x3 formula with the fewest flops. + const double x + = m_xform[0][0] * (m_xform[1][1] * m_xform[2][2] - m_xform[1][2] * m_xform[2][1]) + + m_xform[0][1] * (m_xform[1][2] * m_xform[2][0] - m_xform[1][0] * m_xform[2][2]) + + m_xform[0][2] * (m_xform[1][0] * m_xform[2][1] - m_xform[1][1] * m_xform[2][0]); + + if (0.0 == x) + { + // It is very likely we had a simple case and, mathematically, det = 0. + // (not a 100% safe assumption, but good enough for bFastTest = true case). + return 0; + } + + if (fabs(x) > 1e-8) + { + // x is big enough that it's very likely the sign is mathematically correct. + // (not a 100% safe assumption, but good enough for bFastTest = true case). + const int s = ((x < 0.0) ? -1 : 1) * ((m_xform[3][3] < 0.0) ? -1 : 1); + return s; + } + } + } + + // do it a very slow and careful way + double min_pivot = 0.0; + const double det = this->Determinant(&min_pivot); + if (fabs(min_pivot) > ON_ZERO_TOLERANCE && fabs(det) > ON_ZERO_TOLERANCE) + { + return (det < 0.0) ? -1 : 1; + } + + return 0; +} + bool ON_Xform::Invert( double* pivot ) { double mrofx[4][4], d = 0.0, p = 0.0; diff --git a/opennurbs_xform.h b/opennurbs_xform.h index 8c9bddf9..d6fcd341 100644 --- a/opennurbs_xform.h +++ b/opennurbs_xform.h @@ -411,9 +411,34 @@ public: double* = nullptr // If not nullptr, returns minimum pivot ) const; + /// + /// If you need a slow and accurate determinant, this is the function to call. + /// If you need a fast sign check, used SignOfDeterminant(true). + /// + /// + /// If not nullptr, returns the minimum pivot + /// + /// The determinant of 4x4 matrix double - Determinant( // returns determinant of 4x4 matrix - double* = nullptr // If not nullptr, returns minimum pivot + Determinant( + double* minimum_pivot = nullptr // + ) const; + + /// + /// Quickly determine the sign of the determinant. + /// Definitely good enough for graphics code. + /// + /// + /// When in double, pass true. + /// If you need a fast answer and can tolerate extremely rare wrong answers, + /// pass true. True definitely works for all common matrices used to transform + /// 3d objects and all common view projection matrices. + /// + /// + /// +1, 0, or -1. + /// + int SignOfDeterminant( + bool bFastTest ) const; bool