1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-02 17:46:22 +03:00

0028605: Improve the algorithm of calculation of valid intersection range of an edge

- New method BRepLib::FindValidRange() has been added. It computes the range of the edge not covered by boundary vertices.
- The algorithm of calculation of valid intersection range in the class IntTools_ShrunkRange has been corrected to use the new method.
- The method BOPTools_AlgoTools::MakeSplitEdge() has been improved to protect against errors in the case of reversed orientation of the input edge.
- Two new Draw commands have been added:
  validrange - it calls the new method BRepLib::FindValidRange().
  tolsphere  - it shows tolerances of vertices by drawing a sphere around each vertex of the shape.
- The test cases "offset shape_type_i_c YE1,YE2" became better. The scripts have been corrected to reflect the new state.
This commit is contained in:
msv 2017-03-24 16:04:05 +03:00 committed by bugmaster
parent 501d0d386a
commit c0a1a35fac
10 changed files with 441 additions and 66 deletions

View File

@ -5942,33 +5942,8 @@ box b3 6 0 0 1 1 1
compound b1 b2 b3 c
~~~~~
@subsubsection occt_draw_7_1_5 checkshape
Syntax:
~~~~~
checkshape [-top] shape [result] [-short]
~~~~~
Where:
* *top* -- optional parameter, which allows checking only topological validity of a shape.
* *shape* -- the only required parameter which represents the name of the shape to check.
* *result* -- optional parameter which is the prefix of the output shape names.
* *short* -- a short description of the check.
**checkshape** examines the selected object for topological and geometric coherence. The object should be a three dimensional shape.
**Example:**
~~~~~
# checkshape returns a comment valid or invalid
box b1 0 0 0 1 1 1
checkshape b1
# returns the comment
this shape seems to be valid
~~~~~
**Note** that this test is performed using the tolerance set in the algorithm.
@subsubsection occt_draw_7_1_6 compare
@subsubsection occt_draw_7_1_5 compare
Syntax:
~~~~~
@ -5994,7 +5969,7 @@ compare b1 b2
# shapes are not same
~~~~~
@subsubsection occt_draw_7_1_7 issubshape
@subsubsection occt_draw_7_1_6 issubshape
Syntax:
~~~~~
@ -7273,12 +7248,15 @@ buildevol
@subsection occt_draw_7_9 Analysis of topology and geometry
Analysis of shapes includes commands to compute length, area, volumes and inertial properties.
Analysis of shapes includes commands to compute length, area, volumes and inertial properties, as well as to compute some aspects impacting shape validity.
* Use **lprops**, **sprops**, **vprops** to compute integral properties.
* Use **bounding** to display the bounding box of a shape.
* Use **distmini** to calculate the minimum distance between two shapes.
* Use **xdistef**, **xdistcs**, **xdistcc**, **xdistc2dc2dss**, **xdistcc2ds** to check the distance between two objects on even grid.
* Use **checkshape** to check validity of the shape.
* Use **tolsphere** to see the tolerance spheres of all vertices in the shape.
* Use **validrange** to check range of an edge not covered by vertices.
@subsubsection occt_draw_7_9_1 lprops, sprops, vprops
@ -7411,6 +7389,80 @@ xdistcc2ds c_1 c2d2_1 s2 0 1
xdistc2dc2dss c2d1_1 c2d2_1 s1 s2 0 1 1000
~~~~~
@subsubsection occt_draw_7_9_5 checkshape
Syntax:
~~~~~
checkshape [-top] shape [result] [-short]
~~~~~
Where:
* *top* -- optional parameter, which allows checking only topological validity of a shape.
* *shape* -- the only required parameter which represents the name of the shape to check.
* *result* -- optional parameter which is the prefix of the output shape names.
* *short* -- a short description of the check.
**checkshape** examines the selected object for topological and geometric coherence. The object should be a three dimensional shape.
**Example:**
~~~~~
# checkshape returns a comment valid or invalid
box b1 0 0 0 1 1 1
checkshape b1
# returns the comment
this shape seems to be valid
~~~~~
@subsubsection occt_draw_7_9_6 tolsphere
Syntax:
~~~~~
tolsphere shape
~~~~~
Where:
* *shape* -- the name of the shape to process.
**tolsphere** shows vertex tolerances by drawing spheres around each vertex in the shape. Each sphere is assigned a name of the shape with suffix "_vXXX", where XXX is the number of the vertex in the shape.
**Example:**
~~~~~
# tolsphere returns all names of created spheres.
box b1 0 0 0 1 1 1
settolerance b1 0.05
tolsphere b1
# creates spheres and returns the names
b1_v1 b1_v2 b1_v3 b1_v4 b1_v5 b1_v6 b1_v7 b1_v8
~~~~~
@subsubsection occt_draw_7_9_7 validrange
Syntax:
~~~~~
validrange edge [(out) u1 u2]
~~~~~
Where:
* *edge* -- the name of the edge to analyze.
* *u1*, *u2* -- optional names of variables to put the range into.
**validrange** computes valid range of the edge. If *u1* and *u2* are not given it returns first and last parameters. Otherwise, it sets the variables u1 and u2.
**Example:**
~~~~~
circle c 0 0 0 10
mkedge e c
mkedge e c 0 pi
validrange e
# returns the range
1.9884375000000002e-008 3.1415926337054181
validrange e u1 u2
dval u1
1.9884375000000002e-008
dval u2
3.1415926337054181
~~~~~
@subsection occt_draw_7_10 Surface creation

View File

@ -1162,8 +1162,9 @@ The following methods allow building PCurves of edges on faces:
The following methods allow checking the validity of the shapes:
* *BOPTools_AlgoTools::IsMicroEdge* detects the small edges;
* *BOPTools_AlgoTools::ComputeTolerance* computs the correct tolerance for the edge on the face;
* *BOPTools_AlgoTools::ComputeTolerance* computes the correct tolerance of the edge on the face;
* *BOPTools_AlgoTools::CorrectShapeTolerances* and *BOPTools_AlgoTools::CorrectTolerances* allows correcting the tolerances of the sub-shapes.
* *BRepLib::FindValidRange* finds a range of 3d curve of the edge not covered by tolerance spheres of vertices.
@subsection occt_modalg_2_topo_tools_7 Taking a point inside the face

View File

@ -146,7 +146,7 @@ void BOPTools_AlgoTools::MakeSplitEdge(const TopoDS_Edge& aE,
Standard_Real aTol;//f, l,
aTol=BRep_Tool::Tolerance(aE);
//
TopoDS_Edge E=aE;
TopoDS_Edge E = TopoDS::Edge(aE.Oriented(TopAbs_FORWARD));
E.EmptyCopy();
//
BRep_Builder BB;
@ -159,6 +159,7 @@ void BOPTools_AlgoTools::MakeSplitEdge(const TopoDS_Edge& aE,
BB.Range(E, aP1, aP2);
BB.UpdateEdge(E, aTol);
aNewEdge=E;
aNewEdge.Orientation(aE.Orientation());
}
//=======================================================================

View File

@ -27,6 +27,8 @@
#include <Standard_Integer.hxx>
#include <TopTools_ListOfShape.hxx>
#include <NCollection_List.hxx>
class Adaptor3d_Curve;
class Geom_Plane;
class TopoDS_Edge;
class TopoDS_Shape;
@ -234,6 +236,23 @@ public:
Standard_EXPORT static void BoundingVertex(const NCollection_List<TopoDS_Shape>& theLV,
gp_Pnt& theNewCenter, Standard_Real& theNewTol);
//! For an edge defined by 3d curve and tolerance and vertices defined by points,
//! parameters on curve and tolerances,
//! finds a range of curve between vertices not covered by vertices tolerances.
//! Returns false if there is no such range. Otherwise, sets theFirst and
//! theLast as its bounds.
Standard_EXPORT static Standard_Boolean FindValidRange
(const Adaptor3d_Curve& theCurve, const Standard_Real theTolE,
const Standard_Real theParV1, const gp_Pnt& thePntV1, const Standard_Real theTolV1,
const Standard_Real theParV2, const gp_Pnt& thePntV2, const Standard_Real theTolV2,
Standard_Real& theFirst, Standard_Real& theLast);
//! Finds a range of 3d curve of the edge not covered by vertices tolerances.
//! Returns false if there is no such range. Otherwise, sets theFirst and
//! theLast as its bounds.
Standard_EXPORT static Standard_Boolean FindValidRange
(const TopoDS_Edge& theEdge, Standard_Real& theFirst, Standard_Real& theLast);
protected:

236
src/BRepLib/BRepLib_1.cxx Normal file
View File

@ -0,0 +1,236 @@
// Created on: 2017-03-24
// Created by: Mikhail Sazonov
// Copyright (c) 2017 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BRepLib.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Geom_OffsetCurve.hxx>
#include <Precision.hxx>
#include <TopExp.hxx>
#include <TopoDS_Vertex.hxx>
//=======================================================================
// function: findNearestValidPoint
// purpose : Starting from the appointed end of the curve, find the nearest
// point on the curve that is an intersection with the sphere with
// center theVertPnt and radius theTol.
//=======================================================================
static Standard_Boolean findNearestValidPoint(
const Adaptor3d_Curve& theCurve,
const Standard_Real theFirst, const Standard_Real theLast,
const Standard_Boolean isFirst,
const gp_Pnt& theVertPnt,
const Standard_Real theTol,
const Standard_Real theEps,
Standard_Real& thePar)
{
// 1. Check that the needed end is inside the sphere
Standard_Real aStartU = theFirst;
Standard_Real anEndU = theLast;
if (!isFirst)
std::swap(aStartU, anEndU);
gp_Pnt aP = theCurve.Value(aStartU);
const Standard_Real aSqTol = theTol * theTol;
if (aP.SquareDistance(theVertPnt) > aSqTol)
// the vertex does not cover the corresponding to this vertex end of the curve
return Standard_False;
// 2. Find a nearest point that is outside
// stepping along the curve by theTol till go out
//
// the general step is computed using general curve resolution
Standard_Real aStep = theCurve.Resolution(theTol) * 1.01;
// aD1Mag is a threshold to consider local derivative magnitude too small
// and to accelerate going out of sphere
// (inverse of resolution is the maximal derivative);
// this is actual for bezier and b-spline types only
Standard_Real aD1Mag = 0.;
GeomAbs_CurveType aType = theCurve.GetType();
if (aType == GeomAbs_OffsetCurve)
{
Handle(Geom_OffsetCurve) anOffsetCurve = theCurve.OffsetCurve();
Handle(Geom_Curve) aBaseCurve = anOffsetCurve->BasisCurve();
aType = GeomAdaptor_Curve(aBaseCurve).GetType();
}
if (aType == GeomAbs_BezierCurve || aType == GeomAbs_BSplineCurve)
{
aD1Mag = 1. / theCurve.Resolution(1.) * 0.01;
aD1Mag *= aD1Mag;
}
if (!isFirst)
aStep = -aStep;
Standard_Boolean isOut = Standard_False;
Standard_Real anUIn = aStartU;
Standard_Real anUOut = anUIn;
while (!isOut)
{
anUIn = anUOut;
anUOut += aStep;
if ((isFirst && anUOut > anEndU) || (!isFirst && anUOut < anEndU))
{
// step is too big and we go out of bounds,
// check if the opposite bound is outside
aP = theCurve.Value(anEndU);
isOut = (aP.SquareDistance(theVertPnt) > aSqTol);
if (!isOut)
// all range is inside sphere
return Standard_False;
anUOut = anEndU;
break;
}
if (aD1Mag > 0.)
{
Standard_Real aStepLocal = aStep;
for (;;)
{
// cycle to go out of local singularity
gp_Vec aD1;
theCurve.D1(anUOut, aP, aD1);
if (aD1.SquareMagnitude() < aD1Mag)
{
aStepLocal *= 2.;
anUOut += aStepLocal;
if ((isFirst && anUOut < anEndU) || (!isFirst && anUOut > anEndU))
// still in range
continue;
// went out of range, so check if the end point has out state
anUOut = anEndU;
aP = theCurve.Value(anUOut);
isOut = (aP.SquareDistance(theVertPnt) > aSqTol);
if (!isOut)
// all range is inside sphere
return Standard_False;
}
break;
}
}
else
{
aP = theCurve.Value(anUOut);
}
if (!isOut)
isOut = (aP.SquareDistance(theVertPnt) > aSqTol);
}
// 3. Precise solution with binary search
Standard_Real aDelta = Abs(anUOut - anUIn);
while (aDelta > theEps)
{
Standard_Real aMidU = (anUIn + anUOut) * 0.5;
aP = theCurve.Value(aMidU);
isOut = (aP.SquareDistance(theVertPnt) > aSqTol);
if (isOut)
anUOut = aMidU;
else
anUIn = aMidU;
aDelta = Abs(anUOut - anUIn);
}
thePar = (anUIn + anUOut) * 0.5;
return Standard_True;
}
//=======================================================================
// function: FindValidRange
// purpose :
//=======================================================================
Standard_Boolean BRepLib::FindValidRange
(const Adaptor3d_Curve& theCurve, const Standard_Real theTolE,
const Standard_Real theParV1, const gp_Pnt& thePntV1, const Standard_Real theTolV1,
const Standard_Real theParV2, const gp_Pnt& thePntV2, const Standard_Real theTolV2,
Standard_Real& theFirst, Standard_Real& theLast)
{
if (theParV2 - theParV1 < Precision::PConfusion())
return Standard_False;
Standard_Real anEps = Max(theCurve.Resolution(theTolE) * 0.1, Precision::PConfusion());
if (Precision::IsInfinite(theParV1))
theFirst = theParV1;
else
{
if (!findNearestValidPoint(theCurve, theParV1, theParV2, Standard_True,
thePntV1, theTolV1, anEps, theFirst))
return Standard_False;
if (theParV2 - theFirst < anEps)
return Standard_False;
}
if (Precision::IsInfinite(theParV2))
theLast = theParV2;
else
{
if (!findNearestValidPoint(theCurve, theParV1, theParV2, Standard_False,
thePntV2, theTolV2, anEps, theLast))
return Standard_False;
if (theLast - theParV1 < anEps)
return Standard_False;
}
// check found parameters
if (theFirst > theLast)
{
// overlapping, not valid range
return Standard_False;
}
return Standard_True;
}
//=======================================================================
// function: FindValidRange
// purpose :
//=======================================================================
Standard_Boolean BRepLib::FindValidRange
(const TopoDS_Edge& theEdge, Standard_Real& theFirst, Standard_Real& theLast)
{
TopLoc_Location aLoc;
Standard_Real f, l;
if (BRep_Tool::Curve(theEdge, aLoc, f, l).IsNull())
return Standard_False;
BRepAdaptor_Curve anAC(theEdge);
Standard_Real aParV[2] = { anAC.FirstParameter(), anAC.LastParameter() };
if (aParV[1] - aParV[0] < Precision::PConfusion())
return Standard_False;
// get vertices
TopoDS_Vertex aV[2];
TopExp::Vertices(theEdge, aV[0], aV[1]);
Standard_Real aTolE = BRep_Tool::Tolerance(theEdge);
// to have correspondence with intersection precision
// the tolerances of vertices are increased on Precision::Confusion()
Standard_Real aTolV[2] = { Precision::Confusion(), Precision::Confusion() };
gp_Pnt aPntV[2];
for (Standard_Integer i = 0; i < 2; i++)
{
if (!aV[i].IsNull())
{
aTolV[i] += BRep_Tool::Tolerance(aV[i]);
aPntV[i] = BRep_Tool::Pnt(aV[i]);
}
else if (!Precision::IsInfinite(aParV[i]))
{
aTolV[i] += aTolE;
aPntV[i] = anAC.Value(aParV[i]);
}
}
return FindValidRange(anAC, aTolE,
aParV[0], aPntV[0], aTolV[0],
aParV[1], aPntV[1], aTolV[1],
theFirst, theLast);
}

View File

@ -1,5 +1,6 @@
BRepLib.cxx
BRepLib.hxx
BRepLib_1.cxx
BRepLib_CheckCurveOnSurface.cxx
BRepLib_CheckCurveOnSurface.hxx
BRepLib_Command.cxx

View File

@ -39,12 +39,14 @@
#include <Precision.hxx>
#include <LocalAnalysis.hxx>
#include <LocalAnalysis_SurfaceContinuity.hxx>
#include <Geom_SphericalSurface.hxx>
#include <Geom_Surface.hxx>
#include <Geom_Curve.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2d_Curve.hxx>
#include <DrawTrSurf.hxx>
#include <GeomAbs_Shape.hxx>
#include <TCollection_AsciiString.hxx>
#include <TopoDS.hxx>
#include <TopExp.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
@ -57,6 +59,7 @@
#include <TopOpeBRepTool_PurgeInternalEdges.hxx>
//#include <TopOpeBRepTool_FuseEdges.hxx>
#include <BRepLib.hxx>
#include <BRepLib_FuseEdges.hxx>
#include <TopTools_HSequenceOfShape.hxx>
@ -1579,7 +1582,75 @@ static Standard_Integer listfuseedge(Draw_Interpretor& di,
return 0;
}
//=======================================================================
//function : tolsphere
//purpose :
//=======================================================================
static Standard_Integer tolsphere(Draw_Interpretor& di, Standard_Integer n, const char** a)
{
if (n != 2)
{
di << "use toolsphere shape\n";
return 1;
}
TopoDS_Shape aS = DBRep::Get(a[1]);
if (aS.IsNull())
{
di << "No such shape " << a[1] << "\n";
return 1;
}
TopTools_IndexedMapOfShape aMapV;
TopExp::MapShapes(aS, TopAbs_VERTEX, aMapV);
for (Standard_Integer i = 1; i <= aMapV.Extent(); i++)
{
const TopoDS_Vertex& aV = TopoDS::Vertex(aMapV.FindKey(i));
Standard_Real aRadius = BRep_Tool::Tolerance(aV);
gp_Pnt aCenter = BRep_Tool::Pnt(aV);
Handle(Geom_Surface) aSph = new Geom_SphericalSurface(gp_Ax2(aCenter,gp::DZ()), aRadius);
TCollection_AsciiString aName(a[1]);
aName = aName + "_v" + i;
DrawTrSurf::Set(aName.ToCString(), aSph);
di << aName << " ";
}
return 0;
}
//=======================================================================
//function : validrange
//purpose :
//=======================================================================
static Standard_Integer validrange(Draw_Interpretor& di,
Standard_Integer narg, const char** a)
{
if (narg < 2)
{
di << "usage: validrange edge [(out) u1 u2]";
return 1;
}
TopoDS_Edge aE = TopoDS::Edge(DBRep::Get(a[1],TopAbs_EDGE, true));
if (aE.IsNull())
return 1;
Standard_Real u1, u2;
if (BRepLib::FindValidRange(aE, u1, u2))
{
if (narg > 3)
{
Draw::Set(a[2], u1);
Draw::Set(a[3], u2);
}
else
{
di << u1 << " " << u2;
}
}
else
di << "edge has no valid range";
return 0;
}
//=======================================================================
//function : CheckCommands
@ -1667,5 +1738,13 @@ theCommands.Add("listfuseedge",
"listfuseedge shape",
__FILE__,
listfuseedge,g);
theCommands.Add("tolsphere", "toolsphere shape\n"
"\t\tshows vertex tolerances by drawing spheres",
__FILE__, tolsphere, g);
theCommands.Add("validrange",
"validrange edge [(out) u1 u2]\n"
"\t\tcomputes valid range of the edge, and\n"
"\t\tprints first and last values or sets the variables u1 and u2",
__FILE__, validrange, g);
}

View File

@ -14,6 +14,7 @@
#include <Bnd_Box.hxx>
#include <BRepLib.hxx>
#include <BndLib_Add3dCurve.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
@ -133,6 +134,8 @@ void IntTools_ShrunkRange::Perform()
return;
}
//
gp_Pnt aP1 = BRep_Tool::Pnt(myV1);
gp_Pnt aP2 = BRep_Tool::Pnt(myV2);
Standard_Real aTolE, aTolV1, aTolV2;
aTolE = BRep_Tool::Tolerance(myEdge);
aTolV1 = BRep_Tool::Tolerance(myV1);
@ -150,8 +153,22 @@ void IntTools_ShrunkRange::Perform()
// the tolerances of vertices are increased on Precision::Confusion()
aTolV1 += aDTol;
aTolV2 += aDTol;
//
// compute the shrunk range - part of the edge not covered
// by the tolerance spheres of its vertices
BRepAdaptor_Curve aBAC(myEdge);
if (!BRepLib::FindValidRange(aBAC, aTolE, myT1, aP1, aTolV1,
myT2, aP2, aTolV2, myTS1, myTS2)) {
// no valid range
return;
}
if ((myTS2 - myTS1) < aPDTol) {
// micro edge
return;
}
//
// compute the length of the edge on the shrunk range
//
// parametric tolerance for the edge
// to be used in AbscissaPoint computations
Standard_Real aPTolE = aBAC.Resolution(aTolE);
@ -161,31 +178,6 @@ void IntTools_ShrunkRange::Perform()
if (aPTolE > aPTolEMin) {
aPTolE = aPTolEMin;
}
//
// compute the shrunk range - part of the edge not covered
// by the tolerance spheres of its vertices
GCPnts_AbscissaPoint aPC1(aBAC, aTolV1, myT1, aPTolE);
// if Abscissa is unable to compute the parameter
// use the resolution of the curve
myTS1 = aPC1.IsDone() ? aPC1.Parameter() : (myT1 + aBAC.Resolution(aTolV1));
if (myT2 - myTS1 < aPDTol) {
// micro edge
return;
}
//
GCPnts_AbscissaPoint aPC2(aBAC, -aTolV2, myT2, aPTolE);
myTS2 = aPC2.IsDone() ? aPC2.Parameter() : (myT2 - aBAC.Resolution(aTolV2));
if (myTS2 - myT1 < aPDTol) {
// micro edge
return;
}
//
if ((myTS2 - myTS1) < aPDTol) {
// micro edge
return;
}
//
// compute the length of the edge on the shrunk range
Standard_Real anEdgeLength =
GCPnts_AbscissaPoint::Length(aBAC, myTS1, myTS2, aPTolE);
if (anEdgeLength < aDTol) {

View File

@ -1,7 +1,4 @@
puts "TODO OCC27414 ALL: Error: The command cannot be built"
puts "TODO OCC27414 ALL: Tcl Exception"
puts "TODO OCC27414 ALL: TEST INCOMPLETE"
puts "TODO OCC27414 ALL: WRONG because number of FACE .* is 15"
restore [locate_data_file bug28442_simple3.brep] s

View File

@ -1,7 +1,4 @@
puts "TODO OCC27414 ALL: Error: The command cannot be built"
puts "TODO OCC27414 ALL: Tcl Exception"
puts "TODO OCC27414 ALL: TEST INCOMPLETE"
puts "TODO OCC27414 ALL: WRONG because number of FACE .* is 16"
restore [locate_data_file bug28442_simple3.brep] s
@ -25,9 +22,9 @@ foreach f [explode s f] {
}
offsetperform result
checkprops result -v 0 -s 0
checkprops result -v 1410.52 -s 845.819
unifysamedom result_unif result
checknbshapes result_unif -face 13 -shell 1
checknbshapes result_unif -face 14 -shell 1
checkview -display result_unif -2d -path ${imagedir}/${test_image}.png