View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0029766||Community||OCCT:Modeling Algorithms||public||2018-05-14 15:55||2021-08-29 18:37|
|Summary||0029766: Modeling Algorithms - BRepExtrema_DistShapeShape Should Give Access to Its Solutions|
|Description||I compute the distances of two shapes, but I am not only interested in the minimum distance, but I also want to have the closest points on both shapes, their distances and their parameters with respect to both shapes.|
BRepExtrema_DistShapeShape does not offer an easy solution for that, because its actual solutions are private. For computing the distances of the local solutions, I have to compute the distances of the solution points (using BRepExtrema_DistShapeShape::PointOnShape1 and BRepExtrema_DistShapeShape::PointOnShape2). And for computing the point parameters, I have to project the points with ShapeAnalysis_Curve::Project.
If there were getters for the actual solutions, I could more easily access that data and also it would be less costly in terms of computation times.
|Steps To Reproduce||Not required|
|Tags||No tags attached.|
|Test case number|
Branch CR29766 has been created by BenjaminBihler.
Detailed log of new commits:
Author: Benjamin Bihler
Date: Mon May 14 15:02:22 2018 +0200
0029766: BRepExtrema_DistShapeShape Should Give Access to Its Solutions
Solution getters have been added to BRepExtrema_DistShapeShape.
Why don't you use the methods:
//! gives the support where the Nth solution on the first shape is situated. //! This support can be a Vertex, an Edge or a Face. Standard_EXPORT TopoDS_Shape SupportOnShape1(const Standard_Integer N) const; //! gives the support where the Nth solution on the second shape is situated. //! This support can be a Vertex, an Edge or a Face. Standard_EXPORT TopoDS_Shape SupportOnShape2(const Standard_Integer N) const; //! gives the corresponding parameter t if the Nth solution //! is situated on an Egde of the first shape Standard_EXPORT void ParOnEdgeS1(const Standard_Integer N,Standard_Real& t) const; //! gives the corresponding parameter t if the Nth solution //! is situated on an Egde of the first shape Standard_EXPORT void ParOnEdgeS2(const Standard_Integer N,Standard_Real& t) const; //! gives the corresponding parameters (U,V) if the Nth solution //! is situated on an face of the first shape Standard_EXPORT void ParOnFaceS1(const Standard_Integer N,Standard_Real& u,Standard_Real& v) const; //! gives the corresponding parameters (U,V) if the Nth solution //! is situated on an Face of the second shape Standard_EXPORT void ParOnFaceS2(const Standard_Integer N,Standard_Real& u,Standard_Real& v) const;
I think they provide the info you seek for.
I guess that they don't. Please correct me, if I am wrong.
- If the first shape is an edge, then the method ParOnEdgeS1 looks tempting. But as the documentation states, it returns the parameter, if the Nth solution is situated ON AN EDGE OF THE FIRST SHAPE, which is not the case since the first shape itself is the edge. In this case a BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnEdgeS1: ParOnEdgeS1 is impossible without EDGE") is thrown.
- The local distances are not available at all.
There is no contradiction between the fact that the first shape is an edge and Nth solution is situated on an edge. In this case all solutions will be situated on the edge or on one of its vertices.
Please see how it is used in OCCT sources, e.g. AIS_LengthDimension.cxx, lines 481-501, or better ShapeAnalysis_Edge.cxx, 986-1010.
What do you mean under local distances? The tool gives the distance by the method Value(). All other distances are within the range [Value(), Value()+deflection], by default deflection is 1e-7.
Your answer again was helpful. I have indeed misunderstood the reason for the BRepExtrema_UnCompatibleShape error. This error has appeared since the solution was a vertex of the edge (SupportTypeShape1(...) did not return BRepExtrema_IsOnEdge).
I still see two advantages of giving access to the solutions:
1. If (different from ShapeAnalysis_Edge) I need the edge parameter (for example because I want to call BOPTools_AlgoTools::MakeSplitEdge(...)) then calling the method EdgeParameter(parameter) of the solution allows writing more general code.
would suffice, because the edge parameter is always available from the solution, even if the support shape is a vertex. Right now I have to make a distinction of cases like in ShapeAnalysis_Edge.
2. There may be situations where there are several solutions. I have been working also with higher deflection values than 1e-7. In this case it might be necessary to iterate over the solutions and pick the one that fulfills additional criteria. This is more handy and quicker if the data is easily available.
I will check the way I have been using BRepExtrema_DistShapeShape and see whether I can improve it. If you consider my change proposal a serious design flaw, I can also get along without it.
I would like to a note to the second advantage: sometimes BRepExtrema_DistShapeShape computes more than one solution, even if the deflection value is not raised.
I will attach an example file with one edge and one vertex (one solution expected, but there are two!!!). One of the solutions seems spurious to me. I had seen cases like this before and that is the reason why I have switched to iterating over all solutions and choosing the one that comes closest to the input shape. These iterations where handier if BRepExtrema_DistShapeShape would allow access to its solutions.
Here is the code that leads to ambiguous solutions:
std::vector<TopoDS_Shape> importStep(const std::string file)
IFSelect_ReturnStatus status = reader.ReadFile(file.c_str());
if (status == IFSelect_RetDone)
bool failsonly = false;
int rootsNumber = reader.NbRootsForTransfer();
for (Standard_Integer rootIndex = 1; rootIndex <= rootsNumber; rootIndex++)
//bool ok =
int shapesNumber = reader.NbShapes();
if (shapesNumber > 0)
for (int shapeIndex = 1; shapeIndex <= shapesNumber; shapeIndex++)
TopoDS_Shape shape = reader.Shape(shapeIndex);
throw "Could not read in file.";
int main(int, char**)
std::vector<TopoDS_Shape> shapes = importStep("Extrema.stp");
for (const auto& shape : shapes)
for (TopExp_Explorer edgeExplorer(shape, TopAbs_EDGE, TopAbs_FACE);
edge = TopoDS::Edge(edgeExplorer.Current());
std::cout << "Edge found." << std::endl;
for (TopExp_Explorer vertexExplorer(shape, TopAbs_VERTEX, TopAbs_EDGE);
vertex = TopoDS::Vertex(vertexExplorer.Current());
std::cout << "Vertex found." << std::endl;
if (distanceComputer.NbSolution() > 1)
std::cerr << "There are " << distanceComputer.NbSolution()
<< " solutions. Distance of solution 1 and 2 is: "
distanceComputer.PointOnShape1(2)) << std::endl;
std::cout << "Calculation failed." << std::endl;
Extrema.stp (3,339 bytes)
|2018-05-14 15:55||BenjaminBihler||New Issue|
|2018-05-14 15:55||BenjaminBihler||Assigned To||=> BenjaminBihler|
|2018-05-14 16:07||git||Note Added: 0075964|
|2018-05-14 16:08||BenjaminBihler||Assigned To||BenjaminBihler => msv|
|2018-05-14 16:08||BenjaminBihler||Status||new => resolved|
|2018-05-14 16:08||BenjaminBihler||Steps to Reproduce Updated|
|2018-05-14 16:20||kgv||Summary||BRepExtrema_DistShapeShape Should Give Access to Its Solutions => Modeling Algorithms - BRepExtrema_DistShapeShape Should Give Access to Its Solutions|
|2018-05-14 17:00||msv||Note Added: 0075968|
|2018-05-14 17:00||msv||Assigned To||msv => BenjaminBihler|
|2018-05-14 17:00||msv||Status||resolved => feedback|
|2018-05-14 17:43||BenjaminBihler||Note Added: 0075969|
|2018-05-14 17:44||BenjaminBihler||Assigned To||BenjaminBihler => msv|
|2018-05-17 19:24||msv||Note Added: 0076019|
|2018-05-17 19:24||msv||Assigned To||msv => BenjaminBihler|
|2018-06-04 12:10||BenjaminBihler||Note Added: 0076580|
|2018-06-04 12:10||BenjaminBihler||Assigned To||BenjaminBihler => msv|
|2018-06-18 16:47||BenjaminBihler||Note Added: 0076820|
|2018-06-18 16:47||BenjaminBihler||File Added: Extrema.stp|
|2019-08-12 12:54||msv||Target Version||7.4.0 => 7.5.0|
|2020-09-14 22:58||msv||Target Version||7.5.0 => 7.6.0|
|2021-08-29 18:37||msv||Target Version||7.6.0 => 7.7.0|