|
|
|
@@ -0,0 +1,772 @@
|
|
|
|
|
// File: ShapeFix_LackingEdgeRecover.cxx
|
|
|
|
|
// Created: 10.10.2013
|
|
|
|
|
// Author: Briginas Ivan
|
|
|
|
|
|
|
|
|
|
#include <ShapeFix_LackingEdgeRecover.hxx>
|
|
|
|
|
|
|
|
|
|
#include <BRepBuilderAPI_MakeEdge.hxx>
|
|
|
|
|
#include <BRepBuilderAPI_MakeWire.hxx>
|
|
|
|
|
|
|
|
|
|
#include <BRep_Builder.hxx>
|
|
|
|
|
#include <BRep_Tool.hxx>
|
|
|
|
|
|
|
|
|
|
#include <Geom_Curve.hxx>
|
|
|
|
|
#include <Geom_Surface.hxx>
|
|
|
|
|
|
|
|
|
|
#include <BRepLib.hxx>
|
|
|
|
|
|
|
|
|
|
#include <Geom2d_BSplineCurve.hxx>
|
|
|
|
|
|
|
|
|
|
#include <gp_Pnt2d.hxx>
|
|
|
|
|
#include <gp_Pnt.hxx>
|
|
|
|
|
#include <gp_Vec2d.hxx>
|
|
|
|
|
|
|
|
|
|
#include <TColgp_Array1OfPnt2d.hxx>
|
|
|
|
|
#include <TColgp_SequenceOfPnt.hxx>
|
|
|
|
|
#include <TColStd_Array1OfReal.hxx>
|
|
|
|
|
#include <TColStd_Array1OfInteger.hxx>
|
|
|
|
|
|
|
|
|
|
#include <NCollection_List.hxx>
|
|
|
|
|
#include <NCollection_Map.hxx>
|
|
|
|
|
#include <NCollection_DataMap.hxx>
|
|
|
|
|
|
|
|
|
|
#include <TopoDS.hxx>
|
|
|
|
|
#include <TopoDS_Shape.hxx>
|
|
|
|
|
#include <TopoDS_Face.hxx>
|
|
|
|
|
#include <TopoDS_Edge.hxx>
|
|
|
|
|
#include <TopoDS_Vertex.hxx>
|
|
|
|
|
|
|
|
|
|
#include <TopExp.hxx>
|
|
|
|
|
#include <TopExp_Explorer.hxx>
|
|
|
|
|
|
|
|
|
|
#include <TopTools_IndexedMapOfShape.hxx>
|
|
|
|
|
#include <TopTools_ListIteratorOfListOfShape.hxx>
|
|
|
|
|
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
|
|
|
|
|
|
|
|
|
#include <ShapeBuild_Edge.hxx>
|
|
|
|
|
|
|
|
|
|
#include <ShapeExtend.hxx>
|
|
|
|
|
#include <ShapeExtend_WireData.hxx>
|
|
|
|
|
#include <ShapeBuild_ReShape.hxx>
|
|
|
|
|
|
|
|
|
|
#include <ShapeFix_Edge.hxx>
|
|
|
|
|
|
|
|
|
|
#include <Standard_Assert.hxx>
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_STANDARD_HANDLE (ShapeFix_LackingEdgeRecover, ShapeFix_Root)
|
|
|
|
|
IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_LackingEdgeRecover, ShapeFix_Root)
|
|
|
|
|
|
|
|
|
|
inline Standard_Boolean IsEqual(const TopoDS_Edge& theEdge1,
|
|
|
|
|
const TopoDS_Edge& theEdge2)
|
|
|
|
|
{
|
|
|
|
|
return theEdge1.IsSame(theEdge2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline Standard_Boolean IsEqual(const TopoDS_Face& theFace1,
|
|
|
|
|
const TopoDS_Face& theFace2)
|
|
|
|
|
{
|
|
|
|
|
return theFace1.IsEqual(theFace2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShapeFix_LackingEdgeRecover::ShapeFix_LackingEdgeRecover()
|
|
|
|
|
{
|
|
|
|
|
myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
|
|
|
|
|
SetPrecision(Precision::Confusion());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShapeFix_LackingEdgeRecover::ShapeFix_LackingEdgeRecover(const TopoDS_Shape& theShape)
|
|
|
|
|
{
|
|
|
|
|
this->Init(theShape);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TopoDS_Shape ShapeFix_LackingEdgeRecover::Shape() const
|
|
|
|
|
{
|
|
|
|
|
return myRecoveredShape;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShapeFix_LackingEdgeRecover::Init(const TopoDS_Shape& theShape)
|
|
|
|
|
{
|
|
|
|
|
myShape = theShape;
|
|
|
|
|
if ( Context().IsNull() )
|
|
|
|
|
SetContext ( new ShapeBuild_ReShape );
|
|
|
|
|
|
|
|
|
|
myRecoveredShape = theShape;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShapeFix_LackingEdgeRecover::Perform()
|
|
|
|
|
{
|
|
|
|
|
myRecoveredShape = Context()->Apply(myShape);
|
|
|
|
|
|
|
|
|
|
TopTools_IndexedDataMapOfShapeListOfShape aVertexEdgesMap, aVertexWiresMap,
|
|
|
|
|
anEdgeFacesMap, aWireFacesMap;
|
|
|
|
|
|
|
|
|
|
TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_VERTEX, TopAbs_EDGE, aVertexEdgesMap);
|
|
|
|
|
TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_VERTEX, TopAbs_WIRE, aVertexWiresMap);
|
|
|
|
|
TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_EDGE, TopAbs_FACE, anEdgeFacesMap);
|
|
|
|
|
TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_WIRE, TopAbs_FACE, aWireFacesMap);
|
|
|
|
|
|
|
|
|
|
NCollection_List< std::pair<TopoDS_Vertex, TopoDS_Vertex> > aVerticesForLackingEdgesBuilding;
|
|
|
|
|
typedef NCollection_DataMap<TopoDS_Face, Standard_Integer> FaceDataMap;
|
|
|
|
|
|
|
|
|
|
// search for vertices with tolerance greater than specified threshold (theMaxTol)
|
|
|
|
|
TopTools_IndexedMapOfShape aShapeVertexMap;
|
|
|
|
|
TopExp::MapShapes(myRecoveredShape, TopAbs_VERTEX, aShapeVertexMap);
|
|
|
|
|
|
|
|
|
|
Standard_Integer aVertIter = 1; // start from 1
|
|
|
|
|
for (; aVertIter <= aShapeVertexMap.Extent(); ++aVertIter)
|
|
|
|
|
{
|
|
|
|
|
TopoDS_Vertex aCurVertex = TopoDS::Vertex (aShapeVertexMap.FindKey(aVertIter));
|
|
|
|
|
Standard_Real aCurTol = BRep_Tool::Tolerance (aCurVertex);
|
|
|
|
|
|
|
|
|
|
// skip vertices with tolerance lesser than theMaxTol
|
|
|
|
|
if (aCurTol < this->MaxTolerance())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
const TopTools_ListOfShape& aSharingWiresOfCurVertex = aVertexWiresMap.FindFromKey (aCurVertex);
|
|
|
|
|
|
|
|
|
|
// process each edge
|
|
|
|
|
Standard_Boolean anIsVertexReplaced = Standard_False;
|
|
|
|
|
gp_Pnt aFirstNewPnt, aSecondNewPnt; // these points will replace vertex with big tolerance
|
|
|
|
|
|
|
|
|
|
TopTools_MapOfShape anUniqueSharingWiresOfCurVertex;
|
|
|
|
|
TopTools_ListIteratorOfListOfShape anWireIter(aSharingWiresOfCurVertex);
|
|
|
|
|
for (;anWireIter.More() && !anIsVertexReplaced; anWireIter.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Wire& aCurWire = TopoDS::Wire(anWireIter.Value());
|
|
|
|
|
|
|
|
|
|
if (!anUniqueSharingWiresOfCurVertex.Contains(aCurWire))
|
|
|
|
|
anUniqueSharingWiresOfCurVertex.Add(aCurWire);
|
|
|
|
|
else
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
const TopTools_ListOfShape& aSharingFacesOfCurWire =
|
|
|
|
|
aWireFacesMap.FindFromKey (anWireIter.Value());
|
|
|
|
|
|
|
|
|
|
// (IMPORTANT) process just first found face
|
|
|
|
|
TopTools_ListIteratorOfListOfShape aSharingFacesOfCurWireIter(aSharingFacesOfCurWire);
|
|
|
|
|
for (; aSharingFacesOfCurWireIter.More() && !anIsVertexReplaced; aSharingFacesOfCurWireIter.Next())
|
|
|
|
|
{
|
|
|
|
|
// replace the vertex if sharing wire is strip
|
|
|
|
|
anIsVertexReplaced = IsWireStrip(aCurWire, TopoDS::Face(aSharingFacesOfCurWireIter.Value()),
|
|
|
|
|
aCurVertex, aFirstNewPnt, aSecondNewPnt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//int todo_streach_degenerated_edge;
|
|
|
|
|
|
|
|
|
|
if (!anIsVertexReplaced)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const TopTools_ListOfShape& aSharingEdgesOfCurVertex =
|
|
|
|
|
aVertexEdgesMap.FindFromKey (aCurVertex);
|
|
|
|
|
|
|
|
|
|
FaceDataMap aSharingFacesMap;
|
|
|
|
|
Standard_Boolean anIsCurVertexSkipped = Standard_False;
|
|
|
|
|
|
|
|
|
|
// split sharing edges into two groups
|
|
|
|
|
TColgp_SequenceOfPnt aFirstPntList, aSecondPntList;
|
|
|
|
|
NCollection_Map<TopoDS_Edge> anEdgeMap;
|
|
|
|
|
TopTools_ListIteratorOfListOfShape aSharingEdgesOfCurVertexIter(aSharingEdgesOfCurVertex);
|
|
|
|
|
for (; aSharingEdgesOfCurVertexIter.More(); aSharingEdgesOfCurVertexIter.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Edge& aCurIntEdge = TopoDS::Edge(aSharingEdgesOfCurVertexIter.Value());
|
|
|
|
|
|
|
|
|
|
if (!anEdgeMap.Contains(aCurIntEdge))
|
|
|
|
|
anEdgeMap.Add(aCurIntEdge);
|
|
|
|
|
else
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!anEdgeFacesMap.Contains(aCurIntEdge))
|
|
|
|
|
continue;
|
|
|
|
|
const TopTools_ListOfShape& aSharingFacesOfCurIntEdge = anEdgeFacesMap.FindFromKey (aCurIntEdge);
|
|
|
|
|
|
|
|
|
|
if (aSharingFacesOfCurIntEdge.IsEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// collect all sharing faces
|
|
|
|
|
TopTools_ListIteratorOfListOfShape aSharingFacesIter(aSharingFacesOfCurIntEdge);
|
|
|
|
|
for(; aSharingFacesIter.More(); aSharingFacesIter.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Face aCurShFace = TopoDS::Face(aSharingFacesIter.Value());
|
|
|
|
|
|
|
|
|
|
if (!aSharingFacesMap.IsBound(aCurShFace))
|
|
|
|
|
aSharingFacesMap.Bind(aCurShFace, 1);
|
|
|
|
|
else
|
|
|
|
|
aSharingFacesMap(aCurShFace)++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// skip the case when a vertex is being shared by more
|
|
|
|
|
// than 2 edges that belong to one face
|
|
|
|
|
Standard_Integer aMaxNbEdgesOnOneFace = 2;
|
|
|
|
|
for (FaceDataMap::Iterator anIt(aSharingFacesMap);
|
|
|
|
|
anIt.More() && !anIsCurVertexSkipped; anIt.Next())
|
|
|
|
|
{
|
|
|
|
|
if (anIt.Value() > aMaxNbEdgesOnOneFace)
|
|
|
|
|
anIsCurVertexSkipped = Standard_True;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// break processing of edges that share the cur vertex
|
|
|
|
|
if (anIsCurVertexSkipped)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// take first sharing face
|
|
|
|
|
const TopoDS_Face& aCurIntFace = TopoDS::Face(aSharingFacesOfCurIntEdge.First());
|
|
|
|
|
|
|
|
|
|
TopLoc_Location aLocation;
|
|
|
|
|
Handle(Geom_Surface) aCurIntSurf = BRep_Tool::Surface (aCurIntFace, aLocation);
|
|
|
|
|
|
|
|
|
|
Standard_Real aPFirstParamOfCurIntEdge, aPLastParamOfCurIntEdge;
|
|
|
|
|
Handle(Geom2d_Curve) aPCurveOfCurIntEdge =
|
|
|
|
|
BRep_Tool::CurveOnSurface (aCurIntEdge, aCurIntFace,
|
|
|
|
|
aPFirstParamOfCurIntEdge, aPLastParamOfCurIntEdge);
|
|
|
|
|
|
|
|
|
|
// sort couple of vertices of the current internal edge
|
|
|
|
|
TopoDS_Iterator anVerticesIter(aCurIntEdge, TopAbs_VERTEX);
|
|
|
|
|
for (; anVerticesIter.More(); anVerticesIter.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Vertex& aCurInternalVertex = TopoDS::Vertex(anVerticesIter.Value());
|
|
|
|
|
|
|
|
|
|
if(!aCurInternalVertex.IsSame(aCurVertex))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
gp_Pnt2d anAddingPnt2D = ConvertTo2D(aCurIntEdge, aCurInternalVertex, aPCurveOfCurIntEdge,
|
|
|
|
|
aPFirstParamOfCurIntEdge, aPLastParamOfCurIntEdge);
|
|
|
|
|
|
|
|
|
|
gp_Pnt anAddingPnt;
|
|
|
|
|
aCurIntSurf->D0(anAddingPnt2D.X(), anAddingPnt2D.Y(), anAddingPnt);
|
|
|
|
|
|
|
|
|
|
Standard_Real aDist2ToFirstNewPnt = aFirstNewPnt.SquareDistance(anAddingPnt);
|
|
|
|
|
Standard_Real aDist2ToSecondNewPnt = aSecondNewPnt.SquareDistance(anAddingPnt);
|
|
|
|
|
|
|
|
|
|
if (aDist2ToFirstNewPnt < aDist2ToSecondNewPnt)
|
|
|
|
|
aFirstPntList.Append(anAddingPnt);
|
|
|
|
|
else
|
|
|
|
|
aSecondPntList.Append(anAddingPnt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (anIsCurVertexSkipped)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (aFirstPntList.IsEmpty() || aSecondPntList.IsEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// === process FIRST group
|
|
|
|
|
// mean point of first group
|
|
|
|
|
gp_XYZ aTotalXYZ;
|
|
|
|
|
for (Standard_Integer aCurIndex = 1; aCurIndex <= aFirstPntList.Length(); aCurIndex++)
|
|
|
|
|
aTotalXYZ += aFirstPntList.Value(aCurIndex).XYZ();
|
|
|
|
|
|
|
|
|
|
gp_Pnt aMeanFirstNewPnt(aTotalXYZ/aFirstPntList.Length());
|
|
|
|
|
// === END process FIRST group
|
|
|
|
|
|
|
|
|
|
// === process SECOND group
|
|
|
|
|
// mean point of second group
|
|
|
|
|
aTotalXYZ = gp_XYZ();
|
|
|
|
|
for (Standard_Integer aCurIndex = 1; aCurIndex <= aSecondPntList.Length(); aCurIndex++)
|
|
|
|
|
aTotalXYZ += aSecondPntList.Value(aCurIndex).XYZ();
|
|
|
|
|
|
|
|
|
|
gp_Pnt aMeanSecondNewPnt(aTotalXYZ/aSecondPntList.Length());
|
|
|
|
|
// === END process SECOND group
|
|
|
|
|
|
|
|
|
|
// create new vertices
|
|
|
|
|
BRep_Builder aBuilder;
|
|
|
|
|
TopoDS_Vertex aFirstNewVertex, aSecondNewVertex;
|
|
|
|
|
// tolerance of vertices will be corrected during future edge replacement
|
|
|
|
|
aBuilder.MakeVertex (aFirstNewVertex, aMeanFirstNewPnt, Precision::Confusion());
|
|
|
|
|
aBuilder.MakeVertex (aSecondNewVertex, aMeanSecondNewPnt, Precision::Confusion());
|
|
|
|
|
|
|
|
|
|
// fill in for building lacking edges
|
|
|
|
|
aVerticesForLackingEdgesBuilding.Append(std::make_pair(aFirstNewVertex, aSecondNewVertex));
|
|
|
|
|
|
|
|
|
|
// tool for fixing of vertex tolerance
|
|
|
|
|
Handle(ShapeFix_Edge) anEdgeFixer = new ShapeFix_Edge;
|
|
|
|
|
|
|
|
|
|
// update the shape to replace vertex with big tolerance by two new vertices
|
|
|
|
|
aSharingEdgesOfCurVertexIter.Initialize(aSharingEdgesOfCurVertex);
|
|
|
|
|
for (; aSharingEdgesOfCurVertexIter.More(); aSharingEdgesOfCurVertexIter.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Edge& aCurIntUnUpdatedEdge = TopoDS::Edge(aSharingEdgesOfCurVertexIter.Value());
|
|
|
|
|
|
|
|
|
|
// current updated edge
|
|
|
|
|
TopoDS_Edge aCurIntEdge = TopoDS::Edge(Context()->Apply(aCurIntUnUpdatedEdge));
|
|
|
|
|
|
|
|
|
|
// the copy of the current internal updated edge
|
|
|
|
|
TopoDS_Edge aModifedEdge = TopoDS::Edge(Context()->Apply(aCurIntUnUpdatedEdge));
|
|
|
|
|
|
|
|
|
|
// take first sharing face
|
|
|
|
|
const TopTools_ListOfShape& aSharingFacesOfCurIntEdge = anEdgeFacesMap.FindFromKey (aCurIntUnUpdatedEdge);
|
|
|
|
|
const TopoDS_Face& aCurIntFace = TopoDS::Face(aSharingFacesOfCurIntEdge.First());
|
|
|
|
|
|
|
|
|
|
TopoDS_Iterator aVertIterOfCurIntEdge(aCurIntEdge);
|
|
|
|
|
for (; aVertIterOfCurIntEdge.More(); aVertIterOfCurIntEdge.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Vertex& aCurVertexOfCurIntEdge = TopoDS::Vertex(aVertIterOfCurIntEdge.Value());
|
|
|
|
|
|
|
|
|
|
if (!aCurVertexOfCurIntEdge.IsSame(aCurVertex))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// replace the current vertex of the current internal edge by couple of new vertices
|
|
|
|
|
aModifedEdge = ReplaceVertex(aCurVertexOfCurIntEdge, aModifedEdge,
|
|
|
|
|
aCurIntFace, aFirstPntList,
|
|
|
|
|
aFirstNewVertex, aSecondNewVertex);
|
|
|
|
|
|
|
|
|
|
// increase tolerance of vertices of the modified
|
|
|
|
|
// edge if the ones don't cover the tolerance
|
|
|
|
|
// of the modified edge
|
|
|
|
|
anEdgeFixer->FixVertexTolerance(aModifedEdge);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// update the context
|
|
|
|
|
Context()->Replace(aCurIntEdge, aModifedEdge);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// apply the changes containing all replacements with vertices
|
|
|
|
|
myRecoveredShape = Context()->Apply(myRecoveredShape);
|
|
|
|
|
|
|
|
|
|
// add lacking edges into the modified shape (it doesn't contain vertices with big tolerance already)
|
|
|
|
|
TopTools_IndexedDataMapOfShapeListOfShape anUpdatedVertexWiresMap, anUpdatedWireFacesMap;
|
|
|
|
|
TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_VERTEX, TopAbs_WIRE, anUpdatedVertexWiresMap);
|
|
|
|
|
TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_WIRE, TopAbs_FACE, anUpdatedWireFacesMap);
|
|
|
|
|
|
|
|
|
|
NCollection_List< std::pair<TopoDS_Vertex, TopoDS_Vertex> >::Iterator
|
|
|
|
|
aVerticesForLackingEdgesIter(aVerticesForLackingEdgesBuilding);
|
|
|
|
|
|
|
|
|
|
// run through all pairs of new vertices to add lacking edge between them
|
|
|
|
|
for (; aVerticesForLackingEdgesIter.More(); aVerticesForLackingEdgesIter.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Vertex& aFirstNewVertex = aVerticesForLackingEdgesIter.Value().first;
|
|
|
|
|
const TopoDS_Vertex& aSecondNewVertex = aVerticesForLackingEdgesIter.Value().second;
|
|
|
|
|
|
|
|
|
|
// wires share the first new vertex
|
|
|
|
|
if (!anUpdatedVertexWiresMap.Contains(aFirstNewVertex))
|
|
|
|
|
continue;
|
|
|
|
|
const TopTools_ListOfShape& aSharingWiresOfFirstNewVertex =
|
|
|
|
|
anUpdatedVertexWiresMap.FindFromKey (aFirstNewVertex);
|
|
|
|
|
|
|
|
|
|
// wires share the second new vertex
|
|
|
|
|
if (!anUpdatedVertexWiresMap.Contains(aSecondNewVertex))
|
|
|
|
|
continue;
|
|
|
|
|
const TopTools_ListOfShape& aSharingWiresOfSecondNewVertex =
|
|
|
|
|
anUpdatedVertexWiresMap.FindFromKey (aSecondNewVertex);
|
|
|
|
|
|
|
|
|
|
// seek the intersection of two lists of sharing wires
|
|
|
|
|
TopTools_ListIteratorOfListOfShape anIterOfFirstWireList(aSharingWiresOfFirstNewVertex);
|
|
|
|
|
|
|
|
|
|
TopTools_ListOfShape anIntersectOfTwoLists;
|
|
|
|
|
for (; anIterOfFirstWireList.More(); anIterOfFirstWireList.Next())
|
|
|
|
|
{
|
|
|
|
|
TopTools_ListIteratorOfListOfShape anIterOfSecondWireList(aSharingWiresOfSecondNewVertex);
|
|
|
|
|
for (; anIterOfSecondWireList.More(); anIterOfSecondWireList.Next())
|
|
|
|
|
{
|
|
|
|
|
if (anIterOfFirstWireList.Value().IsSame(anIterOfSecondWireList.Value()))
|
|
|
|
|
anIntersectOfTwoLists.Append(anIterOfFirstWireList.Value());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tool for fixing of vertex tolerance to cover edge tolerance that contains this vertex
|
|
|
|
|
Handle(ShapeFix_Edge) anEdgeFixer = new ShapeFix_Edge;
|
|
|
|
|
TopoDS_Edge aLackingEdge;
|
|
|
|
|
BRep_Builder aBuilder;
|
|
|
|
|
|
|
|
|
|
// add lacking edge to each intersected wire by replacing one their edge
|
|
|
|
|
TopTools_ListIteratorOfListOfShape anIterOfIntersetionList(anIntersectOfTwoLists);
|
|
|
|
|
for (; anIterOfIntersetionList.More(); anIterOfIntersetionList.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Wire& aCurWire = TopoDS::Wire(anIterOfIntersetionList.Value());
|
|
|
|
|
|
|
|
|
|
// faces of doesn't updated wire
|
|
|
|
|
const TopTools_ListOfShape& aSharingFacesOfCurWire =
|
|
|
|
|
anUpdatedWireFacesMap.FindFromKey (aCurWire);
|
|
|
|
|
|
|
|
|
|
if (aSharingFacesOfCurWire.Extent() == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// _first_ found face containing the current wire
|
|
|
|
|
const TopoDS_Face& aCurFace = TopoDS::Face(aSharingFacesOfCurWire.First());
|
|
|
|
|
|
|
|
|
|
TopLoc_Location aLocation;
|
|
|
|
|
Handle(Geom_Surface) aCurSurf = BRep_Tool::Surface (aCurFace, aLocation);
|
|
|
|
|
|
|
|
|
|
TopoDS_Wire anUpdatedCurWire = TopoDS::Wire(Context()->Apply(aCurWire));
|
|
|
|
|
|
|
|
|
|
// seek 2d points (from doesn't updated wire) for 2d pcurve building
|
|
|
|
|
gp_Pnt2d aFirst2D, aSecond2D;
|
|
|
|
|
ConvertLackingVerticesTo2D(aCurWire, aCurFace, aFirstNewVertex, aSecondNewVertex, aFirst2D, aSecond2D);
|
|
|
|
|
|
|
|
|
|
// create 2d pcurve for lacking edge
|
|
|
|
|
const Handle(Geom2d_BSplineCurve)& aBSplineLackingCurve2D =
|
|
|
|
|
MakeBSplineLackingCurve2D(aFirst2D, aSecond2D);
|
|
|
|
|
|
|
|
|
|
if (aLackingEdge.IsNull())
|
|
|
|
|
aLackingEdge = BRepBuilderAPI_MakeEdge(aBSplineLackingCurve2D, aCurSurf, aFirstNewVertex, aSecondNewVertex);
|
|
|
|
|
|
|
|
|
|
// add pcurve to the lacking edge
|
|
|
|
|
aBuilder.UpdateEdge(aLackingEdge, aBSplineLackingCurve2D, aCurSurf, aLocation,
|
|
|
|
|
BRep_Tool::Tolerance(aLackingEdge));
|
|
|
|
|
|
|
|
|
|
// set orientation of the lacking edge
|
|
|
|
|
TopAbs_Orientation anOrientOfLackingEdge = TopAbs_FORWARD;
|
|
|
|
|
for (TopoDS_Iterator anEdgeIter(aCurWire); anEdgeIter.More(); anEdgeIter.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Edge& aCurIntEdge = TopoDS::Edge(anEdgeIter.Value());
|
|
|
|
|
|
|
|
|
|
if (aFirstNewVertex.IsSame(TopExp::FirstVertex(aCurIntEdge)))
|
|
|
|
|
{
|
|
|
|
|
if (aCurIntEdge.Orientation() == TopAbs_FORWARD)
|
|
|
|
|
anOrientOfLackingEdge = TopAbs_REVERSED;
|
|
|
|
|
else
|
|
|
|
|
anOrientOfLackingEdge = TopAbs_FORWARD;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (aFirstNewVertex.IsSame(TopExp::LastVertex(aCurIntEdge)))
|
|
|
|
|
{
|
|
|
|
|
if (aCurIntEdge.Orientation() == TopAbs_FORWARD)
|
|
|
|
|
anOrientOfLackingEdge = TopAbs_FORWARD;
|
|
|
|
|
else
|
|
|
|
|
anOrientOfLackingEdge = TopAbs_REVERSED;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aLackingEdge = TopoDS::Edge(aLackingEdge.Oriented(anOrientOfLackingEdge));
|
|
|
|
|
|
|
|
|
|
// add lacking edge to current wire
|
|
|
|
|
anUpdatedCurWire.Free(Standard_True);
|
|
|
|
|
aBuilder.Add(anUpdatedCurWire, aLackingEdge);
|
|
|
|
|
|
|
|
|
|
Context()->Replace(aCurWire, anUpdatedCurWire);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BRepLib::BuildCurve3d(aLackingEdge);
|
|
|
|
|
BRepLib::SameParameter(aLackingEdge, 1.e-5, Standard_True);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
myRecoveredShape = Context()->Apply(myRecoveredShape);
|
|
|
|
|
|
|
|
|
|
myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=======================================================================
|
|
|
|
|
//function : ReplaceVertex
|
|
|
|
|
//purpose : replace the input vertex by couple of new ones
|
|
|
|
|
//=======================================================================
|
|
|
|
|
TopoDS_Edge ShapeFix_LackingEdgeRecover::ReplaceVertex(const TopoDS_Vertex& theVert /*theBeingReplacedVertex*/,
|
|
|
|
|
const TopoDS_Edge& theEdge /*theBeingReplacedEdge */,
|
|
|
|
|
const TopoDS_Face& theFace,
|
|
|
|
|
const TColgp_SequenceOfPnt&
|
|
|
|
|
theListOfFirstPnt,
|
|
|
|
|
const TopoDS_Vertex& theFirstVertex,
|
|
|
|
|
const TopoDS_Vertex& theSecondVertex) const
|
|
|
|
|
{
|
|
|
|
|
Standard_Real aPFirstParamOfEdge, aPLastParamOfEdge;
|
|
|
|
|
Handle(Geom2d_Curve) aPCurveOfCurIntEdge =
|
|
|
|
|
BRep_Tool::CurveOnSurface (theEdge, theFace, aPFirstParamOfEdge, aPLastParamOfEdge);
|
|
|
|
|
|
|
|
|
|
TopAbs_Orientation anOrientOfVert = theVert.Orientation();
|
|
|
|
|
|
|
|
|
|
// seek the end of pcurve that shares the input vertex
|
|
|
|
|
gp_Pnt2d aBeingSoughtPnt2D = ConvertTo2D(theEdge, theVert, aPCurveOfCurIntEdge,
|
|
|
|
|
aPFirstParamOfEdge, aPLastParamOfEdge);
|
|
|
|
|
|
|
|
|
|
TopLoc_Location aLocation;
|
|
|
|
|
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (theFace, aLocation);
|
|
|
|
|
|
|
|
|
|
// convert the found end of pcurve to point in 3D space
|
|
|
|
|
gp_Pnt aBeingSoughtPnt;
|
|
|
|
|
aSurf->D0(aBeingSoughtPnt2D.X(), aBeingSoughtPnt2D.Y(), aBeingSoughtPnt);
|
|
|
|
|
|
|
|
|
|
// seek what list contains found 3D point
|
|
|
|
|
Standard_Boolean anIsBeingSoughtPntInFirstList = Standard_False;
|
|
|
|
|
Standard_Integer aCurIndex = 1;
|
|
|
|
|
for (; aCurIndex <= theListOfFirstPnt.Length() && !anIsBeingSoughtPntInFirstList; aCurIndex++)
|
|
|
|
|
if (aBeingSoughtPnt.Distance(theListOfFirstPnt.Value(aCurIndex)) <= Precision::Confusion())
|
|
|
|
|
anIsBeingSoughtPntInFirstList = Standard_True;
|
|
|
|
|
|
|
|
|
|
// choose what vertex in the edge will be replaced taking into account found
|
|
|
|
|
// list containing this found 3d point
|
|
|
|
|
TopoDS_Vertex aBeingSoughtVertex;
|
|
|
|
|
if (anIsBeingSoughtPntInFirstList)
|
|
|
|
|
aBeingSoughtVertex = TopoDS::Vertex(theFirstVertex.Oriented(anOrientOfVert));
|
|
|
|
|
else
|
|
|
|
|
aBeingSoughtVertex = TopoDS::Vertex(theSecondVertex.Oriented(anOrientOfVert));
|
|
|
|
|
|
|
|
|
|
TopoDS_Edge aModifiedEdge;
|
|
|
|
|
ShapeBuild_Edge anEdgeBuilder;
|
|
|
|
|
|
|
|
|
|
// replace the vertex in the edge by chosen vertex
|
|
|
|
|
if (anOrientOfVert == TopAbs_FORWARD)
|
|
|
|
|
aModifiedEdge = anEdgeBuilder.CopyReplaceVertices(theEdge, aBeingSoughtVertex, TopoDS_Vertex());
|
|
|
|
|
else
|
|
|
|
|
aModifiedEdge = anEdgeBuilder.CopyReplaceVertices(theEdge, TopoDS_Vertex(), aBeingSoughtVertex);
|
|
|
|
|
|
|
|
|
|
return aModifiedEdge;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=======================================================================
|
|
|
|
|
//function : IsWireStrip
|
|
|
|
|
//purpose : find out wire is strip or not
|
|
|
|
|
//=======================================================================
|
|
|
|
|
Standard_Boolean ShapeFix_LackingEdgeRecover::IsWireStrip(const TopoDS_Wire& theWire,
|
|
|
|
|
const TopoDS_Face& theFace,
|
|
|
|
|
const TopoDS_Vertex& theVertex,
|
|
|
|
|
gp_Pnt& theFirstPnt, gp_Pnt& theSecondPnt) const
|
|
|
|
|
{
|
|
|
|
|
// if the wide of the wire projection in parametric space of the face
|
|
|
|
|
// on vector (which is formed by the first and second input points; theirs analogues in
|
|
|
|
|
// parametric space of the face) will be less than this parameter - aStripRation
|
|
|
|
|
// then wire is detected as a strip
|
|
|
|
|
Standard_Real aStripRatio = 2.0;
|
|
|
|
|
|
|
|
|
|
// number of equidistant points on each edge for wire projection
|
|
|
|
|
// in parametric space on the vector that was described previously
|
|
|
|
|
Standard_Integer aPntNbPerEdgeForProj = 10;
|
|
|
|
|
|
|
|
|
|
// edges sharing the vertex
|
|
|
|
|
TopTools_ListOfShape aSharingEdges;
|
|
|
|
|
TopExp_Explorer aWireExp(theWire, TopAbs_EDGE);
|
|
|
|
|
for (; aWireExp.More(); aWireExp.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Edge& aCurEdge = TopoDS::Edge(aWireExp.Current());
|
|
|
|
|
if (!aCurEdge.IsNull())
|
|
|
|
|
{
|
|
|
|
|
TopExp_Explorer anEdgeExp(aCurEdge, TopAbs_VERTEX);
|
|
|
|
|
for (; anEdgeExp.More(); anEdgeExp.Next())
|
|
|
|
|
{
|
|
|
|
|
if (theVertex.IsSame(TopoDS::Vertex(anEdgeExp.Current())))
|
|
|
|
|
aSharingEdges.Append(aCurEdge);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aSharingEdges.IsEmpty())
|
|
|
|
|
return Standard_False;
|
|
|
|
|
|
|
|
|
|
NCollection_List<gp_Pnt2d> aPnt2DList;
|
|
|
|
|
gp_Pnt2d aPnt2D;
|
|
|
|
|
|
|
|
|
|
TopoDS_Vertex aFirstVertex,aLastVertex;
|
|
|
|
|
Standard_Real aFirstParam, aLastParam;
|
|
|
|
|
|
|
|
|
|
TopTools_ListIteratorOfListOfShape aSEdgeIter(aSharingEdges);
|
|
|
|
|
for (; aSEdgeIter.More(); aSEdgeIter.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Edge& anEdge = TopoDS::Edge(aSEdgeIter.Value());
|
|
|
|
|
TopExp::Vertices(anEdge, aFirstVertex, aLastVertex, Standard_False);
|
|
|
|
|
|
|
|
|
|
Handle(Geom2d_Curve) aPCurve =
|
|
|
|
|
BRep_Tool::CurveOnSurface (anEdge, theFace, aFirstParam, aLastParam);
|
|
|
|
|
|
|
|
|
|
if (theVertex.IsSame(aFirstVertex))
|
|
|
|
|
{
|
|
|
|
|
aPCurve->D0(aFirstParam, aPnt2D);
|
|
|
|
|
aPnt2DList.Append(aPnt2D);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (theVertex.IsSame(aLastVertex))
|
|
|
|
|
{
|
|
|
|
|
aPCurve->D0(aLastParam, aPnt2D);
|
|
|
|
|
aPnt2DList.Append(aPnt2D);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aPnt2DList.Extent() < 2)
|
|
|
|
|
return Standard_False;
|
|
|
|
|
|
|
|
|
|
gp_Pnt2d aFirstPnt2D, aSecondPnt2D;
|
|
|
|
|
|
|
|
|
|
NCollection_List<gp_Pnt2d>::Iterator aPnt2DIter(aPnt2DList);
|
|
|
|
|
|
|
|
|
|
// first param point
|
|
|
|
|
aFirstPnt2D = aPnt2DIter.Value();
|
|
|
|
|
|
|
|
|
|
// second param point
|
|
|
|
|
aPnt2DIter.Next();
|
|
|
|
|
aSecondPnt2D = aPnt2DIter.Value();
|
|
|
|
|
|
|
|
|
|
// todo: process other points if they exist
|
|
|
|
|
|
|
|
|
|
if (aFirstPnt2D.Distance(aSecondPnt2D) <= Precision::PConfusion())
|
|
|
|
|
return Standard_False;
|
|
|
|
|
|
|
|
|
|
// project points of edges on aPVec2D
|
|
|
|
|
Standard_Real aProjLength = ProjectTo2DVector(theWire, theFace, aPntNbPerEdgeForProj, aFirstPnt2D, aSecondPnt2D);
|
|
|
|
|
|
|
|
|
|
gp_Vec2d aVec2D(aFirstPnt2D, aSecondPnt2D);
|
|
|
|
|
|
|
|
|
|
if (aProjLength > aStripRatio*aVec2D.Magnitude())
|
|
|
|
|
return Standard_False;
|
|
|
|
|
|
|
|
|
|
TopLoc_Location aLocation;
|
|
|
|
|
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (theFace, aLocation);
|
|
|
|
|
|
|
|
|
|
aSurf->D0(aFirstPnt2D.X() , aFirstPnt2D.Y(), theFirstPnt);
|
|
|
|
|
aSurf->D0(aSecondPnt2D.X(), aSecondPnt2D.Y(), theSecondPnt);
|
|
|
|
|
|
|
|
|
|
return Standard_True;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=======================================================================
|
|
|
|
|
//function : ConvertLackingVerticesTo2D
|
|
|
|
|
//purpose :
|
|
|
|
|
//=======================================================================
|
|
|
|
|
void ShapeFix_LackingEdgeRecover::ConvertLackingVerticesTo2D(const TopoDS_Wire& theWire,
|
|
|
|
|
const TopoDS_Face& theFace,
|
|
|
|
|
const TopoDS_Vertex& theFirstVertex,
|
|
|
|
|
const TopoDS_Vertex& theSecondVertex,
|
|
|
|
|
gp_Pnt2d& theFirstPnt2D,
|
|
|
|
|
gp_Pnt2d& theSecondPnt2D) const
|
|
|
|
|
{
|
|
|
|
|
Standard_Boolean aHasFirstBeenFound = Standard_False;
|
|
|
|
|
Standard_Boolean aHasSecondBeenFound = Standard_False;
|
|
|
|
|
TopoDS_Iterator anEdgeIter(theWire);
|
|
|
|
|
for (; anEdgeIter.More(); anEdgeIter.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Edge& aCurEdge = TopoDS::Edge(anEdgeIter.Value());
|
|
|
|
|
|
|
|
|
|
Standard_Real aPFirstParamOfCurEdge, aPLastParamOfCurEdge;
|
|
|
|
|
Handle(Geom2d_Curve) aCurCurve2D =
|
|
|
|
|
BRep_Tool::CurveOnSurface(aCurEdge, theFace, aPFirstParamOfCurEdge, aPLastParamOfCurEdge);
|
|
|
|
|
|
|
|
|
|
TopoDS_Iterator aVertexIter(aCurEdge);
|
|
|
|
|
for (; aVertexIter.More(); aVertexIter.Next())
|
|
|
|
|
{
|
|
|
|
|
const TopoDS_Vertex& aCurVertex = TopoDS::Vertex(aVertexIter.Value());
|
|
|
|
|
if (!aHasFirstBeenFound)
|
|
|
|
|
{
|
|
|
|
|
if (theFirstVertex.IsSame(aCurVertex))
|
|
|
|
|
{
|
|
|
|
|
aHasFirstBeenFound = Standard_True;
|
|
|
|
|
theFirstPnt2D = ConvertTo2D(aCurEdge, aCurVertex, aCurCurve2D,
|
|
|
|
|
aPFirstParamOfCurEdge, aPLastParamOfCurEdge);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!aHasSecondBeenFound)
|
|
|
|
|
{
|
|
|
|
|
if (theSecondVertex.IsSame(aCurVertex))
|
|
|
|
|
{
|
|
|
|
|
aHasSecondBeenFound = Standard_True;
|
|
|
|
|
theSecondPnt2D = ConvertTo2D(aCurEdge, aCurVertex, aCurCurve2D,
|
|
|
|
|
aPFirstParamOfCurEdge, aPLastParamOfCurEdge);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aHasFirstBeenFound && aHasSecondBeenFound)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=======================================================================
|
|
|
|
|
//function : MakeBSplineLackingCurve2D
|
|
|
|
|
//purpose :
|
|
|
|
|
//=======================================================================
|
|
|
|
|
Handle(Geom2d_BSplineCurve) ShapeFix_LackingEdgeRecover::MakeBSplineLackingCurve2D(
|
|
|
|
|
const gp_Pnt2d& theFirstPnt2D,
|
|
|
|
|
const gp_Pnt2d& theSecondPnt2D) const
|
|
|
|
|
{
|
|
|
|
|
TColgp_Array1OfPnt2d aPolesOfBSplineCurve (1, 2);
|
|
|
|
|
aPolesOfBSplineCurve(1).SetCoord(theFirstPnt2D.X(), theFirstPnt2D.Y());
|
|
|
|
|
aPolesOfBSplineCurve(2).SetCoord(theSecondPnt2D.X(), theSecondPnt2D.Y());
|
|
|
|
|
|
|
|
|
|
TColStd_Array1OfReal aKnotesOfBSplineCurve(1, 2);
|
|
|
|
|
aKnotesOfBSplineCurve(1) = 0.0;
|
|
|
|
|
aKnotesOfBSplineCurve(2) = 1.0;
|
|
|
|
|
|
|
|
|
|
TColStd_Array1OfInteger aMultiplicities (1, 2);
|
|
|
|
|
aMultiplicities(1) = 2;
|
|
|
|
|
aMultiplicities(2) = 2;
|
|
|
|
|
|
|
|
|
|
return new Geom2d_BSplineCurve(aPolesOfBSplineCurve, aKnotesOfBSplineCurve, aMultiplicities, 1, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=======================================================================
|
|
|
|
|
//function : ConvertTo2D
|
|
|
|
|
//purpose :
|
|
|
|
|
//=======================================================================
|
|
|
|
|
gp_Pnt2d ShapeFix_LackingEdgeRecover::ConvertTo2D(const TopoDS_Edge& theEdge,
|
|
|
|
|
const TopoDS_Vertex& theVertex,
|
|
|
|
|
const Handle(Geom2d_Curve)& theCurve2D,
|
|
|
|
|
const Standard_Real thePFirst,
|
|
|
|
|
const Standard_Real thePLast) const
|
|
|
|
|
{
|
|
|
|
|
gp_Pnt2d aPnt2d;
|
|
|
|
|
if (theEdge.Orientation() == TopAbs_FORWARD)
|
|
|
|
|
{
|
|
|
|
|
if (theVertex.Orientation() == TopAbs_FORWARD)
|
|
|
|
|
theCurve2D->D0(thePFirst, aPnt2d);
|
|
|
|
|
else
|
|
|
|
|
theCurve2D->D0(thePLast, aPnt2d);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (theVertex.Orientation() == TopAbs_FORWARD)
|
|
|
|
|
theCurve2D->D0(thePLast, aPnt2d);
|
|
|
|
|
else
|
|
|
|
|
theCurve2D->D0(thePFirst, aPnt2d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return aPnt2d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=======================================================================
|
|
|
|
|
//function : ProjectTo2DVector
|
|
|
|
|
//purpose :
|
|
|
|
|
//=======================================================================
|
|
|
|
|
Standard_Real ShapeFix_LackingEdgeRecover::ProjectTo2DVector(const TopoDS_Wire& theWire,
|
|
|
|
|
const TopoDS_Face& theFace,
|
|
|
|
|
const Standard_Real thePntNbPerEdgeForProj,
|
|
|
|
|
const gp_Pnt2d& thePFirst2D,
|
|
|
|
|
const gp_Pnt2d& thePSecond2D) const
|
|
|
|
|
{
|
|
|
|
|
gp_Vec2d aPVec2D(thePFirst2D, thePSecond2D);
|
|
|
|
|
|
|
|
|
|
// the wire is explored by BRepTools_WireExplorer and it is
|
|
|
|
|
// guaranteed that edges will be SEQUENCIALLY connected
|
|
|
|
|
Standard_Boolean isNOTExpByBRepTools_WireExplorer = Standard_False;
|
|
|
|
|
Handle(ShapeExtend_WireData) aWireData =
|
|
|
|
|
new ShapeExtend_WireData(theWire, isNOTExpByBRepTools_WireExplorer);
|
|
|
|
|
|
|
|
|
|
Standard_Integer aStartIndex = 1; // start index of ShapeExtend_WireData
|
|
|
|
|
Standard_Integer anEndIndex = aWireData->NbEdges();
|
|
|
|
|
|
|
|
|
|
// project points of edges on aPVec2D
|
|
|
|
|
Standard_Real aMaxWireValue = -Precision::Infinite();
|
|
|
|
|
Standard_Real aMinWireValue = Precision::Infinite();
|
|
|
|
|
|
|
|
|
|
Standard_Integer aCurEdgeIndex = aStartIndex;
|
|
|
|
|
for (; aCurEdgeIndex <= anEndIndex; aCurEdgeIndex++)
|
|
|
|
|
{
|
|
|
|
|
Standard_Real aPFirstParamOfIntCurEdge, aPLastParamOfIntCurEdge;
|
|
|
|
|
Handle(Geom2d_Curve) aPCurveOfIntCurEdge =
|
|
|
|
|
BRep_Tool::CurveOnSurface (aWireData->Edge(aCurEdgeIndex), theFace,
|
|
|
|
|
aPFirstParamOfIntCurEdge, aPLastParamOfIntCurEdge);
|
|
|
|
|
|
|
|
|
|
// split the curve of the current edge on aPntNbPerEdgeForProj parts
|
|
|
|
|
Standard_Integer aCurStep = 0;
|
|
|
|
|
Standard_Real aPCurParam = aPFirstParamOfIntCurEdge;
|
|
|
|
|
Standard_Real aStepSize = (aPLastParamOfIntCurEdge - aPFirstParamOfIntCurEdge)/thePntNbPerEdgeForProj;
|
|
|
|
|
while (aPCurParam <= aPLastParamOfIntCurEdge)
|
|
|
|
|
{
|
|
|
|
|
aPCurParam = aPFirstParamOfIntCurEdge + aCurStep*aStepSize;
|
|
|
|
|
|
|
|
|
|
gp_Pnt2d aPCur2D;
|
|
|
|
|
aPCurveOfIntCurEdge->D0(aPCurParam, aPCur2D);
|
|
|
|
|
|
|
|
|
|
// project current parametric point on the vector (by scalar product)
|
|
|
|
|
Standard_Real aStepFromPFirst2D = aPVec2D*gp_Vec2d(thePFirst2D, aPCur2D) / aPVec2D.Magnitude();
|
|
|
|
|
|
|
|
|
|
aMaxWireValue = Max(aMaxWireValue, aStepFromPFirst2D);
|
|
|
|
|
aMinWireValue = Min(aMinWireValue, aStepFromPFirst2D);
|
|
|
|
|
|
|
|
|
|
aCurStep++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Abs(aMaxWireValue - aMinWireValue);
|
|
|
|
|
}
|