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