View Issue Details
ID  Project  Category  View Status  Date Submitted  Last Update 

0029766  Community  OCCT:Modeling Algorithms  public  20180514 15:55  20221024 10:43 
Reporter  BenjaminBihler  Assigned To  msv  
Priority  normal  Severity  minor  
Status  feedback  Resolution  open  
Product Version  7.2.0  
Target Version  7.8.0  
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. SHA1: 75f3b333f1a8c26086a24714ab9e3c208a589fcd 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 481501, or better ShapeAnalysis_Edge.cxx, 9861010. 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 1e7. 

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. The line distanceComputer.Solution1(solution1).EdgeParameter(parameter1); 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 1e7. 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: #include <TopoDS_Shell.hxx> #include <TopoDS_Edge.hxx> #include <BRepExtrema_DistShapeShape.hxx> #include <TopoDS.hxx> #include <STEPControl_Reader.hxx> #include <Precision.hxx> #include <TopExp_Explorer.hxx> #include <string> #include <vector> #include <iostream> std::vector<TopoDS_Shape> importStep(const std::string file) { std::vector<TopoDS_Shape> shapes; STEPControl_Reader reader; IFSelect_ReturnStatus status = reader.ReadFile(file.c_str()); if (status == IFSelect_RetDone) { //Interface_TraceFile::SetDefault(); bool failsonly = false; reader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity); int rootsNumber = reader.NbRootsForTransfer(); reader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity); for (Standard_Integer rootIndex = 1; rootIndex <= rootsNumber; rootIndex++) { //bool ok = reader.TransferRoot(rootIndex); int shapesNumber = reader.NbShapes(); if (shapesNumber > 0) { for (int shapeIndex = 1; shapeIndex <= shapesNumber; shapeIndex++) { TopoDS_Shape shape = reader.Shape(shapeIndex); shapes.push_back(shape); } } } } else { throw "Could not read in file."; } return shapes; } int main(int, char**) { std::vector<TopoDS_Shape> shapes = importStep("Extrema.stp"); TopoDS_Edge edge; TopoDS_Vertex vertex; for (const auto& shape : shapes) { for (TopExp_Explorer edgeExplorer(shape, TopAbs_EDGE, TopAbs_FACE); edgeExplorer.More(); edgeExplorer.Next()) { edge = TopoDS::Edge(edgeExplorer.Current()); std::cout << "Edge found." << std::endl; break; } for (TopExp_Explorer vertexExplorer(shape, TopAbs_VERTEX, TopAbs_EDGE); vertexExplorer.More(); vertexExplorer.Next()) { vertex = TopoDS::Vertex(vertexExplorer.Current()); std::cout << "Vertex found." << std::endl; break; } } BRepExtrema_DistShapeShape distanceComputer; distanceComputer.SetFlag(Extrema_ExtFlag_MIN); distanceComputer.LoadS1(edge); distanceComputer.LoadS2(vertex); distanceComputer.Perform(); if (distanceComputer.IsDone()) { if (distanceComputer.NbSolution() > 1) { std::cerr << "There are " << distanceComputer.NbSolution() << " solutions. Distance of solution 1 and 2 is: " << distanceComputer.PointOnShape1(1).Distance( distanceComputer.PointOnShape1(2)) << std::endl; } } else { std::cout << "Calculation failed." << std::endl; } return 0; } 

Extrema.stp (3,339 bytes) 
Date Modified  Username  Field  Change 

20180514 15:55  BenjaminBihler  New Issue  
20180514 15:55  BenjaminBihler  Assigned To  => BenjaminBihler 
20180514 16:07  git  Note Added: 0075964  
20180514 16:08  BenjaminBihler  Assigned To  BenjaminBihler => msv 
20180514 16:08  BenjaminBihler  Status  new => resolved 
20180514 16:08  BenjaminBihler  Steps to Reproduce Updated  
20180514 16:20  kgv  Summary  BRepExtrema_DistShapeShape Should Give Access to Its Solutions => Modeling Algorithms  BRepExtrema_DistShapeShape Should Give Access to Its Solutions 
20180514 17:00  msv  Note Added: 0075968  
20180514 17:00  msv  Assigned To  msv => BenjaminBihler 
20180514 17:00  msv  Status  resolved => feedback 
20180514 17:43  BenjaminBihler  Note Added: 0075969  
20180514 17:44  BenjaminBihler  Assigned To  BenjaminBihler => msv 
20180517 19:24  msv  Note Added: 0076019  
20180517 19:24  msv  Assigned To  msv => BenjaminBihler 
20180604 12:10  BenjaminBihler  Note Added: 0076580  
20180604 12:10  BenjaminBihler  Assigned To  BenjaminBihler => msv 
20180618 16:47  BenjaminBihler  Note Added: 0076820  
20180618 16:47  BenjaminBihler  File Added: Extrema.stp  
20190812 12:54  msv  Target Version  7.4.0 => 7.5.0 
20200914 22:58  msv  Target Version  7.5.0 => 7.6.0 
20210829 18:37  msv  Target Version  7.6.0 => 7.7.0 
20221024 10:43  szy  Target Version  7.7.0 => 7.8.0 