Calculate radius of circumcircle as maximum difference between its center and vertices or reference triangle.
Draw test command OCC25547 has been implemented.
Small optimizations for speed.
Update of test-cases according to the new behaviour
Update of test-cases in group mesh
}
//=======================================================================
-//function : Bind
+//function : MakeCircle
//purpose :
//=======================================================================
-Standard_Boolean BRepMesh_CircleTool::Bind(const Standard_Integer theIndex,
- const gp_XY& thePoint1,
- const gp_XY& thePoint2,
- const gp_XY& thePoint3)
+Standard_Boolean BRepMesh_CircleTool::MakeCircle(const gp_XY& thePoint1,
+ const gp_XY& thePoint2,
+ const gp_XY& thePoint3,
+ gp_XY& theLocation,
+ Standard_Real& theRadius)
{
- const Standard_Real aPrecision = Precision::PConfusion();
- const Standard_Real aSqPrecision = aPrecision * aPrecision;
+ static const Standard_Real aPrecision = Precision::PConfusion();
+ static const Standard_Real aSqPrecision = aPrecision * aPrecision;
- const gp_XY aPoints[3] = { thePoint1, thePoint2, thePoint3 };
+ if ((thePoint1 - thePoint3).SquareModulus() < aSqPrecision)
+ return Standard_False;
- gp_XY aNorm[3];
- gp_XY aMidPnt[3];
- for (Standard_Integer i = 0; i < 3; ++i)
- {
- const gp_XY& aPnt1 = aPoints[i];
- const gp_XY& aPnt2 = aPoints[(i + 1) % 3];
+ gp_XY aLink1(thePoint2 - thePoint1);
+ if (aLink1.SquareModulus() < aSqPrecision)
+ return Standard_False;
- aMidPnt[i] = (aPnt1 + aPnt2) / 2.;
+ gp_XY aLink2(thePoint3 - thePoint2);
+ if (aLink2.SquareModulus() < aSqPrecision)
+ return Standard_False;
+
+ gp_XY aMidPnt1 = (thePoint1 + thePoint2) / 2.;
+ gp_XY aNorm1 = gp_XY(aLink1.Y(), -aLink1.X());
+ aNorm1.Add(aMidPnt1);
- gp_XY aLink(aPnt2 - aPnt1);
- if (aLink.SquareModulus() < aSqPrecision)
- return Standard_False;
+ if (aLink2.SquareModulus() < aSqPrecision)
+ return Standard_False;
- aNorm[i] = gp_XY(aLink.Y(), -aLink.X());
- aNorm[i].Add(aMidPnt[i]);
- }
+ gp_XY aMidPnt2 = (thePoint2 + thePoint3) / 2.;
+ gp_XY aNorm2 = gp_XY(aLink2.Y(), -aLink2.X());
+ aNorm2.Add(aMidPnt2);
gp_XY aIntPnt;
Standard_Real aParam[2];
BRepMesh_GeomTool::IntFlag aIntFlag =
- BRepMesh_GeomTool::IntLinLin(aMidPnt[0], aNorm[0],
- aMidPnt[1], aNorm[1], aIntPnt, aParam);
+ BRepMesh_GeomTool::IntLinLin(aMidPnt1, aNorm1,
+ aMidPnt2, aNorm2, aIntPnt, aParam);
if (aIntFlag != BRepMesh_GeomTool::Cross)
return Standard_False;
- Standard_Real aRadius = (aPoints[0] - aIntPnt).Modulus();
- bind(theIndex, aIntPnt, aRadius);
+ theLocation = aIntPnt;
+
+ theRadius = Sqrt(Max(Max((thePoint1 - aIntPnt).SquareModulus(),
+ (thePoint2 - aIntPnt).SquareModulus()),
+ (thePoint3 - aIntPnt).SquareModulus())) + aPrecision;
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : Bind
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_CircleTool::Bind(const Standard_Integer theIndex,
+ const gp_XY& thePoint1,
+ const gp_XY& thePoint2,
+ const gp_XY& thePoint3)
+{
+ gp_XY aLocation;
+ Standard_Real aRadius;
+ if (!MakeCircle(thePoint1, thePoint2, thePoint3, aLocation, aRadius))
+ return Standard_False;
+
+ bind(theIndex, aLocation, aRadius);
return Standard_True;
}
Standard_EXPORT void Bind(const Standard_Integer theIndex,
const gp_Circ2d& theCircle);
+ //! Computes circle on three points.
+ //! @param thePoint1 first point.
+ //! @param thePoint2 second point.
+ //! @param thePoint3 third point.
+ //! @param[out] theLocation center of computed circle.
+ //! @param[out] theRadius radius of computed circle.
+ //! @return FALSE in case of impossibility to build a circle
+ //! on the given points, TRUE elsewhere.
+ Standard_EXPORT static Standard_Boolean MakeCircle(const gp_XY& thePoint1,
+ const gp_XY& thePoint2,
+ const gp_XY& thePoint3,
+ gp_XY& theLocation,
+ Standard_Real& theRadius);
+
//! Computes circle on three points and bind it to the tool.
//! @param theIndex index a circle should be bound with.
//! @param thePoint1 first point.
return 0;
}
+//=======================================================================
+//function : OCC25547
+//purpose :
+//=======================================================================
+#include <BRepMesh_CircleTool.hxx>
+
+static Standard_Boolean inspect_point(const gp_XY& thePoint,
+ const gp_XY& theCenter,
+ const Standard_Real theRadius)
+{
+ static Standard_Real aPrecision = Precision::PConfusion();
+ static Standard_Real aSqPrecision = aPrecision * aPrecision;
+ const gp_XY aDistVec = thePoint - theCenter;
+ if (aDistVec.SquareModulus() - (theRadius * theRadius) < aSqPrecision)
+ return Standard_True;
+ else
+ return Standard_False;
+}
+
+static Standard_Integer OCC24923(
+ Draw_Interpretor& theDI,
+ Standard_Integer argc,
+ const char ** argv)
+{
+ srand(static_cast<unsigned int>(time(NULL)));
+
+ const Standard_Real aMaxDeviation = (argc > 1) ? Draw::Atof(argv[1]) : 0.01;
+ const Standard_Integer aPointsNb = 10000000;
+ const Standard_Real aMinAngle = 5 * M_PI / 180.;
+ static Standard_Real aSqPrecision = Precision::PConfusion() * Precision::PConfusion();
+
+ Standard_Integer aFailedNb = 0;
+ for (Standard_Integer i = 0; i < aPointsNb; ++i)
+ {
+ gp_XY p[3];
+ for (Standard_Integer j = 0; j < 3; ++j)
+ p[j].SetCoord(((Standard_Real)rand())/RAND_MAX, ((Standard_Real)rand())/RAND_MAX);
+
+ // Check that points do not compose degenerated triangle.
+ gp_XY aVec1 = p[1] - p[0];
+ gp_XY aVec2 = p[2] - p[0];
+ if (aVec1.SquareModulus() > aSqPrecision &&
+ aVec2.SquareModulus() > aSqPrecision &&
+ (aVec1 ^ aVec2) > aMinAngle)
+ {
+ gp_XY aCenter;
+ Standard_Real aRadius;
+ if (BRepMesh_CircleTool::MakeCircle(p[0], p[1], p[2], aCenter, aRadius))
+ {
+ if (!inspect_point(p[0], aCenter, aRadius) ||
+ !inspect_point(p[1], aCenter, aRadius) ||
+ !inspect_point(p[2], aCenter, aRadius))
+ {
+ /* theDI << "Missed: " <<
+ "p1=(" << p1.X() << ", " << p1.Y() << "), " <<
+ "p2=(" << p2.X() << ", " << p2.Y() << "), " <<
+ "p3=(" << p3.X() << ", " << p3.Y() << "), " <<
+ "c=(" << aCenter.X() << ", " << aCenter.Y() << "), " <<
+ "r=" << aRadius << "\n";*/
+
+ ++aFailedNb;
+ }
+
+ continue;
+ }
+ }
+
+ // Ensure that aPointsNb suitable for tests are generated
+ --i;
+ }
+
+ const Standard_Real aDeviation =
+ 1. - (Standard_Real)(aPointsNb - aFailedNb) / (Standard_Real)aPointsNb;
+
+ theDI << "Number of failed cases: " << aFailedNb << " (Total " << aPointsNb << ")\n";
+ if (aDeviation > aMaxDeviation)
+ {
+ theDI << "Failed. Number of incorrect results is too huge: " <<
+ aDeviation * 100 << "% (Max " << aMaxDeviation * 100 << "%)" << "\n";
+ return 1;
+ }
+
+ theDI << "Deviation of incorrect results is: " <<
+ aDeviation * 100 << "% (Max " << aMaxDeviation * 100 << "%)" << "\n";
+ theDI << "Test completed\n";
+ return 0;
+}
+
void QABugs::Commands_19(Draw_Interpretor& theCommands) {
const char *group = "QABugs";
theCommands.Add ("OCC25547", "OCC25547", __FILE__, OCC25547, group);
theCommands.Add ("OCC24881", "OCC24881 shape", __FILE__, OCC24881, group);
theCommands.Add ("xprojponf", "xprojponf p f", __FILE__, xprojponf, group);
+ theCommands.Add ("OCC24923", "OCC24923", __FILE__, OCC24923, group);
return;
}
--- /dev/null
+puts "========"
+puts "OCC24923"
+puts "========"
+puts ""
+############################################
+# BRepMesh_CircleTool produces bad circles
+############################################
+
+pload QAcommands
+
+set bug_info [OCC24923]
+set num_failed [string range [lindex $bug_info 12] 0 [expr {[string first "%" [lindex $bug_info 12]] - 1}]]
+set max_failed [string range [lindex $bug_info 14] 0 [expr {[string first "%" [lindex $bug_info 14]] - 1}]]
+if {$num_failed > $max_failed} {
+ puts "ERROR: OCC24923 is reproduced. Number of failed tests is too large ($num_failed > $max_failed)."
+}
puts "mem_virt_2=${mem_virt_2}"
puts "mem_heap_2=${mem_heap_2}"
-set mem_delta_private 180
+set mem_delta_private 200
set mem_delta_swap 100
set mem_delta_swappeak 250
-set mem_delta_wset 180
-set mem_delta_wsetpeak 180
-set mem_delta_virt 180
+set mem_delta_wset 200
+set mem_delta_wsetpeak 200
+set mem_delta_virt 200
set mem_delta_heap 80
if { [regexp {Debug mode} [dversion]] } {
set good_nbtri 2721
set good_nbnod 1405
-set good_defl 0.048938765264496524
+set good_defl 0.044436924588798624
set good_percent 5
}
if { [string compare $os "windows"] != 0 } {
puts "OS = Linux"
- set good_tri 524278
- set good_nod 265870
+ set good_tri 520414
+ set good_nod 263938
set good_defl 0.0026800432954056617
} else {
puts "OS = Windows NT"
- set good_tri 524278
- set good_nod 265870
+ set good_tri 520414
+ set good_nod 263938
set good_defl 0.0026800432954056617
}
set TheFileName shading_012.brep
###set bug_withouttri "OCC22687"
###set nbwithouttri(All) 1
-if { [string compare $command "shading"] == 0 } {
- set bug_freelinks "OCC23106"
- set nbfree(All) 4
-} else {
- set bug_freelinks "OCC25378"
- set nbfree(All) 3
-}
+#if { [string compare $command "shading"] == 0 } {
+# set bug_freelinks "OCC23106"
+# set nbfree(All) 4
+#} else {
+# set bug_freelinks "OCC25378"
+# set nbfree(All) 3
+#}