mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-03 17:56:21 +03:00
772 lines
24 KiB
C++
772 lines
24 KiB
C++
// Created on: 2015-04-24
|
|
// Created by: NIKOLAI BUKHALOV
|
|
// Copyright (c) 2015 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 <BRepBuilderAPI_FastSewing.hxx>
|
|
|
|
#include <BRepTools_Quilt.hxx>
|
|
#include <Bnd_Box.hxx>
|
|
|
|
#include <Geom2d_Line.hxx>
|
|
#include <Geom2d_TrimmedCurve.hxx>
|
|
#include <Geom_Curve.hxx>
|
|
#include <Geom_RectangularTrimmedSurface.hxx>
|
|
#include <Geom_Surface.hxx>
|
|
|
|
#include <Precision.hxx>
|
|
|
|
#include <Standard_NullObject.hxx>
|
|
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopTools_MapOfShape.hxx>
|
|
|
|
|
|
IMPLEMENT_STANDARD_RTTIEXT(BRepBuilderAPI_FastSewing,Standard_Transient)
|
|
|
|
//=======================================================================
|
|
//function : IntersetctionOfSets
|
|
//purpose : Returns minimal value of intersection result
|
|
//=======================================================================
|
|
static Standard_Integer
|
|
IntersectionOfSets( const NCollection_List<Standard_Integer>& theSet1,
|
|
const NCollection_List<Standard_Integer>& theSet2)
|
|
{
|
|
constexpr Standard_Integer anIntMax = IntegerLast();
|
|
Standard_Integer aRetVal = anIntMax;
|
|
for(NCollection_List<Standard_Integer>::Iterator
|
|
anIt1 = theSet1.begin().Iterator();
|
|
anIt1.More(); anIt1.Next())
|
|
{
|
|
const Standard_Integer aVal1 = anIt1.Value();
|
|
for(NCollection_List<Standard_Integer>::Iterator
|
|
anIt2 = theSet2.begin().Iterator();
|
|
anIt2.More(); anIt2.Next())
|
|
{
|
|
const Standard_Integer aVal2 = anIt2.Value();
|
|
if(aVal1 == aVal2)
|
|
{
|
|
//theIntersectionResult.Append(aVal1);
|
|
if(aVal1 < aRetVal)
|
|
aRetVal = aVal1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(aRetVal == anIntMax)
|
|
return -1;
|
|
|
|
return aRetVal;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Get2DCurve
|
|
//purpose :
|
|
//=======================================================================
|
|
static Handle(Geom2d_Curve)
|
|
Get2DCurve( const Standard_Integer theIndex,
|
|
const Standard_Real theUfirst,
|
|
const Standard_Real theUlast,
|
|
const Standard_Real theVfirst,
|
|
const Standard_Real theVlast,
|
|
const Standard_Boolean theIsReverse = Standard_False)
|
|
{
|
|
if((theIndex < 0) || (theIndex > 3))
|
|
throw Standard_OutOfRange("BRepBuilderAPI_FastSewing.cxx, Get2DCurve(): OUT of Range");
|
|
|
|
Handle(Geom2d_Curve) a2dCurv;
|
|
|
|
if(!theIsReverse)
|
|
{
|
|
switch(theIndex)
|
|
{
|
|
case 0:
|
|
a2dCurv =
|
|
new Geom2d_TrimmedCurve(new Geom2d_Line(
|
|
gp_Pnt2d(0.0, theVfirst), gp_Dir2d(1.0,0.0)),
|
|
theUfirst, theUlast);
|
|
break;
|
|
case 1:
|
|
a2dCurv =
|
|
new Geom2d_TrimmedCurve(new Geom2d_Line(
|
|
gp_Pnt2d(theUlast, 0.0), gp_Dir2d(0.0,1.0)),
|
|
theVfirst, theVlast);
|
|
break;
|
|
case 2:
|
|
a2dCurv =
|
|
new Geom2d_TrimmedCurve(new Geom2d_Line(
|
|
gp_Pnt2d(0.0, theVlast), gp_Dir2d(1.0,0.0)),
|
|
theUfirst, theUlast);
|
|
break;
|
|
case 3:
|
|
a2dCurv =
|
|
new Geom2d_TrimmedCurve(new Geom2d_Line(
|
|
gp_Pnt2d(theUfirst, 0.0), gp_Dir2d(0.0,1.0)),
|
|
theVfirst, theVlast);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch(theIndex)
|
|
{
|
|
case 0:
|
|
a2dCurv =
|
|
new Geom2d_TrimmedCurve(new Geom2d_Line(
|
|
gp_Pnt2d(theUfirst+theUlast, theVfirst),
|
|
gp_Dir2d(-1.0,0.0)),
|
|
theUfirst, theUlast);
|
|
break;
|
|
case 1:
|
|
a2dCurv =
|
|
new Geom2d_TrimmedCurve(new Geom2d_Line(
|
|
gp_Pnt2d(theUlast, theVfirst+theVlast),
|
|
gp_Dir2d(0.0,-1.0)),
|
|
theVfirst, theVlast);
|
|
break;
|
|
case 2:
|
|
a2dCurv =
|
|
new Geom2d_TrimmedCurve(new Geom2d_Line(
|
|
gp_Pnt2d(theUfirst+theUlast, theVlast),
|
|
gp_Dir2d(-1.0,0.0)),
|
|
theUfirst, theUlast);
|
|
break;
|
|
case 3:
|
|
a2dCurv =
|
|
new Geom2d_TrimmedCurve(new Geom2d_Line(
|
|
gp_Pnt2d(theUfirst, theVfirst+theVlast),
|
|
gp_Dir2d(0.0,-1.0)),
|
|
theVfirst, theVlast);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return a2dCurv;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Constructor
|
|
//purpose :
|
|
//=======================================================================
|
|
BRepBuilderAPI_FastSewing::
|
|
BRepBuilderAPI_FastSewing( const Standard_Real theTol):
|
|
myTolerance(theTol),
|
|
myStatusList(0)
|
|
{
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Add
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BRepBuilderAPI_FastSewing::Add(const TopoDS_Shape& theShape)
|
|
{
|
|
Standard_Boolean aResult = Standard_False;
|
|
if(theShape.IsNull())
|
|
{
|
|
SetStatus(FS_EmptyInput);
|
|
return aResult;
|
|
}
|
|
|
|
TopTools_MapOfShape aMS;
|
|
//aMS.Add(theShape);
|
|
TopExp_Explorer aFExp(theShape,TopAbs_FACE);
|
|
for (; aFExp.More(); aFExp.Next())
|
|
{
|
|
const TopoDS_Face& aFace = TopoDS::Face(aFExp.Current());
|
|
if(aMS.Add(aFace))
|
|
{
|
|
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
|
|
if(aSurf.IsNull())
|
|
{
|
|
SetStatus(FS_FaceWithNullSurface);
|
|
continue;
|
|
}
|
|
|
|
if(aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
|
|
{
|
|
SetStatus(FS_NotNaturalBoundsFace);
|
|
continue;
|
|
}
|
|
|
|
Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
|
|
aSurf->Bounds(aUf, aUl, aVf, aVl);
|
|
|
|
if(Precision::IsInfinite(aUf) || Precision::IsInfinite(aUl) ||
|
|
Precision::IsInfinite(aVf) || Precision::IsInfinite(aVl))
|
|
{
|
|
SetStatus(FS_InfiniteSurface);
|
|
continue;
|
|
}
|
|
|
|
FS_Face aFFace;
|
|
aFFace.mySrcFace = aFace;
|
|
aFFace.myID = myFaceVec.Length();//because start index is 0
|
|
myFaceVec.Append(aFFace);
|
|
aResult = Standard_True;
|
|
}
|
|
}
|
|
|
|
return aResult;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Add
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BRepBuilderAPI_FastSewing::Add(const Handle(Geom_Surface)& theSurface)
|
|
{
|
|
if(theSurface.IsNull())
|
|
{
|
|
SetStatus(FS_FaceWithNullSurface);
|
|
return Standard_False;
|
|
}
|
|
|
|
if(theSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
|
|
{
|
|
SetStatus(FS_NotNaturalBoundsFace);
|
|
return Standard_False;
|
|
}
|
|
|
|
Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
|
|
theSurface->Bounds(aUf, aUl, aVf, aVl);
|
|
|
|
if(Precision::IsInfinite(aUf) || Precision::IsInfinite(aUl) ||
|
|
Precision::IsInfinite(aVf) || Precision::IsInfinite(aVl))
|
|
{
|
|
SetStatus(FS_InfiniteSurface);
|
|
return Standard_False;
|
|
}
|
|
|
|
FS_Face aFace;
|
|
|
|
BRep_Builder aBuilder;
|
|
aBuilder.MakeFace(aFace.mySrcFace);
|
|
aBuilder.MakeFace(aFace.mySrcFace, theSurface, myTolerance);
|
|
aBuilder.NaturalRestriction(aFace.mySrcFace, Standard_True);
|
|
|
|
aFace.myID = myFaceVec.Length();//because start index is 0
|
|
myFaceVec.Append(aFace);
|
|
|
|
return Standard_True;
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//function : Perform
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepBuilderAPI_FastSewing::Perform(void)
|
|
{
|
|
if(myFaceVec.IsEmpty())
|
|
{
|
|
SetStatus(FS_EmptyInput);
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
{
|
|
// create vertices having unique coordinates
|
|
Standard_Real aRange = Compute3DRange();
|
|
Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
|
|
NCollection_CellFilter<NodeInspector>
|
|
aCells(Max(myTolerance, aRange/IntegerLast()), anAlloc);
|
|
|
|
for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
|
|
{
|
|
FindVertexes(i, aCells);
|
|
}
|
|
}
|
|
|
|
for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
|
|
{
|
|
FindEdges(i);
|
|
}
|
|
|
|
//Create topological structures
|
|
|
|
for(Standard_Integer i = myVertexVec.Lower(); i <= myVertexVec.Upper(); i++)
|
|
{
|
|
myVertexVec.ChangeValue(i).CreateTopologicalVertex(myTolerance);
|
|
}
|
|
|
|
//Edges
|
|
for(Standard_Integer i = myEdgeVec.Lower(); i <= myEdgeVec.Upper(); i++)
|
|
{
|
|
myEdgeVec.ChangeValue(i).CreateTopologicalEdge(myVertexVec, myFaceVec, myTolerance);
|
|
}
|
|
|
|
//Shell
|
|
BRepTools_Quilt aQuilt;
|
|
|
|
//Faces
|
|
for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
|
|
{
|
|
FS_Face& aFace = myFaceVec.ChangeValue(i);
|
|
aFace.CreateTopologicalWire(myEdgeVec, myTolerance);
|
|
aFace.CreateTopologicalFace();
|
|
aQuilt.Add(aFace.myRetFace);
|
|
}
|
|
|
|
myResShape = aQuilt.Shells();
|
|
}
|
|
catch(Standard_Failure const&)
|
|
{
|
|
SetStatus(FS_Exception);
|
|
#ifdef OCCT_DEBUG
|
|
//Standard_Failure::Caught()->Print(std::cout);
|
|
#endif
|
|
return;
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UpdateEdgeInfo
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepBuilderAPI_FastSewing::UpdateEdgeInfo( const Standard_Integer theIDPrevVertex,
|
|
const Standard_Integer theIDCurrVertex,
|
|
const Standard_Integer theFaceID,
|
|
const Standard_Integer theIDCurvOnFace)
|
|
{
|
|
//Indeed, two vertices combine into one edge only.
|
|
const Standard_Integer anEdgeID =
|
|
IntersectionOfSets(myVertexVec.Value(theIDPrevVertex).myEdges,
|
|
myVertexVec.Value(theIDCurrVertex).myEdges);
|
|
|
|
//For DEBUG mode only
|
|
Standard_ProgramError_Raise_if(anEdgeID < 0,
|
|
"BRepBuilderAPI_FastSewing::UpdateEdgeInfo: Update not existing edge.");
|
|
|
|
FS_Edge& anEdge = myEdgeVec.ChangeValue(anEdgeID);
|
|
anEdge.myFaces.Append(theFaceID);
|
|
FS_Face& aFace = myFaceVec.ChangeValue(theFaceID);
|
|
aFace.SetEdge(theIDCurvOnFace, anEdge.myID);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CreateNewEdge
|
|
//purpose : Creates FS_Edge
|
|
//=======================================================================
|
|
void BRepBuilderAPI_FastSewing::CreateNewEdge(const Standard_Integer theIDPrevVertex,
|
|
const Standard_Integer theIDCurrVertex,
|
|
const Standard_Integer theFaceID,
|
|
const Standard_Integer theIDCurvOnFace)
|
|
{
|
|
FS_Edge anEdge(theIDPrevVertex, theIDCurrVertex);
|
|
anEdge.myID = myEdgeVec.Length(); //because start index is 0
|
|
|
|
|
|
anEdge.myFaces.Append(theFaceID);
|
|
FS_Face& aFace = myFaceVec.ChangeValue(theFaceID);
|
|
aFace.SetEdge(theIDCurvOnFace, anEdge.myID);
|
|
|
|
myVertexVec.ChangeValue(theIDPrevVertex).myEdges.Append(anEdge.myID);
|
|
|
|
if(theIDPrevVertex == theIDCurrVertex)
|
|
{//the Edge is degenerated
|
|
SetStatus(FS_Degenerated);
|
|
}
|
|
else
|
|
{
|
|
myVertexVec.ChangeValue(theIDCurrVertex).myEdges.Append(anEdge.myID);
|
|
}
|
|
|
|
myEdgeVec.Append(anEdge);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FindVertexes
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepBuilderAPI_FastSewing::
|
|
FindVertexes(const Standard_Integer theSurfID,
|
|
NCollection_CellFilter<NodeInspector>& theCells)
|
|
{
|
|
const Standard_Integer aNbPoints = 4;
|
|
FS_Face& aFace = myFaceVec.ChangeValue(theSurfID);
|
|
const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace.mySrcFace);
|
|
Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
|
|
aSurf->Bounds(aUf, aUl, aVf, aVl);
|
|
|
|
const gp_Pnt aPnts[aNbPoints] = { aSurf->Value(aUf, aVf),
|
|
aSurf->Value(aUl, aVf),
|
|
aSurf->Value(aUl, aVl),
|
|
aSurf->Value(aUf, aVl)};
|
|
|
|
for(Standard_Integer i = 0; i < aNbPoints; i++)
|
|
{
|
|
FS_Vertex aVert;
|
|
|
|
NodeInspector anInspector(myVertexVec, aPnts[i], myTolerance);
|
|
Bnd_Box aBox;
|
|
aBox.Add(aPnts[i]);
|
|
aBox.Enlarge(myTolerance);
|
|
|
|
theCells.Inspect(aBox.CornerMin().XYZ(), aBox.CornerMax().XYZ(), anInspector);
|
|
NodeInspector::Target aResID = anInspector.GetResult();
|
|
|
|
if(aResID < 0)
|
|
{//Add new Vertex
|
|
aVert.myID = myVertexVec.Length(); //because start index is 0
|
|
aVert.myPnt = aPnts[i];
|
|
aVert.myFaces.Append(theSurfID);
|
|
myVertexVec.Append(aVert);
|
|
aFace.SetVertex(i, aVert.myID);
|
|
|
|
theCells.Add(aVert.myID, aBox.CornerMin().XYZ(), aBox.CornerMax().XYZ());
|
|
}
|
|
else
|
|
{//Change existing vertex
|
|
aFace.SetVertex(i, aResID);
|
|
myVertexVec.ChangeValue(aResID).myFaces.Append(theSurfID);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FindEdges
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepBuilderAPI_FastSewing::FindEdges(const Standard_Integer theSurfID)
|
|
{
|
|
const Standard_Integer aNbPoints = 4;
|
|
FS_Face& aFace = myFaceVec.ChangeValue(theSurfID);
|
|
|
|
const Standard_Integer aFirstInd[aNbPoints] = {0, 1, 3, 0};
|
|
const Standard_Integer aLastInd[aNbPoints] = {1, 2, 2, 3};
|
|
|
|
for(Standard_Integer i = 0; i < aNbPoints; i++)
|
|
{
|
|
const Standard_Integer aFirstVertIndex = aFirstInd[i],
|
|
aLastVertIndex = aLastInd[i];
|
|
const Standard_Integer aFirstVertID = aFace.myVertices[aFirstVertIndex],
|
|
aLastVertID = aFace.myVertices[aLastVertIndex];
|
|
|
|
if(aFirstVertID == aLastVertID)
|
|
{//Edge is degenerated.
|
|
CreateNewEdge(aFirstVertID, aLastVertID, theSurfID, i);
|
|
continue;
|
|
}
|
|
|
|
//Must be minimal element from list
|
|
const Standard_Integer anIntRes =
|
|
IntersectionOfSets(myVertexVec.Value(aFirstVertID).myFaces,
|
|
myVertexVec.Value(aLastVertID).myFaces);
|
|
|
|
if((anIntRes < 0) || (anIntRes >= theSurfID))
|
|
{
|
|
CreateNewEdge(aFirstVertID, aLastVertID, theSurfID, i);
|
|
}
|
|
else
|
|
{//if(theSurfID > anIntRes) => The edge has been processed earlier
|
|
UpdateEdgeInfo(aFirstVertID, aLastVertID, theSurfID, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetStatuses
|
|
//purpose :
|
|
//=======================================================================
|
|
BRepBuilderAPI_FastSewing::FS_VARStatuses
|
|
BRepBuilderAPI_FastSewing::GetStatuses(Standard_OStream* const theOS)
|
|
{
|
|
if(!theOS)
|
|
return myStatusList;
|
|
|
|
if(!myStatusList)
|
|
{
|
|
*theOS << "Fast Sewing OK!\n";
|
|
return myStatusList;
|
|
}
|
|
|
|
//Number of bits
|
|
const Standard_Integer aNumMax = 8*sizeof(myStatusList);
|
|
FS_Statuses anIDS = static_cast<FS_Statuses>(0x0001);
|
|
for(Standard_Integer i = 1; i <= aNumMax; i++,
|
|
anIDS = static_cast<FS_Statuses>(anIDS << 1))
|
|
{
|
|
if((anIDS & myStatusList) == 0)
|
|
continue;
|
|
|
|
switch(anIDS)
|
|
{
|
|
case FS_Degenerated:
|
|
*theOS << "Degenerated case. Try to reduce tolerance.\n";
|
|
break;
|
|
case FS_FindVertexError:
|
|
*theOS << "Error while creating list of vertices.\n";
|
|
break;
|
|
case FS_FindEdgeError:
|
|
*theOS << "Error while creating list of edges.\n";
|
|
break;
|
|
case FS_Exception:
|
|
*theOS << "Exception during the operation.\n";
|
|
break;
|
|
case FS_FaceWithNullSurface:
|
|
*theOS << "Source face has null surface.\n";
|
|
break;
|
|
case FS_NotNaturalBoundsFace:
|
|
*theOS << "Source face has trimmed surface.\n";
|
|
break;
|
|
case FS_InfiniteSurface:
|
|
*theOS << "Source face has the surface with infinite boundaries.\n";
|
|
break;
|
|
case FS_EmptyInput:
|
|
*theOS << "Empty source data.\n";
|
|
break;
|
|
|
|
|
|
default:
|
|
return myStatusList;
|
|
}
|
|
}
|
|
|
|
return myStatusList;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Compute3DRange
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Real BRepBuilderAPI_FastSewing::Compute3DRange()
|
|
{
|
|
Bnd_Box aBox;
|
|
|
|
for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
|
|
{
|
|
FS_Face& aFace = myFaceVec.ChangeValue(i);
|
|
const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace.mySrcFace);
|
|
if(aSurf.IsNull())
|
|
continue;
|
|
Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
|
|
aSurf->Bounds(aUf, aUl, aVf, aVl);
|
|
|
|
aBox.Add(aSurf->Value(aUf, aVf));
|
|
aBox.Add(aSurf->Value(aUl, aVf));
|
|
aBox.Add(aSurf->Value(aUl, aVl));
|
|
aBox.Add(aSurf->Value(aUf, aVl));
|
|
}
|
|
|
|
Standard_Real aXm = 0.0, aYm = 0.0, aZm = 0.0, aXM = 0.0, aYM = 0.0, aZM = 0.0;
|
|
aBox.Get(aXm, aYm, aZm, aXM, aYM, aZM);
|
|
Standard_Real aDelta = aXM - aXm;
|
|
aDelta = Max(aDelta, aYM - aYm);
|
|
aDelta = Max(aDelta, aZM - aZm);
|
|
|
|
return aDelta;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : NodeInspector constructor
|
|
//purpose :
|
|
//=======================================================================
|
|
BRepBuilderAPI_FastSewing::NodeInspector::
|
|
NodeInspector(const NCollection_Vector<FS_Vertex>& theVec,
|
|
const gp_Pnt& thePnt,
|
|
const Standard_Real theTol)
|
|
: myVecOfVertexes(theVec),
|
|
myPoint(thePnt),
|
|
myResID(-1),
|
|
myIsFindingEnable(Standard_False)
|
|
{
|
|
mySQToler = theTol*theTol;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ::NodeInspector::Inspect
|
|
//purpose :
|
|
//=======================================================================
|
|
NCollection_CellFilter_Action BRepBuilderAPI_FastSewing::
|
|
NodeInspector::Inspect(const Target theID)
|
|
{
|
|
const gp_Pnt& aPt = myVecOfVertexes.Value(theID).myPnt;
|
|
const Standard_Real aSQDist = aPt.SquareDistance(myPoint);
|
|
if(aSQDist < mySQToler)
|
|
{
|
|
mySQToler = aSQDist;
|
|
myResID = theID;
|
|
}
|
|
|
|
return CellFilter_Keep;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ::FS_Edge::CreateTopologicalEdge
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepBuilderAPI_FastSewing::FS_Edge::
|
|
CreateTopologicalEdge(const NCollection_Vector<FS_Vertex>& theVertexVec,
|
|
const NCollection_Vector<FS_Face>& theFaceVec,
|
|
const Standard_Real theTol)
|
|
{
|
|
BRep_Builder aBuilder;
|
|
|
|
TopoDS_Vertex aV1 = theVertexVec(myVertices[0]).myTopoVert;
|
|
TopoDS_Vertex aV2 = theVertexVec(myVertices[1]).myTopoVert;
|
|
|
|
aV1.Orientation(TopAbs_FORWARD);
|
|
aV2.Orientation(TopAbs_REVERSED);
|
|
|
|
Handle(Geom_Curve) a3dCurv;
|
|
TopLoc_Location aLocation;
|
|
|
|
const FS_Face& aFace = theFaceVec.Value(myFaces.Value(myFaces.Lower()));
|
|
|
|
//3D-curves in 1st and 2nd faces are considered to be in same-range
|
|
const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace.mySrcFace, aLocation);
|
|
|
|
Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
|
|
aSurf->Bounds(aUf, aUl, aVf, aVl);
|
|
|
|
Standard_Integer anEdgeID = -1;
|
|
for(Standard_Integer anInd = 0; anInd < 4; anInd++)
|
|
{
|
|
if(myID == aFace.myEdges[anInd])
|
|
{
|
|
anEdgeID = anInd;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//For DEBUG mode only
|
|
Standard_ProgramError_Raise_if(anEdgeID < 0,
|
|
"BRepBuilderAPI_FastSewing::FS_Edge::CreateTopologicalEdge: Single edge.");
|
|
|
|
if(IsDegenerated())
|
|
{
|
|
Handle(Geom2d_Curve) a2dCurv = Get2DCurve(anEdgeID, aUf, aUl, aVf, aVl);
|
|
const Standard_Real aFPar = a2dCurv->FirstParameter(),
|
|
aLPar = a2dCurv->LastParameter();
|
|
|
|
aBuilder.MakeEdge(myTopoEdge);
|
|
aBuilder.UpdateEdge(myTopoEdge, a2dCurv, aSurf, aLocation, theTol);
|
|
aBuilder.Add(myTopoEdge, aV1);
|
|
aBuilder.Add(myTopoEdge, aV2);
|
|
aBuilder.Range(myTopoEdge, aFPar, aLPar);
|
|
aBuilder.Degenerated(myTopoEdge, Standard_True);
|
|
return;
|
|
}
|
|
|
|
switch(anEdgeID)
|
|
{
|
|
case 0:
|
|
a3dCurv = aSurf->VIso(aVf);
|
|
break;
|
|
case 1:
|
|
a3dCurv = aSurf->UIso(aUl);
|
|
break;
|
|
case 2:
|
|
a3dCurv = aSurf->VIso(aVl);
|
|
break;
|
|
case 3:
|
|
a3dCurv = aSurf->UIso(aUf);
|
|
break;
|
|
default:
|
|
throw Standard_OutOfRange("FS_Edge::CreateTopologicalEdge()");
|
|
break;
|
|
}
|
|
|
|
aBuilder.MakeEdge(myTopoEdge, a3dCurv, theTol);
|
|
aBuilder.Add(myTopoEdge, aV1);
|
|
aBuilder.Add(myTopoEdge, aV2);
|
|
aBuilder.Range(myTopoEdge, a3dCurv->FirstParameter(), a3dCurv->LastParameter());
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ::FS_Face::CreateTopologicalWire
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepBuilderAPI_FastSewing::FS_Face::
|
|
CreateTopologicalWire(const NCollection_Vector<FS_Edge>& theEdgeVec,
|
|
const Standard_Real theToler)
|
|
{
|
|
TopLoc_Location aLocation;
|
|
//3D-curves in 1st and 2nd faces are considered to be in same-range
|
|
const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(mySrcFace, aLocation);
|
|
Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
|
|
aSurf->Bounds(aUf, aUl, aVf, aVl);
|
|
|
|
BRep_Builder aB;
|
|
aB.MakeWire(myWire);
|
|
for(Standard_Integer anEdge = 0; anEdge < 4; anEdge++)
|
|
{
|
|
Standard_ProgramError_Raise_if(myEdges[anEdge] < 0,
|
|
"BRepBuilderAPI_FastSewing::FS_Face::CreateTopologicalWire: Wire is not closed.");
|
|
|
|
const BRepBuilderAPI_FastSewing::FS_Edge& aFSEdge = theEdgeVec.Value(myEdges[anEdge]);
|
|
TopAbs_Orientation anOri = anEdge < 2 ? TopAbs_FORWARD : TopAbs_REVERSED;
|
|
TopoDS_Edge anTopE = aFSEdge.myTopoEdge;
|
|
|
|
if(aFSEdge.IsDegenerated())
|
|
{
|
|
anTopE.Orientation(anOri);
|
|
aB.Add(myWire, anTopE);
|
|
continue;
|
|
}
|
|
|
|
//Check if 3D and 2D-curve have same-orientation.
|
|
//If it is not, 2d-curve will be reversed.
|
|
{
|
|
Standard_Real aFirstPar = 0.0, aLastPar = 0.0;
|
|
|
|
const Handle(Geom_Curve) a3dCurv = BRep_Tool::Curve(anTopE, aFirstPar, aLastPar);
|
|
Handle(Geom2d_Curve) a2dCurv = Get2DCurve(anEdge, aUf, aUl, aVf, aVl);
|
|
const gp_Pnt aPref(a3dCurv->Value(aFirstPar));
|
|
const gp_Pnt2d aP2df(a2dCurv->Value(aFirstPar)), aP2dl(a2dCurv->Value(aLastPar));
|
|
gp_Pnt aP3df(aSurf->Value(aP2df.X(), aP2df.Y()));
|
|
gp_Pnt aP3dl(aSurf->Value(aP2dl.X(), aP2dl.Y()));
|
|
aP3df.Transform(aLocation);
|
|
aP3dl.Transform(aLocation);
|
|
const Standard_Real aSqD1 = aP3df.SquareDistance(aPref);
|
|
const Standard_Real aSqD2 = aP3dl.SquareDistance(aPref);
|
|
|
|
if(aSqD2 < aSqD1)
|
|
{
|
|
a2dCurv = Get2DCurve(anEdge, aUf, aUl, aVf, aVl, Standard_True);
|
|
anOri = TopAbs::Reverse(anOri);
|
|
}
|
|
|
|
aB.UpdateEdge(anTopE, a2dCurv, aSurf, aLocation, theToler);
|
|
}
|
|
|
|
anTopE.Orientation(anOri);
|
|
|
|
aB.Add(myWire, anTopE);
|
|
}
|
|
|
|
myWire.Closed(Standard_True);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ::FS_Face::CreateTopologicalFace
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepBuilderAPI_FastSewing::FS_Face::CreateTopologicalFace()
|
|
{
|
|
Standard_ProgramError_Raise_if(myWire.IsNull(),
|
|
"BRepBuilderAPI_FastSewing::FS_Face::CreateTopologicalFace: Cannot create wire.");
|
|
|
|
BRep_Builder aBuilder;
|
|
myRetFace = TopoDS::Face(mySrcFace.EmptyCopied());
|
|
aBuilder.Add(myRetFace, myWire);
|
|
aBuilder.NaturalRestriction(myRetFace, Standard_True);
|
|
}
|