From 31173293f943610a132a761494ec404136985335 Mon Sep 17 00:00:00 2001 From: Bozo the Builder Date: Fri, 28 Feb 2025 03:44:09 -0800 Subject: [PATCH] Sync changes from upstream repository --- opennurbs_array.cpp | 6 +-- opennurbs_dimension.cpp | 26 ++++++------ opennurbs_point.cpp | 31 ++++++++++++++ opennurbs_point.h | 26 ++++++++++++ opennurbs_polycurve.cpp | 76 +++++++++++++-------------------- opennurbs_public_version.h | 18 ++++---- opennurbs_subd.cpp | 87 ++++++++++++++++++++++++++++++++------ 7 files changed, 186 insertions(+), 84 deletions(-) diff --git a/opennurbs_array.cpp b/opennurbs_array.cpp index 8017d342..8c870636 100644 --- a/opennurbs_array.cpp +++ b/opennurbs_array.cpp @@ -1189,9 +1189,9 @@ ON_UuidPtr* ON_UuidPtrList::SearchHelper(const ON_UUID* uuid) const return p; } -static_assert(sizeof(ON_UuidPairList) == sizeof(ON_UuidPairList2), "ON_UuidPairList and ON_UuidPairList2 are not the same size"); -static_assert(sizeof(ON_UuidPtrList) == sizeof(ON_UuidPtrList2), "ON_UuidPtrList and ON_UuidPtrList2 are not the same size"); -static_assert(sizeof(ON_UuidIndexList) == sizeof(ON_UuidIndexList2), "ON_UuidIndexList and ON_UuidIndexList2 are not the same size"); +// static_assert(sizeof(ON_UuidPairList) == sizeof(ON_UuidPairList2), "ON_UuidPairList and ON_UuidPairList2 are not the same size"); +// static_assert(sizeof(ON_UuidPtrList) == sizeof(ON_UuidPtrList2), "ON_UuidPtrList and ON_UuidPtrList2 are not the same size"); +// static_assert(sizeof(ON_UuidIndexList) == sizeof(ON_UuidIndexList2), "ON_UuidIndexList and ON_UuidIndexList2 are not the same size"); template struct ON_UuidList2_Private diff --git a/opennurbs_dimension.cpp b/opennurbs_dimension.cpp index fea4d83a..484fb035 100644 --- a/opennurbs_dimension.cpp +++ b/opennurbs_dimension.cpp @@ -765,18 +765,20 @@ bool ON_DimLinear::GetTextXform( ON_3dPoint text_center = ON_3dPoint::Origin; // Text starts out approximately centered at origin ON_3dPoint cp[4]; - if (!text->Get3dCorners(cp)) - return false; - - text_center = (cp[0] + cp[2]) / 2.0; - text_width = (cp[1].x - cp[0].x) * dimscale; - text_height = (cp[3].y - cp[0].y) * dimscale; - - text_gap = dimstyle->TextGap(); - if (dimstyle->MaskFrameType() != ON_TextMask::MaskFrame::NoFrame) - text_gap += dimstyle->TextMask().MaskBorder(); // RH-71452 - text_gap *= dimscale; - + // 06 Feb 2025 - Jeff: https://mcneel.myjetbrains.com/youtrack/issue/RH-84156 + // Don't exit just because the corners don't exist (i.e. no text or zero-length text). + // We still need the transform to get computed. + if (text->Get3dCorners(cp)) + { + text_center = (cp[0] + cp[2]) / 2.0; + text_width = (cp[1].x - cp[0].x) * dimscale; + text_height = (cp[3].y - cp[0].y) * dimscale; + + text_gap = dimstyle->TextGap(); + if (dimstyle->MaskFrameType() != ON_TextMask::MaskFrame::NoFrame) + text_gap += dimstyle->TextMask().MaskBorder(); // RH-71452 + text_gap *= dimscale; + } if (dimstyle->Alternate() && dimstyle->AlternateBelow()) text_height = -2.0 * text_gap; diff --git a/opennurbs_point.cpp b/opennurbs_point.cpp index e4ebbf34..b021f43f 100644 --- a/opennurbs_point.cpp +++ b/opennurbs_point.cpp @@ -670,6 +670,37 @@ ON_Interval ON_Interval::NormalizedParameterAt( // returns x so that min*(1.0-x) NormalizedParameterAt(t[1]) ); } +double ON_Interval::TransformParameterTo(const ON_Interval& target, double t) const +{ + // 31-JAN-2025 MDvR: + // This function was created to fix https://mcneel.myjetbrains.com/youtrack/issue/RH-85831 + // The bug was a result conversions of ON_PolyCurve parameters at PolyCurve segment ends + // to/from Nurbs form curve parameters. + if (!IsValid() || !target.IsValid()) + { + return ON_DBL_QNAN; + } + + if (*this == target) + { + return t; + } + + double s = NormalizedParameterAt(t); + double L1 = std::max(std::abs(target.m_t[0]), std::abs(target.m_t[1])); + double L2 = std::max(std::abs(m_t[0]), std::abs(m_t[1])); + double L = std::max(L1, L2); + if (abs(s / L) < ON_EPSILON) + { + s = 0.0; + } + else if (abs((s - 1.0) / L) < ON_EPSILON) + { + s = 1.0; + } + return target.ParameterAt(s); +} + double ON_Interval::Max() const { diff --git a/opennurbs_point.h b/opennurbs_point.h index 8f851aa3..1c7e218d 100644 --- a/opennurbs_point.h +++ b/opennurbs_point.h @@ -179,6 +179,32 @@ class ON_CLASS ON_Interval double interval_parameter ) const; + + /// + /// Transforms a parameter from the current interval to the target interval. + /// It is effectively target.ParameterAt(this.NormalizedParameterAt(t)) + /// with additional checks when t is very close to the end of this interval. + /// It is useful when the calculation of t may have introduced rounding errors. + /// + /// Specifically, there are cases where t is extremely close to and end of + /// this interval, target.ParameterAt(this.NormalizedParameterAt(t)) + /// will return values that are very near but not exactly at the end of + /// the target interval, and + /// TransformParameterTo() will return a parameter at the exact end of the + /// target interval. This behavior is desired in some cases like + /// converting ON_PolyCurve parameters to NurbsForm parameters when the + /// polycurve parameter is at a segment. + /// + /// Target interval + /// Input parameter + /// + /// The input parameter in the target interval. + /// Returns input paramter unchanged if both intervals are identical. + /// Returns ON_DBL_QNAN if either interval is not valid. + /// + double TransformParameterTo(const ON_Interval& target, double t) const; + + double& operator[](int); // returns (index<=0) ? m_t[0] : m_t[1] double operator[](int) const; // returns (index<=0) ? m_t[0] : m_t[1] double& operator[](unsigned int); // returns (index<=0) ? m_t[0] : m_t[1] diff --git a/opennurbs_polycurve.cpp b/opennurbs_polycurve.cpp index c9d826a4..8178eb03 100644 --- a/opennurbs_polycurve.cpp +++ b/opennurbs_polycurve.cpp @@ -639,9 +639,7 @@ bool ON_PolyCurve::ChangeClosedCurveSeam( double t ) if ( scrv ) { ON_Interval sdom = scrv->Domain(); - double s = ( old_dom == sdom ) - ? t - : sdom.ParameterAt( old_dom.NormalizedParameterAt(t) ); + double s = old_dom.TransformParameterTo(sdom, t); rc = scrv->ChangeClosedCurveSeam(s); if ( rc ) SetDomain( t, t + old_dom.Length() ); @@ -856,11 +854,8 @@ int ON_PolyCurve::IsPolyline( { sdom.Set(m_t[0],m_t[1]); cdom = m_segment[0]->Domain(); - if ( sdom != cdom ) - { - for ( i = 0; i < pline_t->Count(); i++ ) - (*pline_t)[i] = sdom.ParameterAt(cdom.NormalizedParameterAt((*pline_t)[i])); - } + for ( i = 0; i < pline_t->Count(); i++ ) + (*pline_t)[i] = cdom.TransformParameterTo(sdom, (*pline_t)[i]); } } else if (seg_count > 1 ) @@ -888,11 +883,10 @@ int ON_PolyCurve::IsPolyline( { sdom.Set( m_t[seg_i], m_t[seg_i+1] ); cdom = m_segment[seg_i]->Domain(); - if ( sdom != cdom ) - { - for ( i = 0; i < seg_t.Count(); i++ ) - seg_t[i] = sdom.ParameterAt(cdom.NormalizedParameterAt(seg_t[i])); - } + + for (i = 0; i < seg_t.Count(); i++) + seg_t[i] = cdom.TransformParameterTo(sdom, seg_t[i]); + if ( pline_t->Count() > 0 ) pline_t->Remove(); pline_t->Append( seg_t.Count(), seg_t.Array() ); @@ -1909,16 +1903,8 @@ bool ON_PolyCurve::GetNextDiscontinuity( cdom = crv->Domain(); sdom.Set( m_t[segment_index], m_t[segment_index+1] ); - if ( sdom == cdom ) - { - s0 = t0; - s1 = t1; - } - else - { - s0 = cdom.ParameterAt( sdom.NormalizedParameterAt(t0) ); - s1 = cdom.ParameterAt( sdom.NormalizedParameterAt(t1) ); - } + s0 = sdom.TransformParameterTo(cdom, t0); + s1 = sdom.TransformParameterTo(cdom, t1); rc = crv->GetNextDiscontinuity( c, s0, s1, &s, &curve_hint, dtype, cos_angle_tolerance, curvature_tolerance ); if ( rc ) { @@ -1929,7 +1915,7 @@ bool ON_PolyCurve::GetNextDiscontinuity( } else { - kink_t = sdom.ParameterAt( cdom.NormalizedParameterAt(s) ); + kink_t = cdom.TransformParameterTo(sdom, s); double t_tol = (fabs(t0)+fabs(t1)+fabs(t0-t1))*ON_ZERO_TOLERANCE; if ( kink_t <= tmin+t_tol || kink_t >= tmax-t_tol) { @@ -1961,7 +1947,7 @@ bool ON_PolyCurve::GetNextDiscontinuity( rc = crv->GetNextDiscontinuity( c, s0, s1, &s, &curve_hint, dtype, cos_angle_tolerance, curvature_tolerance ); if (rc) { - kink_t = sdom.ParameterAt( cdom.NormalizedParameterAt(s) ); + kink_t = cdom.TransformParameterTo(sdom, s); if ( kink_t <= tmin || kink_t >= tmax ) rc = false; } @@ -2253,8 +2239,7 @@ bool ON_PolyCurve::IsContinuous( ON_Interval sdom, cdom; cdom = segment_curve->Domain(); sdom.Set( m_t[segment_index], m_t[segment_index+1] ); - if ( sdom != cdom ) - t = cdom.ParameterAt( sdom.NormalizedParameterAt(t) ); + t = sdom.TransformParameterTo(cdom, t); rc = segment_curve->IsContinuous( desired_continuity, t, &curve_hint, point_tolerance, d1_tolerance, d2_tolerance, cos_angle_tolerance, curvature_tolerance ); @@ -3011,10 +2996,11 @@ bool ON_PolyCurve::GetCurveParameterFromNurbFormParameter( ON_Interval in( m_t[i], m_t[i+1] ); ON_Interval cdom = curve->Domain(); if ( in != cdom ) { - nurbs_t = cdom.ParameterAt(in.NormalizedParameterAt(nurbs_t)); + + nurbs_t = in.TransformParameterTo(cdom, nurbs_t); rc = curve->GetCurveParameterFromNurbFormParameter(nurbs_t,curve_t); - if ( rc ) - *curve_t = in.ParameterAt(cdom.NormalizedParameterAt(*curve_t)); + if (rc) + *curve_t = cdom.TransformParameterTo(in, *curve_t); } else { rc = curve->GetCurveParameterFromNurbFormParameter(nurbs_t,curve_t); @@ -3035,10 +3021,10 @@ bool ON_PolyCurve::GetNurbFormParameterFromCurveParameter( ON_Interval in( m_t[i], m_t[i+1] ); ON_Interval cdom = curve->Domain(); if ( in != cdom ) { - curve_t = cdom.ParameterAt(in.NormalizedParameterAt(curve_t)); + curve_t = in.TransformParameterTo(cdom, curve_t); rc = curve->GetNurbFormParameterFromCurveParameter(curve_t,nurbs_t); - if ( rc ) - *nurbs_t = in.ParameterAt(cdom.NormalizedParameterAt(*nurbs_t)); + if (rc) + *nurbs_t = cdom.TransformParameterTo(in, *nurbs_t); } else { rc = curve->GetNurbFormParameterFromCurveParameter(curve_t,nurbs_t); @@ -3242,8 +3228,8 @@ bool ON_PolyCurve::Trim( if ( c_dom != s_dom ) { // need to convert polycurve parameters to "real" segment curve parameters - trim_c_dom[0] = c_dom.ParameterAt( s_dom.NormalizedParameterAt(trim_s_dom[0]) ); - trim_c_dom[1] = c_dom.ParameterAt( s_dom.NormalizedParameterAt(trim_s_dom[1]) ); + trim_c_dom[0] = s_dom.TransformParameterTo(c_dom, trim_s_dom[0]); + trim_c_dom[1] = s_dom.TransformParameterTo(c_dom, trim_s_dom[1]); if ( !trim_c_dom.IsIncreasing() ) { if ( s_dom.NormalizedParameterAt(trim_s_dom[0]) >= 1.0-fuzz && s1 > 0 ) @@ -3348,7 +3334,7 @@ bool ON_PolyCurve::Trim( trim_c_dom[0] = c_dom[0]; if ( c_dom != s_dom ) { - trim_c_dom[1] = c_dom.ParameterAt( s_dom.NormalizedParameterAt(trim_s_dom[1]) ); + trim_c_dom[1] = s_dom.TransformParameterTo(c_dom, trim_s_dom[1]); if ( !trim_c_dom.IsIncreasing() ) { if ( s_dom.NormalizedParameterAt(trim_s_dom[1]) <= fuzz && s1 > 0 ) @@ -3433,14 +3419,14 @@ bool ON_PolyCurve::Extend( if (!seg) return false; ON_Interval sdom = SegmentDomain(0); ON_Interval cdom = seg->Domain(); - double a = (sdom == cdom) ? domain[0] : cdom.ParameterAt(sdom.NormalizedParameterAt(domain[0])); + double a = sdom.TransformParameterTo(cdom, domain[0]); ON_Interval DesiredDom(a, cdom[1]); changed = seg->Extend(DesiredDom); if (changed) { if (seg->Domain() == DesiredDom) m_t[0] = domain[0]; else - m_t[0] = sdom.ParameterAt(cdom.NormalizedParameterAt(seg->Domain()[0])); + m_t[0] = cdom.TransformParameterTo(sdom, seg->Domain()[0]); } } if (Domain()[1] < domain[1]){ @@ -3449,14 +3435,14 @@ bool ON_PolyCurve::Extend( if (!seg) return false; ON_Interval sdom = SegmentDomain(Count()-1); ON_Interval cdom = seg->Domain(); - double a = (sdom == cdom) ? domain[1] : cdom.ParameterAt(sdom.NormalizedParameterAt(domain[1])); + double a = sdom.TransformParameterTo(cdom, domain[1]); ON_Interval DesiredDom(cdom[0], a); chgd = seg->Extend(DesiredDom); if (chgd) { if (seg->Domain() == DesiredDom) m_t[Count()] = domain[1]; else - m_t[Count()] = sdom.ParameterAt(cdom.NormalizedParameterAt(seg->Domain()[1])); + m_t[Count()] = cdom.TransformParameterTo(sdom, seg->Domain()[1]); changed = true; } } @@ -3521,12 +3507,10 @@ bool ON_PolyCurve::Split( ON_Interval c_dom = seg_curve->Domain(); double c; - if( split_at_break) - c = c_dom[0]; - else - c = ( c_dom == s_dom ) - ? split_parameter - : c_dom.ParameterAt( s_dom.NormalizedParameterAt(split_parameter) ); + if (split_at_break) + c = c_dom[0]; + else + c = s_dom.TransformParameterTo(c_dom, split_parameter); ON_Curve* seg_left = 0; ON_Curve* seg_right = 0; diff --git a/opennurbs_public_version.h b/opennurbs_public_version.h index cbdd0060..63f142a8 100644 --- a/opennurbs_public_version.h +++ b/opennurbs_public_version.h @@ -6,7 +6,7 @@ // To update version numbers, edit ..\build\build_dates.msbuild #define RMA_VERSION_MAJOR 8 -#define RMA_VERSION_MINOR 16 +#define RMA_VERSION_MINOR 17 //////////////////////////////////////////////////////////////// // @@ -15,8 +15,8 @@ // #define RMA_VERSION_YEAR 2025 #define RMA_VERSION_MONTH 2 -#define RMA_VERSION_DATE 11 -#define RMA_VERSION_HOUR 13 +#define RMA_VERSION_DATE 27 +#define RMA_VERSION_HOUR 17 #define RMA_VERSION_MINUTE 0 //////////////////////////////////////////////////////////////// @@ -35,8 +35,8 @@ // 3 = build system release build #define RMA_VERSION_BRANCH 0 -#define VERSION_WITH_COMMAS 8,16,25042,13000 -#define VERSION_WITH_PERIODS 8.16.25042.13000 +#define VERSION_WITH_COMMAS 8,17,25058,17000 +#define VERSION_WITH_PERIODS 8.17.25058.17000 #define COPYRIGHT "Copyright (C) 1993-2025, Robert McNeel & Associates. All Rights Reserved." #define SPECIAL_BUILD_DESCRIPTION "Public OpenNURBS C++ 3dm file IO library." @@ -44,11 +44,11 @@ #define RMA_VERSION_NUMBER_MAJOR_WSTRING L"8" #define RMA_PREVIOUS_VERSION_NUMBER_MAJOR_WSTRING L"7" -#define RMA_VERSION_NUMBER_SR_STRING "SR16" -#define RMA_VERSION_NUMBER_SR_WSTRING L"SR16" +#define RMA_VERSION_NUMBER_SR_STRING "SR17" +#define RMA_VERSION_NUMBER_SR_WSTRING L"SR17" -#define RMA_VERSION_WITH_PERIODS_STRING "8.16.25042.13000" -#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.16.25042.13000" +#define RMA_VERSION_WITH_PERIODS_STRING "8.17.25058.17000" +#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.17.25058.17000" diff --git a/opennurbs_subd.cpp b/opennurbs_subd.cpp index 196083f5..4f72b64c 100644 --- a/opennurbs_subd.cpp +++ b/opennurbs_subd.cpp @@ -14276,19 +14276,52 @@ bool ON_SubDFace::ReverseEdgeList() return ON_SUBD_RETURN_ERROR(false); } - ON_SubDEdgePtr buffer[16]; - ON_SubDEdgePtr* reversed_eptrs; - if ( edge_count <= sizeof(buffer)/sizeof(buffer[0]) ) - reversed_eptrs = buffer; + bool has_tpoints{ TexturePointsAreSet() }; + constexpr int buffer_size = 16; + ON_SubDEdgePtr eptr_buffer[buffer_size]{}; + ON_3dPoint tpoint_buffer[buffer_size]{}; + ON_SubDEdgePtr* reversed_eptrs{ nullptr }; + ON_3dPoint* reversed_tpoints{ nullptr }; + if (edge_count <= buffer_size) { + reversed_eptrs = eptr_buffer; + reversed_tpoints = tpoint_buffer; + } else { reversed_eptrs = new(std::nothrow) ON_SubDEdgePtr[edge_count]; - if ( nullptr == reversed_eptrs) - return ON_SUBD_RETURN_ERROR(false); + if (has_tpoints) + reversed_tpoints = new(std::nothrow) ON_3dPoint[edge_count]; + } + + + if (nullptr == reversed_eptrs) + return ON_SUBD_RETURN_ERROR(false); + if (has_tpoints && nullptr == reversed_tpoints) + { + has_tpoints = false; + ClearTexturePoints(); + } + + if (!has_tpoints) + { + for (unsigned int fei = 0; fei < edge_count; fei++) + { + reversed_eptrs[fei] = ON_SubDEdgePtr::Null; + } } + else + { + for (unsigned int fei = 0; fei < edge_count; fei++) + { + reversed_eptrs[fei] = ON_SubDEdgePtr::Null; + reversed_tpoints[fei] = ON_3dPoint::UnsetPoint; + } + } + ON_SubDEdgePtr* face_eptrs = m_edge4; - for (unsigned int fei = 0; fei < edge_count; fei++, face_eptrs++) + ON_3dPoint* face_tpoints = m_texture_points; + for (unsigned int fei = 0; fei < edge_count; fei++, face_eptrs++, face_tpoints++) { if (4 == fei) face_eptrs = m_edgex; @@ -14313,19 +14346,45 @@ bool ON_SubDFace::ReverseEdgeList() continue; *edges_fptrs = ON_SubDFacePtr::Create(this,1-ON_SUBD_FACE_DIRECTION(edges_fptrs->m_ptr)); break; - } + } + + if (has_tpoints) + { + if (fei == 0) + reversed_tpoints[0] = *face_tpoints; + else + reversed_tpoints[edge_count - fei] = *face_tpoints; + } } - face_eptrs = m_edge4; - for (unsigned int fei = 0; fei < edge_count; fei++) + if (!has_tpoints) { - if (4 == fei) - face_eptrs = m_edgex; - *face_eptrs++ = reversed_eptrs[fei]; + face_eptrs = m_edge4; + for (unsigned int fei = 0; fei < edge_count; fei++, face_eptrs++) + { + if (4 == fei) + face_eptrs = m_edgex; + *face_eptrs = reversed_eptrs[fei]; + } + } + else + { + face_eptrs = m_edge4; + face_tpoints = m_texture_points; + for (unsigned int fei = 0; fei < edge_count; fei++, face_eptrs++, face_tpoints++) + { + if (4 == fei) + face_eptrs = m_edgex; + *face_eptrs = reversed_eptrs[fei]; + *face_tpoints = reversed_tpoints[fei]; + } } - if ( reversed_eptrs != buffer ) + if (reversed_eptrs != eptr_buffer) { delete[] reversed_eptrs; + if (has_tpoints) + delete[] reversed_tpoints; + } return true; }