0033787: Refactor Geom_UndefinedValue exception handling to boolean returns#48
0033787: Refactor Geom_UndefinedValue exception handling to boolean returns#48
Conversation
…eturns Replace exception-based error handling with boolean return values for Geom_UndefinedValue. This change improves code maintainability and performance by eliminating exception throwing in normal control flow. Changes: - GeomEvaluator_OffsetSurface: Modified Calculate* methods to return Standard_Boolean indicating success/failure instead of throwing exceptions. Updated callers to check return values. - GeomFill_Darboux: Refactored static Normal* helper functions to return Standard_Boolean. Updated call sites to check return values and propagate failures. - Geom_OffsetSurface: Removed CHECK ifdef block that threw exception. - Geom_UndefinedValue: Marked exception class and macro as deprecated using Standard_DEPRECATED with guidance to use boolean returns. All changes follow OCCT naming conventions (a/an/the + camel case).
|
Warning Rate limit exceeded@dpasukhi has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 14 minutes and 54 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (4)
WalkthroughThe PR replaces exception/out-parameter evaluation patterns with explicit success signalling across the geometry stack. GeomFill_Darboux NormalD0/D1/D2 now return Standard_Boolean and callers propagate failures. GeomEvaluator interfaces and implementations (GeomEvaluator_Surface, OffsetSurface, SurfaceOfExtrusion, SurfaceOfRevolution and helpers) now return std::optional result structs for D0/D1/D2/D3/DN. Geom_OffsetSurface and other Geom_* callers consume optionals and either propagate failures or raise the deprecated Geom_UndefinedValue; Geom_Surface gains optional-based APIs while retaining deprecated output-parameter wrappers. Pre-merge checks❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/ModelingData/TKG3d/Geom/Geom_UndefinedValue.hxx (1)
25-41: Redundant deprecation annotations across forward declaration and definition.Both the forward declaration (lines 25–28) and the exception definition (line 40) include deprecation comments and/or attributes. While this redundancy is harmless, it may be cleaner to reserve the full deprecation guidance (message and comment) for the actual definition (line 40–41) rather than repeating it on the forward declaration.
If the syntax check confirms that
Standard_DEPRECATEDworks correctly on forward declarations, consider removing the deprecation attribute from the forward declaration and keeping the full deprecation documentation only on the definition for clarity.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
src/ModelingAlgorithms/TKGeomAlgo/GeomFill/GeomFill_Darboux.cxx(9 hunks)src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx(0 hunks)src/ModelingData/TKG3d/Geom/Geom_UndefinedValue.hxx(1 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx(14 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.hxx(1 hunks)
💤 Files with no reviewable changes (1)
- src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-13T22:08:43.235Z
Learnt from: CR
Repo: dpasukhi/OCCT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-13T22:08:43.235Z
Learning: Applies to src/**/*.@(cxx|hxx) : ALWAYS use Handle(ClassName) for any class inheriting from Standard_Transient (e.g., Geom_*, Poly_*, AIS_*, V3d_*) instead of raw pointers.
Applied to files:
src/ModelingData/TKG3d/Geom/Geom_UndefinedValue.hxx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Prepare and Build on macOS with Clang (No PCH)
- GitHub Check: Prepare and Build on Ubuntu with Clang (x64)
- GitHub Check: Prepare and Build on macOS with Clang (x64)
- GitHub Check: Build Documentation
- GitHub Check: Prepare and Build on Windows with MSVC (x64)
🔇 Additional comments (2)
src/ModelingData/TKG3d/Geom/Geom_UndefinedValue.hxx (2)
32-35: Deprecation guidance is clear and actionable.The deprecation comment and macro remain functional while signaling developers to migrate to boolean returns. This supports the gradual migration outlined in the PR objectives.
25-28: ****The syntax pattern used in lines 27–28 is valid and consistent with established codebase conventions. The
class Standard_DEPRECATED(...) ClassName;syntax across separate lines is not unusual—it's the standard pattern used throughout OCCT for deprecated classes (BRepMesh_FastDiscret, TCollection, Message_ProgressSentry, and others). The Standard_DEPRECATED macro correctly expands to compiler attributes (__declspec, attribute) that fully support application to forward declarations. The deprecation strategy is sound and follows best practices in this codebase.Likely an incorrect or invalid review comment.
Address code review feedback by completely eliminating exception throws:
1. GeomEvaluator_OffsetSurface (GeomEvaluator_OffsetSurface.cxx:277-456)
- Changed D0, D1, D2, D3 to return early without throwing when calculation
fails (output parameters remain unmodified)
- Changed DN to return zero vector (0,0,0) when calculation fails
- All methods now use early return instead of throw Geom_UndefinedValue
2. GeomFill_Darboux (GeomFill_Darboux.cxx:504-538)
- Fixed GetAverageLaw() to check D0() return value before accumulating
- Skip failed samples and adjust averaging denominator (aSuccessCount)
- Prevents accumulation of uninitialized/garbage values
3. Geom_UndefinedValue (Geom_UndefinedValue.hxx:25-40)
- Cleaned up redundant deprecation annotations
- Kept deprecation attribute and documentation on forward declaration only
- Removed duplicate deprecation comment from DEFINE_STANDARD_EXCEPTION
All changes maintain OCCT naming conventions (a/an/the + camel case).
No exceptions are thrown in normal control flow.
…zero When offset correction fails in DN(), return the base surface derivative without offset correction instead of zero vector. This is consistent with how D0/D1/D2/D3 handle failures (returning uncorrected values) and provides a meaningful fallback rather than an arbitrary zero vector. Changes: - GeomEvaluator_OffsetSurface::DN() now returns base surface DN when offset calculation fails, matching the behavior pattern of other methods
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (1)
425-462: Inconsistent failure handling between DN and D0-D3 methods.The
DNmethod provides a fallback by returning the base surface derivative when offset calculation fails (lines 455-458), whileD0,D1,D2, andD3methods return early with partially computed output parameters. This inconsistency in error handling behavior could be confusing.Consider either:
- Applying a consistent fallback strategy across all derivative methods
- Making all methods return
Standard_Booleanto explicitly signal success/failure to callers- Documenting why DN has different failure semantics
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx(14 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Prepare and Build on Windows with MSVC (x64)
- GitHub Check: Prepare and Build on macOS with Clang (No PCH)
- GitHub Check: Prepare and Build on Ubuntu with Clang (x64)
- GitHub Check: Build Documentation
- GitHub Check: Prepare and Build on macOS with Clang (x64)
🔇 Additional comments (5)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (5)
560-643: Boolean return implementation looks correct.The refactoring properly returns
Standard_Falsewhen normal calculation fails (line 638) andStandard_Trueon success (line 642). The logic correctly handles both singular and non-singular cases.
645-805: Boolean return implementation is correct.The method properly handles both non-singular (line 723) and singular cases, returning appropriate boolean values at all exit points.
807-897: Boolean return implementation is correct.The method correctly returns
Standard_Falsewhen normal calculation fails andStandard_Trueon success.
899-999: Boolean return implementation is correct.The method correctly returns
Standard_Falsewhen normal calculation fails andStandard_Trueon success.
1001-1086: Boolean return with output parameter is correctly implemented.The refactored signature using an output parameter
theResult(line 1007) combined with a boolean return value provides clear success/failure semantics. The implementation correctly populates the output parameter and returns appropriate status at all exit points.
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx
Outdated
Show resolved
Hide resolved
Document the 3-level error handling strategy used throughout: 1. Try to calculate offset-corrected values at requested point 2. If normal calculation fails (e.g., at singular points), try at shifted point 3. If both fail, return base surface values without offset correction as fallback This strategy provides: - Graceful degradation rather than throwing exceptions - Meaningful fallback (base surface geometry) rather than invalid/undefined values - Consistent behavior across all derivative methods (D0, D1, D2, D3, DN) Added detailed comments in all public derivative methods to explain the error handling behavior and rationale for returning base surface values when offset correction cannot be computed.
Replace exception-throwing and output parameters with std::optional returns
to provide type-safe error handling in surface evaluators.
Changes:
- Updated GeomEvaluator_Surface base class:
* D0/D1/D2/D3/DN now return std::optional instead of void
* Created result structures (D1Result, D2Result, D3Result) to bundle
point and derivative values
* Added comprehensive documentation for return values
- Updated GeomEvaluator_OffsetSurface:
* Converted all public D0/D1/D2/D3/DN methods to return std::optional
* Updated internal Calculate* methods to return std::optional
* Removed fallback returns to base surface on calculation failure
* Returns std::nullopt on error instead of throwing or silent fallback
- Updated GeomEvaluator_SurfaceOfExtrusion:
* Converted all D0/D1/D2/D3/DN methods to return std::optional
* These methods always succeed, so always return a value
- Updated GeomEvaluator_SurfaceOfRevolution:
* Converted all D0/D1/D2/D3/DN methods to return std::optional
* These methods always succeed, so always return a value
Note: Callers of these evaluator methods will need to be updated to handle
std::optional return values. This commit only updates the evaluator classes
themselves.
Related to #0033787 - Geom_UndefinedValue exception refactoring
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (1)
265-441: Update all Geom_OffsetSurface.cxx calls to handle std::optional returns and new signatures.The API change has not been applied to calling code. All five methods at lines 320, 338, 360, 387, and 409 in
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxxare calling the old signatures:
myEvaluator->D0(U, V, P)should use:auto opt = myEvaluator->D0(U, V); if (opt) P = *opt; else ...myEvaluator->D1(U, V, P, D1U, D1V)should use:auto opt = myEvaluator->D1(U, V); if (opt) { P = opt->P; D1U = opt->D1U; D1V = opt->D1V; } else ...myEvaluator->D2(...)andmyEvaluator->D3(...)follow the same patternD = myEvaluator->DN(U, V, Nu, Nv)should use:auto opt = myEvaluator->DN(...); D = opt ? *opt : gp_Vec(0,0,0);or appropriate error handling
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx(14 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.hxx(2 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_Surface.hxx(1 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.cxx(1 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.hxx(1 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.cxx(1 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.hxx(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: dpasukhi/OCCT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-13T22:08:43.235Z
Learning: Applies to src/**/*.cxx : After using an API that performs a geometric operation (e.g., BRepAlgoAPI_Fuse, BRepBuilderAPI_MakeEdge), ALWAYS check if the operation was successful using the IsDone() method before accessing the result.
📚 Learning: 2025-07-13T22:08:43.235Z
Learnt from: CR
Repo: dpasukhi/OCCT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-13T22:08:43.235Z
Learning: Applies to src/**/*.@(cxx|hxx) : When downcasting topological shapes, ALWAYS use the TopoDS helper functions (e.g., TopoDS::Face(anExp.Current())) to avoid errors.
Applied to files:
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.hxx
🧬 Code graph analysis (3)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.cxx (2)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (10)
D0(265-290)D0(265-266)D1(292-318)D1(292-294)D2(320-357)D2(320-322)D3(359-407)D3(359-361)DN(409-441)DN(409-412)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.cxx (10)
D0(43-56)D0(43-44)D1(58-82)D1(58-60)D2(84-114)D2(84-86)D3(116-153)D3(116-118)DN(155-209)DN(155-158)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (3)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.cxx (10)
D0(39-50)D0(39-40)D1(52-65)D1(52-54)D2(67-83)D2(67-69)D3(85-104)D3(85-87)DN(106-127)DN(106-109)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.cxx (10)
D0(43-56)D0(43-44)D1(58-82)D1(58-60)D2(84-114)D2(84-86)D3(116-153)D3(116-118)DN(155-209)DN(155-158)src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx (10)
D0(317-323)D0(317-317)D1(327-341)D1(327-331)D2(345-363)D2(345-352)D3(367-390)D3(367-378)DN(394-413)DN(394-397)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.cxx (2)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (10)
D0(265-290)D0(265-266)D1(292-318)D1(292-294)D2(320-357)D2(320-322)D3(359-407)D3(359-361)DN(409-441)DN(409-412)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.cxx (10)
D0(39-50)D0(39-40)D1(52-65)D1(52-54)D2(67-83)D2(67-69)D3(85-104)D3(85-87)DN(106-127)DN(106-109)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Prepare and Build on Ubuntu with Clang (x64)
- GitHub Check: Prepare and Build on Windows with MSVC (x64)
- GitHub Check: Prepare and Build on macOS with Clang (No PCH)
- GitHub Check: Prepare and Build on macOS with Clang (x64)
- GitHub Check: Build Documentation
🔇 Additional comments (4)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (2)
265-290: Past review issue successfully resolved.The previous review flagged that output parameters could be in a partially modified state on early return. This refactoring completely resolves that issue by eliminating out-parameters and returning fresh values via
std::optional. The method now either returns a valid point orstd::nullopt, with no intermediate states possible.
539-624: Excellent separation of normal error handling from exceptional cases.The refactoring correctly distinguishes between:
- Normal control flow failures (undefined normals at singular points): Now return
std::nulloptinstead of throwingGeom_UndefinedValue- Truly exceptional cases (infinite parameters, precondition violations): Still throw exceptions via
CheckInfiniteandStandard_RangeError_Raise_ifThis aligns with modern C++ best practices and the PR objectives.
Also applies to: 626-792, 794-888, 890-994, 996-1082
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.hxx (2)
42-64: LGTM! Clear documentation of optional return semantics.The public API documentation clearly explains that methods return the computed value on success or
std::nullopton failure. The signatures are consistent with the base classGeomEvaluator_Surfaceand follow the same pattern as related evaluators (SurfaceOfExtrusion,SurfaceOfRevolution).
78-129: LGTM! Private method signatures match implementation.The private
Calculate*method signatures correctly:
- Accept input values as
constreferences (no mutation)- Return
std::optionalto indicate success/failure- Include clear documentation of return semantics
| myBaseAdaptor->D0(theU, aValue); | ||
| else | ||
| myBaseCurve->D0(theU, theValue); | ||
| myBaseCurve->D0(theU, aValue); | ||
|
|
||
| Shift(theV, theValue); | ||
| Shift(theV, aValue); | ||
| return aValue; | ||
| } | ||
|
|
||
| void GeomEvaluator_SurfaceOfExtrusion::D1(const Standard_Real theU, | ||
| const Standard_Real theV, | ||
| gp_Pnt& theValue, | ||
| gp_Vec& theD1U, | ||
| gp_Vec& theD1V) const | ||
| std::optional<GeomEvaluator_D1Result> GeomEvaluator_SurfaceOfExtrusion::D1( | ||
| const Standard_Real theU, | ||
| const Standard_Real theV) const | ||
| { | ||
| GeomEvaluator_D1Result aResult; | ||
| if (!myBaseAdaptor.IsNull()) | ||
| myBaseAdaptor->D1(theU, theValue, theD1U); | ||
| myBaseAdaptor->D1(theU, aResult.theValue, aResult.theD1U); | ||
| else | ||
| myBaseCurve->D1(theU, theValue, theD1U); | ||
| myBaseCurve->D1(theU, aResult.theValue, aResult.theD1U); | ||
|
|
||
| theD1V = myDirection; | ||
| Shift(theV, theValue); | ||
| aResult.theD1V = myDirection; | ||
| Shift(theV, aResult.theValue); | ||
| return aResult; | ||
| } | ||
|
|
There was a problem hiding this comment.
Propagate base evaluation failures before returning
With the Geom_UndefinedValue refactor, the adaptor/curve D0/D1/D2/D3 calls now report success via Standard_Boolean. Here we still assume success, so a false result leaves aValue/derivatives undefined, yet we return an engaged std::optional. That both defeats the new error-handling model and risks propagating garbage. Please capture the Boolean, return std::nullopt when evaluation fails, and apply the same guard to the D1/D2/D3/DN overrides in this class.
- if (!myBaseAdaptor.IsNull())
- myBaseAdaptor->D0(theU, aValue);
- else
- myBaseCurve->D0(theU, aValue);
+ Standard_Boolean isDone = Standard_True;
+ if (!myBaseAdaptor.IsNull())
+ isDone = myBaseAdaptor->D0(theU, aValue);
+ else
+ isDone = myBaseCurve->D0(theU, aValue);
+ if (!isDone)
+ return std::nullopt;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| myBaseAdaptor->D0(theU, aValue); | |
| else | |
| myBaseCurve->D0(theU, theValue); | |
| myBaseCurve->D0(theU, aValue); | |
| Shift(theV, theValue); | |
| Shift(theV, aValue); | |
| return aValue; | |
| } | |
| void GeomEvaluator_SurfaceOfExtrusion::D1(const Standard_Real theU, | |
| const Standard_Real theV, | |
| gp_Pnt& theValue, | |
| gp_Vec& theD1U, | |
| gp_Vec& theD1V) const | |
| std::optional<GeomEvaluator_D1Result> GeomEvaluator_SurfaceOfExtrusion::D1( | |
| const Standard_Real theU, | |
| const Standard_Real theV) const | |
| { | |
| GeomEvaluator_D1Result aResult; | |
| if (!myBaseAdaptor.IsNull()) | |
| myBaseAdaptor->D1(theU, theValue, theD1U); | |
| myBaseAdaptor->D1(theU, aResult.theValue, aResult.theD1U); | |
| else | |
| myBaseCurve->D1(theU, theValue, theD1U); | |
| myBaseCurve->D1(theU, aResult.theValue, aResult.theD1U); | |
| theD1V = myDirection; | |
| Shift(theV, theValue); | |
| aResult.theD1V = myDirection; | |
| Shift(theV, aResult.theValue); | |
| return aResult; | |
| } | |
| std::optional<GeomEvaluator_D0Result> GeomEvaluator_SurfaceOfExtrusion::D0( | |
| const Standard_Real theU, | |
| const Standard_Real theV) const | |
| { | |
| GeomEvaluator_D0Result aValue; | |
| Standard_Boolean isDone = Standard_True; | |
| if (!myBaseAdaptor.IsNull()) | |
| isDone = myBaseAdaptor->D0(theU, aValue); | |
| else | |
| isDone = myBaseCurve->D0(theU, aValue); | |
| if (!isDone) | |
| return std::nullopt; | |
| Shift(theV, aValue); | |
| return aValue; | |
| } | |
| std::optional<GeomEvaluator_D1Result> GeomEvaluator_SurfaceOfExtrusion::D1( | |
| const Standard_Real theU, | |
| const Standard_Real theV) const | |
| { | |
| GeomEvaluator_D1Result aResult; | |
| if (!myBaseAdaptor.IsNull()) | |
| myBaseAdaptor->D1(theU, aResult.theValue, aResult.theD1U); | |
| else | |
| myBaseCurve->D1(theU, aResult.theValue, aResult.theD1U); | |
| aResult.theD1V = myDirection; | |
| Shift(theV, aResult.theValue); | |
| return aResult; | |
| } |
🤖 Prompt for AI Agents
In src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.cxx
around lines 44 to 66, the calls to myBaseAdaptor->D0/D1 (or myBaseCurve->D0/D1)
currently ignore their Standard_Boolean return value and always return an
engaged std::optional; change each evaluation call to capture the Boolean
success flag, and if it is false return std::nullopt immediately (do not call
Shift or use the value/derivatives), otherwise proceed to set Shift(theV, ...)
and return the populated result. Apply the same pattern to D1/D2/D3/DN overrides
in this class: check the adaptor/curve boolean result, return std::nullopt on
failure, only modify/internalize values and return when success is true.
| if (!myBaseAdaptor.IsNull()) | ||
| myBaseAdaptor->D0(theV, theValue); | ||
| myBaseAdaptor->D0(theV, aValue); | ||
| else | ||
| myBaseCurve->D0(theV, theValue); | ||
| myBaseCurve->D0(theV, aValue); | ||
|
|
||
| gp_Trsf aRotation; | ||
| aRotation.SetRotation(myRotAxis, theU); | ||
| theValue.Transform(aRotation); | ||
| aValue.Transform(aRotation); | ||
| return aValue; | ||
| } | ||
|
|
||
| void GeomEvaluator_SurfaceOfRevolution::D1(const Standard_Real theU, | ||
| const Standard_Real theV, | ||
| gp_Pnt& theValue, | ||
| gp_Vec& theD1U, | ||
| gp_Vec& theD1V) const | ||
| std::optional<GeomEvaluator_D1Result> GeomEvaluator_SurfaceOfRevolution::D1( | ||
| const Standard_Real theU, | ||
| const Standard_Real theV) const | ||
| { | ||
| GeomEvaluator_D1Result aResult; | ||
| if (!myBaseAdaptor.IsNull()) | ||
| myBaseAdaptor->D1(theV, theValue, theD1V); | ||
| myBaseAdaptor->D1(theV, aResult.theValue, aResult.theD1V); | ||
| else | ||
| myBaseCurve->D1(theV, theValue, theD1V); | ||
| myBaseCurve->D1(theV, aResult.theValue, aResult.theD1V); | ||
|
|
||
| // vector from center of rotation to the point on rotated curve | ||
| gp_XYZ aCQ = theValue.XYZ() - myRotAxis.Location().XYZ(); | ||
| theD1U = gp_Vec(myRotAxis.Direction().XYZ().Crossed(aCQ)); | ||
| gp_XYZ aCQ = aResult.theValue.XYZ() - myRotAxis.Location().XYZ(); | ||
| aResult.theD1U = gp_Vec(myRotAxis.Direction().XYZ().Crossed(aCQ)); | ||
| // If the point is placed on the axis of revolution then derivatives on U are undefined. | ||
| // Manually set them to zero. | ||
| if (theD1U.SquareMagnitude() < Precision::SquareConfusion()) | ||
| theD1U.SetCoord(0.0, 0.0, 0.0); | ||
| if (aResult.theD1U.SquareMagnitude() < Precision::SquareConfusion()) | ||
| aResult.theD1U.SetCoord(0.0, 0.0, 0.0); | ||
|
|
||
| gp_Trsf aRotation; | ||
| aRotation.SetRotation(myRotAxis, theU); | ||
| theValue.Transform(aRotation); | ||
| theD1U.Transform(aRotation); | ||
| theD1V.Transform(aRotation); | ||
| aResult.theValue.Transform(aRotation); | ||
| aResult.theD1U.Transform(aRotation); | ||
| aResult.theD1V.Transform(aRotation); | ||
| return aResult; | ||
| } |
There was a problem hiding this comment.
Return std::nullopt when the base curve evaluation fails
myBaseAdaptor->D0 / myBaseCurve->D0 now signal Geom_UndefinedValue via their Boolean return. We still ignore that flag and rotate whatever happens to be in aValue, so a failed evaluation produces an engaged optional with undefined data. Capture the Boolean, bail out with std::nullopt, and mirror the same guard in D1/D2/D3/DN so every optional actually reflects the new failure semantics.
- if (!myBaseAdaptor.IsNull())
- myBaseAdaptor->D0(theV, aValue);
- else
- myBaseCurve->D0(theV, aValue);
+ Standard_Boolean isDone = Standard_True;
+ if (!myBaseAdaptor.IsNull())
+ isDone = myBaseAdaptor->D0(theV, aValue);
+ else
+ isDone = myBaseCurve->D0(theV, aValue);
+ if (!isDone)
+ return std::nullopt;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (!myBaseAdaptor.IsNull()) | |
| myBaseAdaptor->D0(theV, theValue); | |
| myBaseAdaptor->D0(theV, aValue); | |
| else | |
| myBaseCurve->D0(theV, theValue); | |
| myBaseCurve->D0(theV, aValue); | |
| gp_Trsf aRotation; | |
| aRotation.SetRotation(myRotAxis, theU); | |
| theValue.Transform(aRotation); | |
| aValue.Transform(aRotation); | |
| return aValue; | |
| } | |
| void GeomEvaluator_SurfaceOfRevolution::D1(const Standard_Real theU, | |
| const Standard_Real theV, | |
| gp_Pnt& theValue, | |
| gp_Vec& theD1U, | |
| gp_Vec& theD1V) const | |
| std::optional<GeomEvaluator_D1Result> GeomEvaluator_SurfaceOfRevolution::D1( | |
| const Standard_Real theU, | |
| const Standard_Real theV) const | |
| { | |
| GeomEvaluator_D1Result aResult; | |
| if (!myBaseAdaptor.IsNull()) | |
| myBaseAdaptor->D1(theV, theValue, theD1V); | |
| myBaseAdaptor->D1(theV, aResult.theValue, aResult.theD1V); | |
| else | |
| myBaseCurve->D1(theV, theValue, theD1V); | |
| myBaseCurve->D1(theV, aResult.theValue, aResult.theD1V); | |
| // vector from center of rotation to the point on rotated curve | |
| gp_XYZ aCQ = theValue.XYZ() - myRotAxis.Location().XYZ(); | |
| theD1U = gp_Vec(myRotAxis.Direction().XYZ().Crossed(aCQ)); | |
| gp_XYZ aCQ = aResult.theValue.XYZ() - myRotAxis.Location().XYZ(); | |
| aResult.theD1U = gp_Vec(myRotAxis.Direction().XYZ().Crossed(aCQ)); | |
| // If the point is placed on the axis of revolution then derivatives on U are undefined. | |
| // Manually set them to zero. | |
| if (theD1U.SquareMagnitude() < Precision::SquareConfusion()) | |
| theD1U.SetCoord(0.0, 0.0, 0.0); | |
| if (aResult.theD1U.SquareMagnitude() < Precision::SquareConfusion()) | |
| aResult.theD1U.SetCoord(0.0, 0.0, 0.0); | |
| gp_Trsf aRotation; | |
| aRotation.SetRotation(myRotAxis, theU); | |
| theValue.Transform(aRotation); | |
| theD1U.Transform(aRotation); | |
| theD1V.Transform(aRotation); | |
| aResult.theValue.Transform(aRotation); | |
| aResult.theD1U.Transform(aRotation); | |
| aResult.theD1V.Transform(aRotation); | |
| return aResult; | |
| } | |
| Standard_Boolean isDone = Standard_True; | |
| if (!myBaseAdaptor.IsNull()) | |
| isDone = myBaseAdaptor->D0(theV, aValue); | |
| else | |
| isDone = myBaseCurve->D0(theV, aValue); | |
| if (!isDone) | |
| return std::nullopt; | |
| gp_Trsf aRotation; | |
| aRotation.SetRotation(myRotAxis, theU); | |
| aValue.Transform(aRotation); | |
| return aValue; | |
| } | |
| std::optional<GeomEvaluator_D1Result> GeomEvaluator_SurfaceOfRevolution::D1( | |
| const Standard_Real theU, | |
| const Standard_Real theV) const | |
| { | |
| GeomEvaluator_D1Result aResult; | |
| if (!myBaseAdaptor.IsNull()) | |
| myBaseAdaptor->D1(theV, aResult.theValue, aResult.theD1V); | |
| else | |
| myBaseCurve->D1(theV, aResult.theValue, aResult.theD1V); | |
| // vector from center of rotation to the point on rotated curve | |
| gp_XYZ aCQ = aResult.theValue.XYZ() - myRotAxis.Location().XYZ(); | |
| aResult.theD1U = gp_Vec(myRotAxis.Direction().XYZ().Crossed(aCQ)); | |
| // If the point is placed on the axis of revolution then derivatives on U are undefined. | |
| // Manually set them to zero. | |
| if (aResult.theD1U.SquareMagnitude() < Precision::SquareConfusion()) | |
| aResult.theD1U.SetCoord(0.0, 0.0, 0.0); | |
| gp_Trsf aRotation; | |
| aRotation.SetRotation(myRotAxis, theU); | |
| aResult.theValue.Transform(aRotation); | |
| aResult.theD1U.Transform(aRotation); | |
| aResult.theD1V.Transform(aRotation); | |
| return aResult; | |
| } |
🤖 Prompt for AI Agents
In src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.cxx
around lines 47-82, the code calls myBaseAdaptor->D0/D1 or myBaseCurve->D0/D1
but ignores their Boolean return that signals Geom_UndefinedValue; as a result
we rotate/transform undefined data and return an engaged optional. Change the D0
and D1 implementations (and mirror the same pattern in D2/D3/DN): capture the
Boolean result from the base D* call, and if it returns false immediately return
std::nullopt (without performing the rotation/Transform), otherwise proceed to
compute rotation, apply transforms, and return the populated optional. Ensure
the same guard is applied for all overloads so optional reflects evaluation
failure semantics.
…m evaluators Modified Geom_OffsetSurface, Geom_SurfaceOfRevolution, and Geom_SurfaceOfLinearExtrusion to check std::optional return values from their evaluators and throw Geom_UndefinedValue on calculation failure instead of silently failing or returning invalid values. Changes: - Check std::optional return from D0/D1/D2/D3/DN evaluator methods - Throw Geom_UndefinedValue with descriptive message when computation fails - Extract values from result structures for D1/D2/D3 - Added Geom_UndefinedValue include where needed
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx(5 hunks)src/ModelingData/TKG3d/Geom/Geom_SurfaceOfLinearExtrusion.cxx(6 hunks)src/ModelingData/TKG3d/Geom/Geom_SurfaceOfRevolution.cxx(5 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: dpasukhi/OCCT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-13T22:08:43.235Z
Learning: Applies to src/**/*.cxx : After using an API that performs a geometric operation (e.g., BRepAlgoAPI_Fuse, BRepBuilderAPI_MakeEdge), ALWAYS check if the operation was successful using the IsDone() method before accessing the result.
📚 Learning: 2025-07-13T22:08:43.235Z
Learnt from: CR
Repo: dpasukhi/OCCT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-13T22:08:43.235Z
Learning: Applies to src/**/*.@(cxx|hxx) : When downcasting topological shapes, ALWAYS use the TopoDS helper functions (e.g., TopoDS::Face(anExp.Current())) to avoid errors.
Applied to files:
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Prepare and Build on Ubuntu with Clang (x64)
- GitHub Check: Prepare and Build on macOS with Clang (No PCH)
- GitHub Check: Prepare and Build on macOS with Clang (x64)
- GitHub Check: Prepare and Build on Windows with MSVC (x64)
- GitHub Check: Build Documentation
🔇 Additional comments (5)
src/ModelingData/TKG3d/Geom/Geom_SurfaceOfRevolution.cxx (1)
234-241: Consistent error handling pattern implemented correctly.The implementation follows a consistent pattern across D0, D1, D2, D3, and DN methods:
- Uses modern C++17 if-with-initializer to check evaluator results
- Provides descriptive, method-specific error messages
- Properly extracts values from the optional results (dereferencing for D0/DN, accessing struct members for D1/D2/D3)
Also applies to: 252-261, 275-287, 305-321, 331-338
src/ModelingData/TKG3d/Geom/Geom_SurfaceOfLinearExtrusion.cxx (2)
25-25: Include added correctly.The include for
Geom_UndefinedValue.hxxis properly added to support the new exception type.
148-155: Consistent error handling pattern implemented correctly.The implementation mirrors the pattern in
Geom_SurfaceOfRevolution.cxx:
- Uses C++17 if-with-initializer for optional result checking
- Provides descriptive error messages for each method (D0, D1, D2, D3, DN)
- Properly handles both point/vector results (D0/DN) and structured results (D1/D2/D3)
Also applies to: 166-175, 189-201, 219-235, 245-252
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx (2)
320-329: Consistent error handling pattern with predecessor files.The implementation follows the same pattern as
Geom_SurfaceOfRevolution.cxxandGeom_SurfaceOfLinearExtrusion.cxx, with appropriate handling of theequivSurfpath. WhenequivSurfis null, evaluator results are checked andGeom_UndefinedValueis thrown on failure with descriptive messages.Also applies to: 347-358, 380-394, 421-439, 461-470
342-345: ****The review claims
#ifdef CHECKblocks were "removed," but the code snippet provided shows these blocks are present at lines 342-345, 374-378, 414-419, and 452-457. The CHECK guards remain active and throwGeom_UndefinedDerivativebased on basis surface continuity.The evaluator (
GeomEvaluator_OffsetSurface) has no continuity checks by design—it returnsstd::optional<...>for D1/D2/D3/DN methods, allowing computation to succeed or fail based on mathematical feasibility. The wrapper (Geom_OffsetSurface) performs upfront validation via CHECK guards before invoking the evaluator. This is not a behavior change; validation remains in place.Likely an incorrect or invalid review comment.
| { | ||
| if (auto aResult = myEvaluator->D0(U, V)) | ||
| { | ||
| P = *aResult; | ||
| } | ||
| else | ||
| { | ||
| throw Geom_UndefinedValue("Geom_OffsetSurface::D0 - computation failed"); | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
Verify the include for Geom_UndefinedValue.
Similar to Geom_SurfaceOfRevolution.cxx, this file throws Geom_UndefinedValue but doesn't show the include being added. Verify that #include <Geom_UndefinedValue.hxx> is present.
🏁 Script executed:
#!/bin/bash
# Check if Geom_UndefinedValue.hxx is included
rg -n '#include.*Geom_UndefinedValue' src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxxLength of output: 0
🏁 Script executed:
#!/bin/bash
# Check what includes are present at the top of the file
head -50 src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx | grep -n '#include'Length of output: 1020
🏁 Script executed:
#!/bin/bash
# Verify the actual throw statements for Geom_UndefinedValue
rg -n 'throw Geom_Undefined' src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxxLength of output: 587
Add missing include for Geom_UndefinedValue.
The file throws Geom_UndefinedValue at lines 327, 356, 392, 437, and 468 but #include <Geom_UndefinedValue.hxx> is not present. The include section has Geom_UndefinedDerivative.hxx (line 43) but is missing the required header for Geom_UndefinedValue.
🤖 Prompt for AI Agents
In src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx around lines 320 to 329,
the code throws Geom_UndefinedValue but the header <Geom_UndefinedValue.hxx> is
not included; add #include <Geom_UndefinedValue.hxx> to the include section
(near the existing Geom_UndefinedDerivative.hxx include) so the exception type
is declared and compile errors are resolved.
| if (auto aResult = myEvaluator->D0(U, V)) | ||
| { | ||
| P = *aResult; | ||
| } | ||
| else | ||
| { | ||
| throw Geom_UndefinedValue("Geom_SurfaceOfRevolution::D0 - computation failed"); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
Verify the include for Geom_UndefinedValue.
The code throws Geom_UndefinedValue but this file doesn't show the corresponding include being added (unlike Geom_SurfaceOfLinearExtrusion.cxx which adds #include <Geom_UndefinedValue.hxx> at line 25). Verify that the include is present, either already existing or added elsewhere.
Run the following script to check if the include is present:
🏁 Script executed:
#!/bin/bash
# Check if Geom_UndefinedValue.hxx is included
rg -n '#include.*Geom_UndefinedValue' src/ModelingData/TKG3d/Geom/Geom_SurfaceOfRevolution.cxxLength of output: 0
🏁 Script executed:
#!/bin/bash
# Check the header includes of the file
head -50 src/ModelingData/TKG3d/Geom/Geom_SurfaceOfRevolution.cxx | grep -n '#include'Length of output: 735
🏁 Script executed:
#!/bin/bash
# Check entire file for Geom_UndefinedValue reference
rg -n 'Geom_UndefinedValue' src/ModelingData/TKG3d/Geom/Geom_SurfaceOfRevolution.cxxLength of output: 439
Add missing include for Geom_UndefinedValue.
The code throws Geom_UndefinedValue in five methods (D0, D1, D2, D3, DN) but the corresponding header #include <Geom_UndefinedValue.hxx> is not present in the file. The file includes Geom_UndefinedDerivative.hxx but not Geom_UndefinedValue.hxx. Add the include directive to the existing include block at the top of the file.
🤖 Prompt for AI Agents
In src/ModelingData/TKG3d/Geom/Geom_SurfaceOfRevolution.cxx around lines 234 to
241, the methods (D0, D1, D2, D3, DN) throw Geom_UndefinedValue but the header
<Geom_UndefinedValue.hxx> is not included; add #include
<Geom_UndefinedValue.hxx> to the existing include block at the top of the file
(next to the existing Geom_UndefinedDerivative.hxx include) so the exception
type is declared.
…es to base class WORK IN PROGRESS - This commit will break compilation until all derived classes are updated. Changes: - Moved result structures into GeomEvaluator_Surface as public types - Renamed structures from GeomEvaluator_D1Result to GeomEvaluator_Surface::D1Result (same for D2, D3) - Updated Geom_Surface base class API to return std::optional instead of void - Updated GeomEvaluator implementations to use new structure names - Fully updated Geom_OffsetSurface to return std::optional without throwing exceptions Next steps needed: - Update Geom_SurfaceOfRevolution to match new API - Update Geom_SurfaceOfLinearExtrusion to match new API - Update all other Geom_* derived surface classes This is a major API refactoring to eliminate Geom_UndefinedValue exceptions in favor of std::optional return values as requested.
…l returns Changes: - Geom_Surface base class now has both APIs: * New: D0/D1/D2/D3/DN returning std::optional (pure virtual) * Deprecated: void D0/D1/D2/D3/DN and gp_Vec DN (implemented to call std::optional versions) - Deprecated methods call new std::optional methods and throw Geom_UndefinedValue on failure - Updated Geom_OffsetSurface.hxx to declare both method signatures - Geom_OffsetSurface.cxx already has std::optional implementations - Base class provides deprecated method implementations that work for all derived classes This approach maintains backward compatibility while providing the new std::optional API. Existing code continues to work, new code can use std::optional for better error handling.
…arExtrusion Added std::optional-returning methods alongside deprecated void methods for both classes. Changes for Geom_SurfaceOfRevolution: - Added std::optional<gp_Pnt> D0(U, V) returning evaluator result directly - Added std::optional<D1Result/D2Result/D3Result> D1/D2/D3 methods - Added std::optional<gp_Vec> DN method - Kept deprecated void methods that call evaluator and throw on failure Changes for Geom_SurfaceOfLinearExtrusion: - Added std::optional<gp_Pnt> D0(U, V) returning evaluator result directly - Added std::optional<D1Result/D2Result/D3Result> D1/D2/D3 methods - Added std::optional<gp_Vec> DN method - Kept deprecated void methods that call evaluator and throw on failure All three classes (OffsetSurface, SurfaceOfRevolution, SurfaceOfLinearExtrusion) now have: 1. New std::optional API for modern exception-free error handling 2. Deprecated void API for backward compatibility 3. Proper error propagation through both paths
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.cxx (1)
39-127: Propagate base-curve evaluation failures before returning optionalsThe base curve/adaptor
D0/D1/D2/D3/DNcalls now report success viaStandard_Boolean, but we drop that flag and always return an engagedstd::optional. When the upstream evaluation fails we end up shifting/normalizing undefined data and still claim success. Please capture the boolean, bail out withstd::nullopton failure, and apply the same guard pattern across D1/D2/D3/DN.std::optional<gp_Pnt> GeomEvaluator_SurfaceOfExtrusion::D0(const Standard_Real theU, const Standard_Real theV) const { - gp_Pnt aValue; - if (!myBaseAdaptor.IsNull()) - myBaseAdaptor->D0(theU, aValue); - else - myBaseCurve->D0(theU, aValue); + gp_Pnt aValue; + Standard_Boolean isDone = Standard_False; + if (!myBaseAdaptor.IsNull()) + isDone = myBaseAdaptor->D0(theU, aValue); + else + isDone = myBaseCurve->D0(theU, aValue); + if (!isDone) + return std::nullopt; Shift(theV, aValue); return aValue; }Please mirror this guard for D1/D2/D3/DN so we only populate and return results when the base evaluation succeeds.
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.cxx (1)
43-82: Still ignoring the base curve failure flagThe new
std::optionalresults are never cleared when the underlying curve evaluation fails.Adaptor3d_Curve::D0/D1/...(and theGeom_Curveequivalents) now returnStandard_Booleanto reportGeom_UndefinedValue, but we discard that flag and keep rotating whatever junk stayed in the output buffers. Callers will therefore receive an engaged optional filled with undefined data, defeating the whole refactor. Please capture the Boolean, bail out withstd::nullopt, and apply the same guard in D2/D3/DN.Apply this diff pattern:
gp_Pnt aValue; - if (!myBaseAdaptor.IsNull()) - myBaseAdaptor->D0(theV, aValue); - else - myBaseCurve->D0(theV, aValue); + Standard_Boolean isDone = Standard_True; + if (!myBaseAdaptor.IsNull()) + isDone = myBaseAdaptor->D0(theV, aValue); + else + isDone = myBaseCurve->D0(theV, aValue); + if (!isDone) + return std::nullopt; @@ - if (!myBaseAdaptor.IsNull()) - myBaseAdaptor->D1(theV, aResult.theValue, aResult.theD1V); - else - myBaseCurve->D1(theV, aResult.theValue, aResult.theD1V); + Standard_Boolean isDone = Standard_True; + if (!myBaseAdaptor.IsNull()) + isDone = myBaseAdaptor->D1(theV, aResult.theValue, aResult.theD1V); + else + isDone = myBaseCurve->D1(theV, aResult.theValue, aResult.theD1V); + if (!isDone) + return std::nullopt; @@ - if (!myBaseAdaptor.IsNull()) - myBaseAdaptor->D2(theV, aResult.theValue, aResult.theD1V, aResult.theD2V); - else - myBaseCurve->D2(theV, aResult.theValue, aResult.theD1V, aResult.theD2V); + Standard_Boolean isDone = Standard_True; + if (!myBaseAdaptor.IsNull()) + isDone = myBaseAdaptor->D2(theV, aResult.theValue, aResult.theD1V, aResult.theD2V); + else + isDone = myBaseCurve->D2(theV, aResult.theValue, aResult.theD1V, aResult.theD2V); + if (!isDone) + return std::nullopt; @@ - if (!myBaseAdaptor.IsNull()) - myBaseAdaptor->D3(theV, aResult.theValue, aResult.theD1V, aResult.theD2V, aResult.theD3V); - else - myBaseCurve->D3(theV, aResult.theValue, aResult.theD1V, aResult.theD2V, aResult.theD3V); + Standard_Boolean isDone = Standard_True; + if (!myBaseAdaptor.IsNull()) + isDone = myBaseAdaptor->D3(theV, aResult.theValue, aResult.theD1V, aResult.theD2V, aResult.theD3V); + else + isDone = myBaseCurve->D3(theV, aResult.theValue, aResult.theD1V, aResult.theD2V, aResult.theD3V); + if (!isDone) + return std::nullopt;Mirror the same pattern in
DN()for whichever base call supplies the data so every overload returnsstd::nullopton failure instead of silently fabricating values.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx(1 hunks)src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.hxx(3 hunks)src/ModelingData/TKG3d/Geom/Geom_Surface.cxx(1 hunks)src/ModelingData/TKG3d/Geom/Geom_Surface.hxx(2 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx(14 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.hxx(2 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_Surface.hxx(1 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.cxx(1 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.hxx(1 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.cxx(1 hunks)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.hxx(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: dpasukhi/OCCT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-13T22:08:43.235Z
Learning: Applies to src/**/*.cxx : After using an API that performs a geometric operation (e.g., BRepAlgoAPI_Fuse, BRepBuilderAPI_MakeEdge), ALWAYS check if the operation was successful using the IsDone() method before accessing the result.
🧬 Code graph analysis (4)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.cxx (3)
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx (10)
D0(317-327)D0(317-317)D1(331-346)D1(331-332)D2(350-366)D2(350-351)D3(370-387)D3(370-371)DN(391-415)DN(391-394)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (10)
D0(265-290)D0(265-266)D1(292-318)D1(292-294)D2(320-357)D2(320-322)D3(359-407)D3(359-361)DN(409-441)DN(409-412)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.cxx (10)
D0(43-56)D0(43-44)D1(58-82)D1(58-60)D2(84-114)D2(84-86)D3(116-153)D3(116-118)DN(155-209)DN(155-158)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.cxx (3)
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx (10)
D0(317-327)D0(317-317)D1(331-346)D1(331-332)D2(350-366)D2(350-351)D3(370-387)D3(370-371)DN(391-415)DN(391-394)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (10)
D0(265-290)D0(265-266)D1(292-318)D1(292-294)D2(320-357)D2(320-322)D3(359-407)D3(359-361)DN(409-441)DN(409-412)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.cxx (10)
D0(39-50)D0(39-40)D1(52-65)D1(52-54)D2(67-83)D2(67-69)D3(85-104)D3(85-87)DN(106-127)DN(106-109)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (3)
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx (10)
D0(317-327)D0(317-317)D1(331-346)D1(331-332)D2(350-366)D2(350-351)D3(370-387)D3(370-371)DN(391-415)DN(391-394)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfExtrusion.cxx (10)
D0(39-50)D0(39-40)D1(52-65)D1(52-54)D2(67-83)D2(67-69)D3(85-104)D3(85-87)DN(106-127)DN(106-109)src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_SurfaceOfRevolution.cxx (10)
D0(43-56)D0(43-44)D1(58-82)D1(58-60)D2(84-114)D2(84-86)D3(116-153)D3(116-118)DN(155-209)DN(155-158)
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx (3)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (10)
D0(265-290)D0(265-266)D1(292-318)D1(292-294)D2(320-357)D2(320-322)D3(359-407)D3(359-361)DN(409-441)DN(409-412)src/ModelingData/TKG3d/Geom/Geom_SurfaceOfLinearExtrusion.cxx (10)
D0(146-156)D0(146-146)D1(160-176)D1(160-164)D2(180-202)D2(180-187)D3(206-236)D3(206-217)DN(240-253)DN(240-243)src/ModelingData/TKG3d/Geom/Geom_SurfaceOfRevolution.cxx (10)
D0(232-242)D0(232-232)D1(246-262)D1(246-250)D2(266-288)D2(266-273)D3(292-322)D3(292-303)DN(326-339)DN(326-329)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Prepare and Build on Windows with MSVC (x64)
- GitHub Check: Build Documentation
- GitHub Check: Prepare and Build on Ubuntu with Clang (x64)
- GitHub Check: Prepare and Build on macOS with Clang (No PCH)
- GitHub Check: Prepare and Build on macOS with Clang (x64)
🔇 Additional comments (6)
src/ModelingData/TKG3d/GeomEvaluator/GeomEvaluator_OffsetSurface.cxx (6)
265-290: Excellent refactor addressing past review concerns.The refactoring from out-parameter mutation to optional-based returns cleanly resolves the previous issue where output parameters were left in a partially computed state on early return. The retry loop with point shifting is well-structured and provides robust handling of singular points.
292-407: Consistent implementation pattern across derivative methods.The uniform structure across D1, D2, and D3 methods enhances maintainability and reduces cognitive load. Each method correctly calls the appropriate Base* and Calculate* helpers with proper error propagation.
409-441: LGTM: Input validation and error handling are correct.The range checks and retry logic are appropriate. The method correctly propagates failures via
std::nullopt.
539-624: Past review issue fully resolved with clean implementation.The method now takes
theBaseValueas a const reference, creates a local copy (line 545), and returns the computed point orstd::nullopt. This eliminates the previous problem of returning with partially modified output parameters. The singular point handling via osculating surfaces and CSLib::Normal is robust.
626-888: Clean result-struct pattern with proper const-correctness.Both methods demonstrate excellent separation of concerns: base parameters are const, result structs are built internally, and failure cases return
std::nullopt. The non-singular optimization in CalculateD1 (lines 676-711) is a nice touch for common cases.
890-1082: Comprehensive derivative handling with proper error signaling.Both CalculateD3 and CalculateDN correctly compute higher-order derivatives and use
std::nulloptto signal undefined normals. The implementation handles arbitrary derivative orders (in DN) while maintaining the consistent optional-return pattern.
| std::optional<gp_Vec> Geom_OffsetSurface::DN(const Standard_Real U, | ||
| const Standard_Real V, | ||
| const Standard_Integer Nu, | ||
| const Standard_Integer Nv) const | ||
| { | ||
| Standard_RangeError_Raise_if(Nu < 0 || Nv < 0 || Nu + Nv < 1, " "); | ||
| if (Nu < 0 || Nv < 0 || Nu + Nv < 1) | ||
| { | ||
| return std::nullopt; | ||
| } | ||
| #ifdef CHECK | ||
| if (!(basisSurf->IsCNu(Nu) && basisSurf->IsCNv(Nv))) | ||
| { | ||
| throw Geom_UndefinedDerivative(); | ||
| return std::nullopt; | ||
| } |
There was a problem hiding this comment.
Restore Standard_RangeError for invalid derivative orders
The legacy implementation raised Standard_RangeError when Nu < 0, Nv < 0, or Nu + Nv < 1. The new version quietly returns std::nullopt, so callers now get a Geom_UndefinedValue after the wrapper converts the null optional instead of the documented range error. That silently widens the valid input domain and breaks existing error handling. Please reinstate the range checks before delegating to the evaluator.
Apply this diff:
- if (Nu < 0 || Nv < 0 || Nu + Nv < 1)
- {
- return std::nullopt;
- }
+ Standard_RangeError_Raise_if(Nu < 0 || Nv < 0 || Nu + Nv < 1,
+ "Geom_OffsetSurface::DN - invalid derivative order");📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| std::optional<gp_Vec> Geom_OffsetSurface::DN(const Standard_Real U, | |
| const Standard_Real V, | |
| const Standard_Integer Nu, | |
| const Standard_Integer Nv) const | |
| { | |
| Standard_RangeError_Raise_if(Nu < 0 || Nv < 0 || Nu + Nv < 1, " "); | |
| if (Nu < 0 || Nv < 0 || Nu + Nv < 1) | |
| { | |
| return std::nullopt; | |
| } | |
| #ifdef CHECK | |
| if (!(basisSurf->IsCNu(Nu) && basisSurf->IsCNv(Nv))) | |
| { | |
| throw Geom_UndefinedDerivative(); | |
| return std::nullopt; | |
| } | |
| std::optional<gp_Vec> Geom_OffsetSurface::DN(const Standard_Real U, | |
| const Standard_Real V, | |
| const Standard_Integer Nu, | |
| const Standard_Integer Nv) const | |
| { | |
| Standard_RangeError_Raise_if(Nu < 0 || Nv < 0 || Nu + Nv < 1, | |
| "Geom_OffsetSurface::DN - invalid derivative order"); | |
| #ifdef CHECK | |
| if (!(basisSurf->IsCNu(Nu) && basisSurf->IsCNv(Nv))) | |
| { | |
| return std::nullopt; | |
| } |
🤖 Prompt for AI Agents
In src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx around lines 391 to 404,
restore the original behavior of raising Standard_RangeError for invalid
derivative orders: when Nu < 0 or Nv < 0 or Nu + Nv < 1 throw
Standard_RangeError (with a descriptive message) instead of returning
std::nullopt so callers receive the documented range error; perform these range
checks before any optional-returning logic or delegation to the evaluator and
keep the existing CHECK block unchanged after the range validation.
| gp_Vec Geom_Surface::DN(const Standard_Real U, | ||
| const Standard_Real V, | ||
| const Standard_Integer Nu, | ||
| const Standard_Integer Nv) const | ||
| { | ||
| if (auto aResult = DN(U, V, Nu, Nv)) | ||
| { | ||
| return *aResult; | ||
| } | ||
| else | ||
| { | ||
| throw Geom_UndefinedValue("Geom_Surface::DN - computation failed"); | ||
| } |
There was a problem hiding this comment.
Stop the self-recursion in DN legacy wrapper
Geom_Surface::DN now calls DN(U, V, Nu, Nv) with an identical signature, so the invocation resolves right back to this wrapper and immediately recurses until the stack blows up. Please route this code through the new optional-return implementation (or otherwise rename/split the APIs) before dereferencing so we actually reach the evaluator and can throw on failure.
CRITICAL FIX: The previous approach made std::optional methods pure virtual, breaking all derived classes that don't implement them (Geom_Plane, BSplineSurface, etc.) New architecture: - void methods are pure virtual (= 0) - forces derived classes to implement (as originally) - std::optional methods are non-pure virtual - have default implementation in base class - Default std::optional implementation calls void method and catches exceptions This way: - Old classes (Geom_Plane, etc.) only implement void methods - they compile - New classes (OffsetSurface, etc.) can override std::optional for better performance - No breaking changes to existing codebase Changes: - Geom_Surface.hxx: Swapped = 0 markers (void is pure virtual, std::optional is not) - Geom_Surface.cxx: std::optional methods now call void methods with try/catch
…std::optional Correct API architecture: - std::optional<> D0/D1/D2/D3/DN methods: pure virtual (= 0) → Forces ALL derived classes to implement - void D0/D1/D2/D3 and gp_Vec DN methods: non-virtual, deprecated → Implemented in base class → Call std::optional methods and throw exception on std::nullopt This requires updating all Geom_* derived surface classes to implement std::optional methods. Already completed: Geom_OffsetSurface, Geom_SurfaceOfRevolution, Geom_SurfaceOfLinearExtrusion Still need: Geom_Plane, Geom_BSplineSurface, Geom_BezierSurface, elementary surfaces, etc.
Completed refactoring for elementary analytical surfaces: - Geom_Plane: Added std::optional D0/D1/D2/D3/DN methods - Geom_ConicalSurface: Added std::optional D0/D1/D2/D3/DN methods - Geom_CylindricalSurface: Added std::optional D0/D1/D2/D3/DN methods All classes now implement dual API: - New: std::optional methods (pure virtual, no exceptions) - Old: void methods (non-virtual wrappers, deprecated, throw on failure) These analytical surfaces always succeed and return computed values. Related to Geom_UndefinedValue exception deprecation.
Completed refactoring for remaining elementary surfaces: - Geom_SphericalSurface: Added std::optional D0/D1/D2/D3/DN methods - Geom_ToroidalSurface: Added std::optional D0/D1/D2/D3/DN methods All 5 elementary surfaces now complete (Plane, Conical, Cylindrical, Spherical, Toroidal). Dual API pattern maintained: - New: std::optional methods (pure virtual, no exceptions) - Old: void methods (non-virtual wrappers, deprecated, throw on failure) Related to Geom_UndefinedValue exception deprecation.
Added std::optional D0 implementation for Geom_BezierSurface. Still needs: D1, D2, D3, DN implementations and header updates. This is partial work on the parametric surface refactoring. Related to Geom_UndefinedValue exception deprecation.
This commit adds non-virtual void D0/D1/D2/D3 methods and gp_Vec DN method to the Geom_Surface base class. These wrapper methods: 1. Call the pure virtual std::optional versions (implemented in derived classes) 2. Extract values from std::optional if successful 3. Throw Geom_UndefinedValue/Geom_UndefinedDerivative if std::nullopt is returned This provides backward compatibility for existing code using void methods while allowing new code to use std::optional methods for explicit error handling. Architecture: - Pure virtual std::optional methods in base class (= 0) - Non-virtual void wrappers in base class (call std::optional, throw on nullopt) - Derived classes implement ONLY std::optional methods - Derived classes inherit void wrappers from base class Next steps: Implement std::optional D0/D1/D2/D3/DN in all derived surface classes. Related to Geom_UndefinedValue exception deprecation.
All derived surface classes now only implement std::optional methods. The void D0/D1/D2/D3 and gp_Vec DN methods are inherited from Geom_Surface base class, which provides non-virtual wrapper implementations that call the std::optional versions. This eliminates code duplication and ensures consistent error handling. Files cleaned: - Geom_Plane.cxx - Geom_ConicalSurface.cxx - Geom_CylindricalSurface.cxx - Geom_SphericalSurface.cxx - Geom_ToroidalSurface.cxx - Geom_BezierSurface.cxx - Geom_BSplineSurface_1.cxx Total: ~700 lines of duplicate code removed.
BUG #1 - Wrong Exception Type: - Fixed Geom_Surface::DN to throw Geom_UndefinedDerivative instead of Geom_UndefinedValue - DN is a derivative method and should use derivative exception type BUG #2 - RectangularTrimmedSurface Not Refactored (CRITICAL): - Added std::optional D0/D1/D2/D3/DN implementations - This class was completely missing std::optional methods - Without these, code wouldn't compile (pure virtual not implemented) - All methods delegate to basisSurf->D0/D1/D2/D3/DN BUG #3 - SurfaceOfRevolution Duplicate void Methods: - Removed 112 lines of duplicate void D0/D1/D2/D3/DN implementations - These methods are inherited from Geom_Surface base class BUG #4 - SurfaceOfLinearExtrusion Duplicate void Methods: - Removed 112 lines of duplicate void D0/D1/D2/D3/DN implementations - These methods are inherited from Geom_Surface base class Total: 224 lines of duplicate code removed Compilation should now succeed for all surface classes.
- Updated Geom_BezierSurface.hxx: removed old void declarations, added std::optional - Updated Geom_BSplineSurface.hxx: removed old void declarations, added std::optional - Added std::optional implementations to Geom_BSplineSurface_1.cxx (D0, D1, D2, D3, DN) - Updated Geom_OffsetSurface.hxx: removed deprecated void methods, kept only std::optional - Updated Geom_SurfaceOfRevolution.hxx: removed deprecated void methods, kept only std::optional - Updated Geom_SurfaceOfLinearExtrusion.hxx: removed deprecated void methods, kept only std::optional - Changed Standard_OVERRIDE to override throughout All derived classes now only have std::optional methods in headers, matching implementations.
The DN method had two declarations with identical parameters but different return types (gp_Vec vs std::optional<gp_Vec>), which is illegal in C++. Unlike D0/D1/D2/D3 where the deprecated wrappers have different signatures (void with reference parameters), the DN wrapper had the same signature and only differed by return type, causing compilation errors. Solution: Remove the deprecated gp_Vec DN() version entirely. - Removed declaration from Geom_Surface.hxx - Removed implementation from Geom_Surface.cxx DN now only has the std::optional<gp_Vec> version. Users must migrate to the new API (no backward compatibility wrapper for this method). This is acceptable as DN is less commonly used than D0/D1/D2/D3.
Two fixes: 1. Fixed BSplineSurface_1.cxx line 1748: Qualified D0 call with Geom_Surface:: to access base class wrapper (C++ name hiding issue) 2. Removed second duplicate DN wrapper from Geom_Surface.cxx that was missed in previous commit (there were TWO DN implementations, only removed one) C++ name hiding: When a derived class declares any method with the same name as a base class method, it hides ALL base class methods with that name, regardless of signature. To access hidden base class methods, must use explicit qualification (BaseClass::method).
Removed all deprecated void method declarations (D0, D1, D2, D3, DN) from: - Geom_Plane.hxx (56 lines) - Geom_ConicalSurface.hxx (61 lines) - Geom_CylindricalSurface.hxx (57 lines) - Geom_SphericalSurface.hxx (57 lines) - Geom_ToroidalSurface.hxx (51 lines) Total: 282 lines removed These void wrappers now only exist in the base class (Geom_Surface) as non-virtual methods. Derived classes only implement the std::optional versions, which override the pure virtual methods from the base class. This fixes compilation errors where Standard_OVERRIDE was being applied to non-overriding methods (void wrappers that don't exist in base class).
…tions Updated Geom_RectangularTrimmedSurface.hxx to replace old void method declarations with std::optional versions: - void D0(..., gp_Pnt& P) → std::optional<gp_Pnt> D0(...) - void D1(..., gp_Pnt& P, gp_Vec& D1U, D1V) → std::optional<D1Result> D1(...) - void D2(...) → std::optional<D2Result> D2(...) - void D3(...) → std::optional<D3Result> D3(...) - gp_Vec DN(...) → std::optional<gp_Vec> DN(...) The implementations in the .cxx file were already updated in a previous commit, but the header declarations were missed. This fixes compilation errors where the class was considered abstract due to unimplemented pure virtual methods from the base class.
Removed duplicate implementations of D0, D1, D2, D3 wrapper methods that were causing 'redefinition' compilation errors. The file had TWO identical implementations of each wrapper method: - D0: lines 85-95 and 188-198 (removed second) - D1: lines 99-115 and 202-218 (removed second) - D2: lines 119-141 and 222-244 (removed second) - D3: lines 145-175 and 248-278 (removed second) Total: 91 lines of duplicate code removed These duplicates were likely introduced during the refactoring when wrapper methods were added in multiple commits without checking for existing implementations.
Updated all surface method calls in GeomAdaptor_Surface.cxx to use the new std::optional-based API instead of the old void-based API with reference parameters. Changes: - D0 calls: Added std::optional unwrapping (myNestedEvaluator) - D1 calls: Added std::optional unwrapping and result structure access - D2 calls: Added std::optional unwrapping and result structure access - D3 calls: Added std::optional unwrapping for myBSplineSurface and myNestedEvaluator - DN returns: Added std::optional unwrapping before return All calls now properly handle std::optional results by checking for value and throwing Standard_Failure on nullopt.
Updated GeomEvaluator_OffsetSurface.cxx to handle the new std::optional-based DN() method in Geom_Surface. Changes: - Added unwrapDN() helper template using C++17 constexpr if to handle both std::optional<gp_Vec> (from Geom_Surface::DN) and gp_Vec (from GeomAdaptor_Surface::DN) - Updated derivatives() template function to unwrap DN() results when calling SetValue() (lines 183, 186, 198, 201) - Updated D3() method to unwrap myBaseSurf->DN() calls (lines 984-990) - Updated CalculateDN() method to unwrap myBaseSurf->DN() call (line 1093) The helper function uses compile-time type checking to determine whether to unwrap std::optional or return the value directly, allowing the template code to work with both Geom_Surface and GeomAdaptor_Surface.
Fixed additional DN() calls that were missed in the previous commit: - derivatives() template: Added unwrapDN() for DN() calls in else clause (lines 223, 226) - CalculateD2() method: Added unwrapDN() for myBaseSurf->DN() calls (lines 890-892) All myBaseSurf->DN() calls now properly handle std::optional<gp_Vec> returns. myBaseAdaptor->DN() calls remain unchanged as they return gp_Vec directly.
…_SurfaceTool Updated remaining void-based API calls to use new std::optional-based API. Changes in GeomEvaluator_OffsetSurface.cxx: - Fixed theL->D1() call to use std::optional D1Result (lines 148-155) - Fixed theL->D2() call to use std::optional D2Result (lines 160-170) - Fixed theL->D3() call to use std::optional D3Result (lines 178-192) - Added unwrapDN() for all theL->DN() calls (lines 213, 218, 228, 233) Changes in GeomLProp_SurfaceTool.cxx: - Fixed DN() method to unwrap std::optional<gp_Vec> return from Geom_Surface::DN() - Added Standard_Failure.hxx include for error handling All surface DN() calls in the codebase have been reviewed. Remaining DN() calls in Geom_RectangularTrimmedSurface, Geom_SurfaceOfRevolution, Geom_SurfaceOfLinearExtrusion, and Geom_OffsetSurface correctly delegate and return std::optional<gp_Vec> without modification.
Implemented the missing D1, D2, D3, and DN methods for Geom_BezierSurface that were declared in the header but not implemented in the .cxx file. All implementations follow the same pattern as the existing D0 method: - Use BSplSLib library functions (D1, D2, D3, DN) for computation - Handle both rational and non-rational surfaces - Create knot/multiplicity arrays for Bezier representation - Return std::optional results with appropriate result structures This fixes the linker errors: - unresolved external symbol Geom_BezierSurface::D1 - unresolved external symbol Geom_BezierSurface::D2 - unresolved external symbol Geom_BezierSurface::D3 - unresolved external symbol Geom_BezierSurface::DN
Updated GeomPlate_Surface to use std::optional-based surface methods instead of the deprecated void-based API. Changes in GeomPlate_Surface.hxx: - Added GeomEvaluator_Surface.hxx include for result structures - Replaced void D0/D1/D2/D3 method declarations with std::optional versions - Changed DN return type from gp_Vec to std::optional<gp_Vec> - Changed Standard_OVERRIDE to override Changes in GeomPlate_Surface.cxx: - Updated D0() to return std::optional<gp_Pnt> - Updated D1() to return std::optional<D1Result> and use new API - Updated D2() to return std::optional<D2Result> and use new API - Updated D3() to return std::nullopt (not implemented) - Updated DN() to return std::nullopt (not implemented) All methods now properly call the std::optional-based API on mySurfinit and handle nullopt returns gracefully.
fca37d1 to
53954e1
Compare
Updated files that call Geom_Surface and GeomPlate_Surface methods to use the new std::optional-based API. IMPORTANT: Only calls to Geom_Surface and GeomPlate_Surface were changed. Calls to Adaptor3d_Surface (via myFrontiere->GetSurface()) were NOT changed because Adaptor3d_Surface still uses the void-based API. Fixed calls: - GeomPlate_MakeApprox.cxx: * myPlate->D0/D1 (lines 367, 374) - GeomPlate_Surface - GeomPlate_BuildPlateSurface.cxx: * myGeomPlateSurface->D0/D1 - GeomPlate_Surface * mySurfInit->D0/D1/D2 - Geom_Surface - GeomPlate_PointConstraint.cxx: * Surf->D2 (line 69) - Geom_Surface NOT fixed (uses Adaptor3d_Surface with void API): - GeomPlate_CurveConstraint.cxx: * myFrontiere->GetSurface()->D0/D1/D2 - Adaptor3d_Surface (no change) All changed calls properly unwrap std::optional results and access result structure members (theValue, theD1U, theD1V, theD2U, theD2V, theD2UV).
a6eefaf to
cc0e608
Compare
This commit updates GeomFill files to use the new std::optional-based API, but ONLY for files that actually call methods on Geom_Surface or its derived classes. Files correctly updated: - GeomFill_ConstrainedFilling.cxx - calls Geom_BSplineSurface methods - GeomFill_FunctionGuide.cxx - calls Geom_SurfaceOfRevolution methods - GeomFill_Pipe.cxx - calls Geom_Curve::D0 (fixed syntax errors) - GeomFill_SectionPlacement.cxx - calls GeomFill_LocationLaw::D0 - GeomFill_Sweep.cxx - calls GeomFill_LocationLaw::D0 Files NOT changed (reverted from automated script): - GeomFill_CircularBlendFunc.cxx - uses Adaptor3d_Curve (void API) - GeomFill_Darboux.cxx - uses Adaptor3d_Surface (void API) - GeomFill_Frenet.cxx - uses Adaptor3d_Curve (void API) - GeomFill_FunctionDraft.cxx - uses Adaptor3d_Surface (void API) - GeomFill_GuideTrihedronAC.cxx - uses Adaptor3d_Curve (void API) - GeomFill_LocationGuide.cxx - calls GeomFill_SectionLaw (boolean return) - GeomFill_SweepFunction.cxx - calls GeomFill_SectionLaw (boolean return) The key distinction: Adaptor classes (Adaptor3d_Surface, Adaptor3d_Curve, GeomAdaptor_Surface) still use the old void-based API. Only direct calls to Geom_Surface and its derived classes use the new std::optional API.
cc0e608 to
93f5834
Compare
…olean API GeomFill_SectionLaw::D0() still returns Standard_Boolean, not std::optional. Only the TheSurface->D0/D1/D2 calls (which use Geom_SurfaceOfRevolution) should use the new std::optional API. This fixes the compilation error: error: too few arguments to function call, expected 3, have 2 if (auto aResult = TheLaw->D0(TheUonS, Poles))
Geom_Curve::D0() has NOT been updated to use std::optional - it still uses the old void-based API: void D0(const Standard_Real U, gp_Pnt& P) Only Geom_Surface has been refactored to use std::optional in this work. Geom_Curve is a separate class that has not been updated yet. This fixes compilation errors: error: too few arguments to function call, expected 2, have 1 if (auto aResult = C1->D0(u))
… boolean API GeomFill_LocationLaw::D0() returns Standard_Boolean, not std::optional. It requires 3 arguments: D0(Param, M, V) or 4 arguments with Poles2d. Both files call GeomFill_LocationLaw::D0() methods which still use the old boolean-based API, not the new std::optional API. This fixes compilation error: error: no matching member function for call to 'D0' if (auto aResult = myLaw->D0(PathParam, M)) note: candidate function not viable: requires 3 arguments, but 2 were provided
myInitialSurface is Handle(Geom_Surface), so D0() and DN() now return
std::optional<gp_Pnt> and std::optional<gp_Vec> respectively.
Changed from:
Value = myInitialSurface->Value(point2d.X(), point2d.Y()).XYZ();
Value = myInitialSurface->DN(point2d.X(), point2d.Y(), iu, iv).XYZ();
To:
if (auto aResult = myInitialSurface->D0(point2d.X(), point2d.Y()))
Value = aResult->XYZ();
if (auto aResult = myInitialSurface->DN(point2d.X(), point2d.Y(), iu, iv))
Value = aResult->XYZ();
This fixes compilation error:
error: no member named 'XYZ' in 'std::optional<gp_Vec>'
ShapeExtend_CompositeSurface inherits from Geom_Surface, so it must override
the new std::optional-returning methods instead of the old void-based ones.
Changes:
- D0() now returns std::optional<gp_Pnt>
- D1() now returns std::optional<GeomEvaluator_Surface::D1Result>
- D2() now returns std::optional<GeomEvaluator_Surface::D2Result>
- D3() now returns std::optional<GeomEvaluator_Surface::D3Result>
- DN() now returns std::optional<gp_Vec>
All implementations simply delegate to the patch surface and return its result.
This fixes compilation errors:
error: 'D0' marked 'override' but does not override any member functions
error: virtual function 'DN' has a different return type ('gp_Vec') than
the function it overrides (which has return type 'std::optional<gp_Vec>')
…::D1
Changed from:
anObject->D1(0., 0., resPnt, resD1U, resD1V);
To:
if (auto aResult = anObject->D1(0., 0.))
{
resPnt = aResult->theValue;
resD1U = aResult->theD1U;
resD1V = aResult->theD1V;
}
anObject is Handle(Geom_ToroidalSurface) which inherits from Geom_Surface,
so D1() now returns std::optional<GeomEvaluator_Surface::D1Result>.
This fixes compilation error:
error: too many arguments to function call, expected 2, have 5
…om_Surface::D0
Updated three D0 calls to unwrap std::optional returns:
1. SR->D0(U1, V1, P0) on Geom_SurfaceOfRevolution
2. SPH->D0(US1, VS1, PS) on Geom_SphericalSurface
3. SR->D0(UR1, VR1, PR) on Geom_SurfaceOfRevolution
All changed to:
if (auto aResult = surface->D0(U, V))
point = *aResult;
This fixes compilation errors:
error: too many arguments to function call, expected 2, have 3
Replace exception-based error handling with boolean return values for Geom_UndefinedValue. This change improves code maintainability and performance by eliminating exception throwing in normal control flow.
Changes:
GeomEvaluator_OffsetSurface: Modified Calculate* methods to return Standard_Boolean indicating success/failure instead of throwing exceptions. Updated callers to check return values.
GeomFill_Darboux: Refactored static Normal* helper functions to return Standard_Boolean. Updated call sites to check return values and propagate failures.
Geom_OffsetSurface: Removed CHECK ifdef block that threw exception.
Geom_UndefinedValue: Marked exception class and macro as deprecated using Standard_DEPRECATED with guidance to use boolean returns.
All changes follow OCCT naming conventions (a/an/the + camel case).