mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
0026118: Implement FastSewing algorithm
1. Develop special sewing algorithm. 2. DRAW-command "fastsewing" has been created (see help for detail information). 3. BRepLib::EnsureNormalConsistency() method has been added (see help for detail information). 4. DRAW-command correctnormals has been created (see help for detail information). Test cases for this issue. Correction of elapsed time in test-cases
This commit is contained in:
parent
97f3106c05
commit
7693827d4a
@ -258,6 +258,7 @@ is
|
|||||||
--
|
--
|
||||||
|
|
||||||
class Sewing;
|
class Sewing;
|
||||||
|
imported transient class FastSewing;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Construction of composite topologies
|
-- Construction of composite topologies
|
||||||
|
768
src/BRepBuilderAPI/BRepBuilderAPI_FastSewing.cxx
Normal file
768
src/BRepBuilderAPI/BRepBuilderAPI_FastSewing.cxx
Normal file
@ -0,0 +1,768 @@
|
|||||||
|
// 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_HANDLE(BRepBuilderAPI_FastSewing, Standard_Transient)
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
const 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))
|
||||||
|
Standard_OutOfRange::Raise("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)
|
||||||
|
{
|
||||||
|
SetStatus(FS_Exception);
|
||||||
|
#ifdef OCCT_DEBUG
|
||||||
|
//Standard_Failure::Caught()->Print(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)
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
Standard_OutOfRange::Raise("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);
|
||||||
|
}
|
306
src/BRepBuilderAPI/BRepBuilderAPI_FastSewing.hxx
Normal file
306
src/BRepBuilderAPI/BRepBuilderAPI_FastSewing.hxx
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
//! 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.
|
||||||
|
|
||||||
|
#ifndef _BRepBuilderAPI_FastSewing_HeaderFile
|
||||||
|
#define _BRepBuilderAPI_FastSewing_HeaderFile
|
||||||
|
|
||||||
|
#include <Standard_Transient.hxx>
|
||||||
|
#include <BRep_Builder.hxx>
|
||||||
|
|
||||||
|
#include <NCollection_List.hxx>
|
||||||
|
#include <NCollection_Sequence.hxx>
|
||||||
|
#include <NCollection_Vector.hxx>
|
||||||
|
#include <NCollection_CellFilter.hxx>
|
||||||
|
|
||||||
|
#include <TopoDS_Edge.hxx>
|
||||||
|
#include <TopoDS_Face.hxx>
|
||||||
|
#include <TopoDS_Vertex.hxx>
|
||||||
|
#include <TopoDS_Wire.hxx>
|
||||||
|
|
||||||
|
class Handle(NCollection_IncAllocator);
|
||||||
|
class Handle(Geom_Surface);
|
||||||
|
|
||||||
|
//! This class performs fast sewing of surfaces (faces). It supposes
|
||||||
|
//! that all surfaces are finite and are naturally restricted by their bounds.
|
||||||
|
//! Moreover, it supposes that stitched together surfaces have the same parameterization
|
||||||
|
//! along common boundaries, therefore it does not perform time-consuming check for
|
||||||
|
//! SameParameter property of edges.
|
||||||
|
//!
|
||||||
|
//! For sewing, use this function as following:
|
||||||
|
//! - set tolerance value (default tolerance is 1.E-06)
|
||||||
|
//! - add all necessary surfaces (faces)
|
||||||
|
//! - check status if adding is correctly completed.
|
||||||
|
//! - compute -> Perform
|
||||||
|
//! - retrieve the error status if any
|
||||||
|
//! - retrieve the resulted shape
|
||||||
|
class BRepBuilderAPI_FastSewing : public Standard_Transient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef unsigned int FS_VARStatuses;
|
||||||
|
|
||||||
|
//! Enumeration of result statuses
|
||||||
|
//ATTENTION!!! If you add new status, please
|
||||||
|
// describe it in GetStatuses() method
|
||||||
|
enum FS_Statuses
|
||||||
|
{
|
||||||
|
FS_OK = 0x00000000,
|
||||||
|
FS_Degenerated = 0x00000001,
|
||||||
|
FS_FindVertexError = 0x00000002,
|
||||||
|
FS_FindEdgeError = 0x00000004,
|
||||||
|
FS_FaceWithNullSurface = 0x00000008,
|
||||||
|
FS_NotNaturalBoundsFace = 0x00000010,
|
||||||
|
FS_InfiniteSurface = 0x00000020,
|
||||||
|
FS_EmptyInput = 0x00000040,
|
||||||
|
FS_Exception = 0x00000080
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//! Creates an object with tolerance of connexity
|
||||||
|
Standard_EXPORT BRepBuilderAPI_FastSewing(const Standard_Real theTolerance = 1.0e-06);
|
||||||
|
|
||||||
|
//! Adds faces of a shape
|
||||||
|
Standard_EXPORT Standard_Boolean Add(const TopoDS_Shape& theShape);
|
||||||
|
|
||||||
|
//! Adds a surface
|
||||||
|
Standard_EXPORT Standard_Boolean Add(const Handle(Geom_Surface)& theSurface);
|
||||||
|
|
||||||
|
//! Compute resulted shape
|
||||||
|
Standard_EXPORT void Perform (void) ;
|
||||||
|
|
||||||
|
//! Sets tolerance
|
||||||
|
void SetTolerance (const Standard_Real theToler)
|
||||||
|
{
|
||||||
|
myTolerance = theToler;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns tolerance
|
||||||
|
Standard_Real GetTolerance() const
|
||||||
|
{
|
||||||
|
return myTolerance;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns resulted shape
|
||||||
|
const TopoDS_Shape& GetResult() const
|
||||||
|
{
|
||||||
|
return myResShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns list of statuses. Print message if theOS != 0
|
||||||
|
Standard_EXPORT FS_VARStatuses GetStatuses(Standard_OStream* const theOS = 0);
|
||||||
|
|
||||||
|
DEFINE_STANDARD_RTTI(BRepBuilderAPI_FastSewing)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class NodeInspector;
|
||||||
|
|
||||||
|
Standard_EXPORT void FindVertexes(const Standard_Integer theSurfID,
|
||||||
|
NCollection_CellFilter<NodeInspector>& theCells);
|
||||||
|
Standard_EXPORT void FindEdges(const Standard_Integer theSurfID);
|
||||||
|
Standard_EXPORT void UpdateEdgeInfo(const Standard_Integer theIDPrevVertex,
|
||||||
|
const Standard_Integer theIDCurrVertex,
|
||||||
|
const Standard_Integer theFaceID,
|
||||||
|
const Standard_Integer theIDCurvOnFace);
|
||||||
|
Standard_EXPORT void CreateNewEdge( const Standard_Integer theIDPrevVertex,
|
||||||
|
const Standard_Integer theIDCurrVertex,
|
||||||
|
const Standard_Integer theFaceID,
|
||||||
|
const Standard_Integer theIDCurvOnFace);
|
||||||
|
|
||||||
|
Standard_EXPORT Standard_Real Compute3DRange();
|
||||||
|
|
||||||
|
//! Sets status. Returns numeric value of the status set
|
||||||
|
FS_VARStatuses SetStatus(FS_Statuses theStatus)
|
||||||
|
{
|
||||||
|
const FS_VARStatuses aStatusID = (FS_VARStatuses)(theStatus);
|
||||||
|
myStatusList |= aStatusID;
|
||||||
|
return aStatusID;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FS_Edge;
|
||||||
|
|
||||||
|
// Classes FS_Vertex, FS_Face and FS_Edge keep information about
|
||||||
|
// relations between resulted members (e.g. which faces share this vertex? etc.)
|
||||||
|
|
||||||
|
//! The struct corresponding to a vertex
|
||||||
|
struct FS_Vertex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FS_Vertex(): myID(-1){};
|
||||||
|
|
||||||
|
//! Creates topological member (vertex)
|
||||||
|
void CreateTopologicalVertex(const Standard_Real theToler)
|
||||||
|
{
|
||||||
|
BRep_Builder aBuilder;
|
||||||
|
aBuilder.MakeVertex(myTopoVert, myPnt, theToler);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Geometry point of this Vertex
|
||||||
|
gp_Pnt myPnt;
|
||||||
|
TopoDS_Vertex myTopoVert;
|
||||||
|
|
||||||
|
//! List of faces and edges which share this vertex
|
||||||
|
NCollection_List<Standard_Integer> myFaces;
|
||||||
|
NCollection_List<Standard_Integer> myEdges;
|
||||||
|
|
||||||
|
//! Indentifies the place of this Vertex in
|
||||||
|
//! BRepBuilderAPI_FastSewing::myVertexVec list
|
||||||
|
Standard_Integer myID;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! The struct corresponding to an face
|
||||||
|
struct FS_Face
|
||||||
|
{
|
||||||
|
FS_Face(): myID(-1)
|
||||||
|
{
|
||||||
|
for (Standard_Integer i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
myVertices[i] = -1;
|
||||||
|
myEdges[i] = -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//! Creates topological members (wire and face)
|
||||||
|
void CreateTopologicalWire(const NCollection_Vector<FS_Edge>& theEdgeVec,
|
||||||
|
const Standard_Real theToler);
|
||||||
|
void CreateTopologicalFace();
|
||||||
|
|
||||||
|
//! Sets vertex
|
||||||
|
void SetVertex(const Standard_Integer thePlaceID, const Standard_Integer theVertID)
|
||||||
|
{
|
||||||
|
Standard_RangeError_Raise_if((thePlaceID < 0) || (thePlaceID > 3),
|
||||||
|
"FS_Face::SetVertex(): OUT of Range");
|
||||||
|
|
||||||
|
myVertices[thePlaceID] = theVertID;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Sets edge
|
||||||
|
void SetEdge(const Standard_Integer thePlaceID, const Standard_Integer theEdgeID)
|
||||||
|
{
|
||||||
|
Standard_RangeError_Raise_if((thePlaceID < 0) || (thePlaceID > 3),
|
||||||
|
"FS_Face::SetEdge(): OUT of Range");
|
||||||
|
|
||||||
|
myEdges[thePlaceID] = theEdgeID;
|
||||||
|
}
|
||||||
|
|
||||||
|
TopoDS_Face mySrcFace;
|
||||||
|
TopoDS_Wire myWire;
|
||||||
|
TopoDS_Face myRetFace;
|
||||||
|
|
||||||
|
//! myEdges[i] number of the edge in myEdgeVec
|
||||||
|
//! (i==0) <-> (V=Vf); (i==1) <-> (U=Ul);
|
||||||
|
//! (i==2) <-> (V=Vl); (i==3) <-> (U=Uf)
|
||||||
|
Standard_Integer myEdges[4];
|
||||||
|
//! myVertices[i] is Start point of myEdges[i]
|
||||||
|
Standard_Integer myVertices[4];
|
||||||
|
|
||||||
|
//! Indentifies the place of this Face in
|
||||||
|
//! BRepBuilderAPI_FastSewing::myFaceVec list
|
||||||
|
Standard_Integer myID;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! The struct corresponding to a edge
|
||||||
|
class FS_Edge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FS_Edge(): myID(-1)
|
||||||
|
{
|
||||||
|
myVertices[0] = -1;
|
||||||
|
myVertices[1] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FS_Edge(const Standard_Integer theIDVert1, const Standard_Integer theIDVert2): myID(-1)
|
||||||
|
{
|
||||||
|
myVertices[0] = theIDVert1;
|
||||||
|
myVertices[1] = theIDVert2;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Creates topological member (TopoDS_Edge)
|
||||||
|
void CreateTopologicalEdge( const NCollection_Vector<FS_Vertex>& theVertexVec,
|
||||||
|
const NCollection_Vector<FS_Face>& theFaceVec,
|
||||||
|
const Standard_Real theTol);
|
||||||
|
|
||||||
|
//! Sets vertex
|
||||||
|
void SetVertex(const Standard_Integer thePlaceID, const Standard_Integer theVertID)
|
||||||
|
{
|
||||||
|
Standard_RangeError_Raise_if((thePlaceID < 0) || (thePlaceID > 1),
|
||||||
|
"FS_Face::SetVertex(): OUT of Range");
|
||||||
|
|
||||||
|
myVertices[thePlaceID] = theVertID;
|
||||||
|
}
|
||||||
|
|
||||||
|
Standard_Boolean IsDegenerated() const
|
||||||
|
{
|
||||||
|
return (myVertices[0] == myVertices[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! List of faces which are shared with this edge
|
||||||
|
//! Value is the index of this shape in myFaceVec array
|
||||||
|
NCollection_Sequence<Standard_Integer> myFaces;
|
||||||
|
|
||||||
|
//! Indentifies the place of this Edge in
|
||||||
|
//! BRepBuilderAPI_FastSewing::myEdgeVec list
|
||||||
|
Standard_Integer myID;
|
||||||
|
|
||||||
|
TopoDS_Edge myTopoEdge;
|
||||||
|
private:
|
||||||
|
//! Index of the vertex in myVertexVec array
|
||||||
|
Standard_Integer myVertices[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
//! This inspector will find a node nearest to the given point
|
||||||
|
//! not far than on the given tolerance
|
||||||
|
class NodeInspector: public NCollection_CellFilter_InspectorXYZ
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Standard_Integer Target;
|
||||||
|
|
||||||
|
NodeInspector(const NCollection_Vector<FS_Vertex>& theVec,
|
||||||
|
const gp_Pnt& thePnt, const Standard_Real theTol);
|
||||||
|
|
||||||
|
Standard_EXPORT NCollection_CellFilter_Action Inspect (const Target theId);
|
||||||
|
|
||||||
|
Target GetResult()
|
||||||
|
{
|
||||||
|
return myResID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
NodeInspector& operator = (const NodeInspector&);
|
||||||
|
const NCollection_Vector<FS_Vertex>& myVecOfVertexes;
|
||||||
|
gp_Pnt myPoint;
|
||||||
|
Standard_Real mySQToler;
|
||||||
|
Target myResID;
|
||||||
|
Standard_Boolean myIsFindingEnable;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
TopoDS_Shape myResShape;
|
||||||
|
|
||||||
|
// myFaceVec, myVertexVec and myEdgeVec lists are filled only once!!!!!
|
||||||
|
|
||||||
|
//! Vector of faces
|
||||||
|
NCollection_Vector<FS_Face> myFaceVec;
|
||||||
|
//! Vector of Vertices
|
||||||
|
NCollection_Vector<FS_Vertex> myVertexVec;
|
||||||
|
//! Vector of edges
|
||||||
|
NCollection_Vector<FS_Edge> myEdgeVec;
|
||||||
|
|
||||||
|
//! Tolerance
|
||||||
|
Standard_Real myTolerance;
|
||||||
|
|
||||||
|
//! Bits of computation status
|
||||||
|
FS_VARStatuses myStatusList;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _BRepBuilderAPI_FastSewing_HeaderFile
|
||||||
|
|
||||||
|
DEFINE_STANDARD_HANDLE(BRepBuilderAPI_FastSewing, Standard_Transient)
|
@ -1,4 +1,5 @@
|
|||||||
BRepBuilderAPI_VertexInspector.hxx
|
BRepBuilderAPI_VertexInspector.hxx
|
||||||
BRepBuilderAPI_CellFilter.hxx
|
BRepBuilderAPI_CellFilter.hxx
|
||||||
BRepBuilderAPI_BndBoxTreeSelector.hxx
|
BRepBuilderAPI_BndBoxTreeSelector.hxx
|
||||||
|
BRepBuilderAPI_FastSewing.hxx
|
||||||
|
BRepBuilderAPI_FastSewing.cxx
|
||||||
|
@ -311,5 +311,14 @@ is
|
|||||||
---Purpose: Sorts in LF the Faces of S on the reverse
|
---Purpose: Sorts in LF the Faces of S on the reverse
|
||||||
-- complexity of their surfaces
|
-- complexity of their surfaces
|
||||||
-- (other,Torus,Sphere,Cone,Cylinder,Plane)
|
-- (other,Torus,Sphere,Cone,Cylinder,Plane)
|
||||||
|
|
||||||
|
EnsureNormalConsistency (S : Shape from TopoDS;
|
||||||
|
theAngTol: Real from Standard = 0.001;
|
||||||
|
ForceComputeNormals: Boolean from Standard = Standard_False)
|
||||||
|
returns Boolean;
|
||||||
|
---Purpose: Corrects the normals in Poly_Triangulation of faces,
|
||||||
|
-- in such way that normals at nodes lying along smooth
|
||||||
|
-- edges have the same value on both adjacent triangulations.
|
||||||
|
-- Returns TRUE if any correction is done.
|
||||||
|
|
||||||
end BRepLib;
|
end BRepLib;
|
||||||
|
@ -82,6 +82,10 @@
|
|||||||
#include <Approx_CurvilinearParameter.hxx>
|
#include <Approx_CurvilinearParameter.hxx>
|
||||||
#include <Geom_BSplineSurface.hxx>
|
#include <Geom_BSplineSurface.hxx>
|
||||||
|
|
||||||
|
#include <Poly_Triangulation.hxx>
|
||||||
|
#include <TShort_HArray1OfShortReal.hxx>
|
||||||
|
#include <GeomLProp_SLProps.hxx>
|
||||||
|
#include <Poly_PolygonOnTriangulation.hxx>
|
||||||
|
|
||||||
// TODO - not thread-safe static variables
|
// TODO - not thread-safe static variables
|
||||||
static Standard_Real thePrecision = Precision::Confusion();
|
static Standard_Real thePrecision = Precision::Confusion();
|
||||||
@ -1657,6 +1661,146 @@ void BRepLib::EncodeRegularity(TopoDS_Edge& E,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
// function : EnsureNormalConsistency
|
||||||
|
// purpose : Corrects the normals in Poly_Triangulation of faces.
|
||||||
|
// Returns TRUE if any correction is done.
|
||||||
|
//=======================================================================
|
||||||
|
Standard_Boolean BRepLib::
|
||||||
|
EnsureNormalConsistency(const TopoDS_Shape& theShape,
|
||||||
|
const Standard_Real theAngTol,
|
||||||
|
const Standard_Boolean theForceComputeNormals)
|
||||||
|
{
|
||||||
|
const Standard_Real aThresDot = cos(theAngTol);
|
||||||
|
|
||||||
|
Standard_Boolean aRetVal = Standard_False, isNormalsFound = Standard_False;
|
||||||
|
|
||||||
|
// compute normals if they are absent
|
||||||
|
TopExp_Explorer anExpFace(theShape,TopAbs_FACE);
|
||||||
|
for (; anExpFace.More(); anExpFace.Next())
|
||||||
|
{
|
||||||
|
const TopoDS_Face& aFace = TopoDS::Face(anExpFace.Current());
|
||||||
|
const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
|
||||||
|
if(aSurf.IsNull())
|
||||||
|
continue;
|
||||||
|
TopLoc_Location aLoc;
|
||||||
|
const Handle(Poly_Triangulation)& aPT = BRep_Tool::Triangulation(aFace, aLoc);
|
||||||
|
if(aPT.IsNull())
|
||||||
|
continue;
|
||||||
|
if (!theForceComputeNormals && aPT->HasNormals())
|
||||||
|
{
|
||||||
|
isNormalsFound = Standard_True;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GeomLProp_SLProps aSLP(aSurf, 2, Precision::Confusion());
|
||||||
|
const Standard_Integer anArrDim = 3*aPT->NbNodes();
|
||||||
|
Handle(TShort_HArray1OfShortReal) aNormArr = new TShort_HArray1OfShortReal(1, anArrDim);
|
||||||
|
Standard_Integer anNormInd = aNormArr->Lower();
|
||||||
|
for(Standard_Integer i = aPT->UVNodes().Lower(); i <= aPT->UVNodes().Upper(); i++)
|
||||||
|
{
|
||||||
|
const gp_Pnt2d &aP2d = aPT->UVNodes().Value(i);
|
||||||
|
aSLP.SetParameters(aP2d.X(), aP2d.Y());
|
||||||
|
|
||||||
|
gp_XYZ aNorm(0.,0.,0.);
|
||||||
|
if(!aSLP.IsNormalDefined())
|
||||||
|
{
|
||||||
|
#ifdef OCCT_DEBUG
|
||||||
|
cout << "BRepLib::EnsureNormalConsistency(): Cannot find normal!" << endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aNorm = aSLP.Normal().XYZ();
|
||||||
|
if (aFace.Orientation() == TopAbs_REVERSED)
|
||||||
|
aNorm.Reverse();
|
||||||
|
}
|
||||||
|
aNormArr->ChangeValue(anNormInd++) = static_cast<Standard_ShortReal>(aNorm.X());
|
||||||
|
aNormArr->ChangeValue(anNormInd++) = static_cast<Standard_ShortReal>(aNorm.Y());
|
||||||
|
aNormArr->ChangeValue(anNormInd++) = static_cast<Standard_ShortReal>(aNorm.Z());
|
||||||
|
}
|
||||||
|
|
||||||
|
aRetVal = Standard_True;
|
||||||
|
isNormalsFound = Standard_True;
|
||||||
|
aPT->SetNormals(aNormArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isNormalsFound)
|
||||||
|
{
|
||||||
|
return aRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop by edges
|
||||||
|
TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
|
||||||
|
TopExp::MapShapesAndAncestors(theShape,TopAbs_EDGE,TopAbs_FACE,aMapEF);
|
||||||
|
for(Standard_Integer anInd = 1; anInd <= aMapEF.Extent(); anInd++)
|
||||||
|
{
|
||||||
|
const TopoDS_Edge& anEdg = TopoDS::Edge(aMapEF.FindKey(anInd));
|
||||||
|
const TopTools_ListOfShape& anEdgList = aMapEF.FindFromIndex(anInd);
|
||||||
|
if (anEdgList.Extent() != 2)
|
||||||
|
continue;
|
||||||
|
TopTools_ListIteratorOfListOfShape anItF(anEdgList);
|
||||||
|
const TopoDS_Face aFace1 = TopoDS::Face(anItF.Value());
|
||||||
|
anItF.Next();
|
||||||
|
const TopoDS_Face aFace2 = TopoDS::Face(anItF.Value());
|
||||||
|
TopLoc_Location aLoc1, aLoc2;
|
||||||
|
const Handle(Poly_Triangulation)& aPT1 = BRep_Tool::Triangulation(aFace1, aLoc1);
|
||||||
|
const Handle(Poly_Triangulation)& aPT2 = BRep_Tool::Triangulation(aFace2, aLoc2);
|
||||||
|
|
||||||
|
if(aPT1.IsNull() || aPT2.IsNull())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!aPT1->HasNormals() || !aPT2->HasNormals())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const Handle(Poly_PolygonOnTriangulation)& aPTEF1 =
|
||||||
|
BRep_Tool::PolygonOnTriangulation(anEdg, aPT1, aLoc1);
|
||||||
|
const Handle(Poly_PolygonOnTriangulation)& aPTEF2 =
|
||||||
|
BRep_Tool::PolygonOnTriangulation(anEdg, aPT2, aLoc2);
|
||||||
|
|
||||||
|
TShort_Array1OfShortReal& aNormArr1 = aPT1->ChangeNormals();
|
||||||
|
TShort_Array1OfShortReal& aNormArr2 = aPT2->ChangeNormals();
|
||||||
|
|
||||||
|
for(Standard_Integer anEdgNode = aPTEF1->Nodes().Lower();
|
||||||
|
anEdgNode <= aPTEF1->Nodes().Upper(); anEdgNode++)
|
||||||
|
{
|
||||||
|
//Number of node
|
||||||
|
const Standard_Integer aFNodF1 = aPTEF1->Nodes().Value(anEdgNode);
|
||||||
|
const Standard_Integer aFNodF2 = aPTEF2->Nodes().Value(anEdgNode);
|
||||||
|
|
||||||
|
const Standard_Integer aFNorm1FirstIndex = aNormArr1.Lower() + 3*
|
||||||
|
(aFNodF1 - aPT1->Nodes().Lower());
|
||||||
|
const Standard_Integer aFNorm2FirstIndex = aNormArr2.Lower() + 3*
|
||||||
|
(aFNodF2 - aPT2->Nodes().Lower());
|
||||||
|
|
||||||
|
gp_XYZ aNorm1(aNormArr1.Value(aFNorm1FirstIndex),
|
||||||
|
aNormArr1.Value(aFNorm1FirstIndex+1),
|
||||||
|
aNormArr1.Value(aFNorm1FirstIndex+2));
|
||||||
|
gp_XYZ aNorm2(aNormArr2.Value(aFNorm2FirstIndex),
|
||||||
|
aNormArr2.Value(aFNorm2FirstIndex+1),
|
||||||
|
aNormArr2.Value(aFNorm2FirstIndex+2));
|
||||||
|
const Standard_Real aDot = aNorm1 * aNorm2;
|
||||||
|
|
||||||
|
if(aDot > aThresDot)
|
||||||
|
{
|
||||||
|
gp_XYZ aNewNorm = (aNorm1 + aNorm2).Normalized();
|
||||||
|
aNormArr1.ChangeValue(aFNorm1FirstIndex) =
|
||||||
|
aNormArr2.ChangeValue(aFNorm2FirstIndex) =
|
||||||
|
static_cast<Standard_ShortReal>(aNewNorm.X());
|
||||||
|
aNormArr1.ChangeValue(aFNorm1FirstIndex+1) =
|
||||||
|
aNormArr2.ChangeValue(aFNorm2FirstIndex+1) =
|
||||||
|
static_cast<Standard_ShortReal>(aNewNorm.Y());
|
||||||
|
aNormArr1.ChangeValue(aFNorm1FirstIndex+2) =
|
||||||
|
aNormArr2.ChangeValue(aFNorm2FirstIndex+2) =
|
||||||
|
static_cast<Standard_ShortReal>(aNewNorm.Z());
|
||||||
|
aRetVal = Standard_True;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
//function : SortFaces
|
//function : SortFaces
|
||||||
//purpose :
|
//purpose :
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
#include <TopTools_SequenceOfShape.hxx>
|
#include <TopTools_SequenceOfShape.hxx>
|
||||||
#include <Precision.hxx>
|
#include <Precision.hxx>
|
||||||
#include <Draw_ProgressIndicator.hxx>
|
#include <Draw_ProgressIndicator.hxx>
|
||||||
|
#include <NCollection_Vector.hxx>
|
||||||
|
#include <BRepBuilderAPI_FastSewing.hxx>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
//#define strcasecmp strcmp Already defined
|
//#define strcasecmp strcmp Already defined
|
||||||
@ -404,6 +406,66 @@ static Standard_Integer sewing (Draw_Interpretor& theDi,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : fastsewing
|
||||||
|
//purpose :
|
||||||
|
//=======================================================================
|
||||||
|
Standard_Integer fastsewing (Draw_Interpretor& theDI,
|
||||||
|
Standard_Integer theNArg,
|
||||||
|
const char** theArgVal)
|
||||||
|
{
|
||||||
|
if(theNArg < 3)
|
||||||
|
{
|
||||||
|
// 0 1 2 3 4
|
||||||
|
theDI << "Use: fastsewing result [-tol <value>] <list_of_faces>\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BRepBuilderAPI_FastSewing aFS;
|
||||||
|
|
||||||
|
Standard_Integer aStartIndex = 2;
|
||||||
|
|
||||||
|
if(!strcmp(theArgVal[aStartIndex], "-tol"))
|
||||||
|
{
|
||||||
|
aFS.SetTolerance(Draw::Atof (theArgVal[aStartIndex+1]));
|
||||||
|
aStartIndex = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Standard_Integer i = aStartIndex; i < theNArg; i++)
|
||||||
|
{
|
||||||
|
TopoDS_Shape aS = DBRep::Get(theArgVal[i]);
|
||||||
|
|
||||||
|
if(!aFS.Add(aS))
|
||||||
|
{
|
||||||
|
theDI << "Face is not added. See statuses.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BRepBuilderAPI_FastSewing::FS_VARStatuses aStatus = aFS.GetStatuses();
|
||||||
|
|
||||||
|
if(aStatus)
|
||||||
|
{
|
||||||
|
theDI << "Error: There are some problems while adding (" <<
|
||||||
|
(static_cast<Standard_Integer>(aStatus)) << ")\n";
|
||||||
|
aFS.GetStatuses(&cout);
|
||||||
|
}
|
||||||
|
|
||||||
|
aFS.Perform();
|
||||||
|
|
||||||
|
aStatus = aFS.GetStatuses();
|
||||||
|
|
||||||
|
if(aStatus)
|
||||||
|
{
|
||||||
|
theDI << "Error: There are some problems while performing (" <<
|
||||||
|
(static_cast<Standard_Integer>(aStatus)) << ")\n";
|
||||||
|
aFS.GetStatuses(&cout);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBRep::Set(theArgVal[1], aFS.GetResult());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
// continuity
|
// continuity
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
@ -508,5 +570,8 @@ void BRepTest::SurfaceCommands(Draw_Interpretor& theCommands)
|
|||||||
theCommands.Add("encoderegularity",
|
theCommands.Add("encoderegularity",
|
||||||
"encoderegularity shape [tolerance (in degree)]",
|
"encoderegularity shape [tolerance (in degree)]",
|
||||||
__FILE__,encoderegularity, g);
|
__FILE__,encoderegularity, g);
|
||||||
|
|
||||||
|
theCommands.Add ("fastsewing", "fastsewing result [-tol <value>] <list_of_faces>",
|
||||||
|
__FILE__, fastsewing, g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@
|
|||||||
#include <BRepAdaptor_Surface.hxx>
|
#include <BRepAdaptor_Surface.hxx>
|
||||||
#include <Bnd_Box.hxx>
|
#include <Bnd_Box.hxx>
|
||||||
#include <BRepBndLib.hxx>
|
#include <BRepBndLib.hxx>
|
||||||
|
#include <BRepLib.hxx>
|
||||||
|
|
||||||
|
|
||||||
//epa Memory leaks test
|
//epa Memory leaks test
|
||||||
@ -1589,6 +1590,31 @@ Standard_Integer triedgepoints(Draw_Interpretor& di, Standard_Integer nbarg, con
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : correctnormals
|
||||||
|
//purpose : Corrects normals in shape triangulation nodes (...)
|
||||||
|
//=======================================================================
|
||||||
|
Standard_Integer correctnormals (Draw_Interpretor& theDI,
|
||||||
|
Standard_Integer /*theNArg*/,
|
||||||
|
const char** theArgVal)
|
||||||
|
{
|
||||||
|
TopoDS_Shape S = DBRep::Get(theArgVal[1]);
|
||||||
|
|
||||||
|
//Use "correctnormals shape"
|
||||||
|
|
||||||
|
|
||||||
|
if(!BRepLib::EnsureNormalConsistency(S))
|
||||||
|
{
|
||||||
|
theDI << "Normals have not been changed!\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
theDI << "Some corrections in source shape have been made!\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
void MeshTest::Commands(Draw_Interpretor& theCommands)
|
void MeshTest::Commands(Draw_Interpretor& theCommands)
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
@ -1623,6 +1649,8 @@ void MeshTest::Commands(Draw_Interpretor& theCommands)
|
|||||||
theCommands.Add("onetriangulation","onetriangulation name",__FILE__, onetriangulation, g);
|
theCommands.Add("onetriangulation","onetriangulation name",__FILE__, onetriangulation, g);
|
||||||
theCommands.Add("triepoints", "triepoints shape1 [shape2 ...]",__FILE__, triedgepoints, g);
|
theCommands.Add("triepoints", "triepoints shape1 [shape2 ...]",__FILE__, triedgepoints, g);
|
||||||
|
|
||||||
|
theCommands.Add("correctnormals", "correctnormals shape",__FILE__, correctnormals, g);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
theCommands.Add("extrema","extrema ",__FILE__, extrema, g);
|
theCommands.Add("extrema","extrema ",__FILE__, extrema, g);
|
||||||
theCommands.Add("vb","vb ",__FILE__, vb, g);
|
theCommands.Add("vb","vb ",__FILE__, vb, g);
|
||||||
|
49
tests/sewing/fast/A1
Normal file
49
tests/sewing/fast/A1
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
if { [regexp {Debug mode} [dversion]] } {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 9
|
||||||
|
} else {
|
||||||
|
set max_time 9
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 3
|
||||||
|
} else {
|
||||||
|
set max_time 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restore [locate_data_file 5000-12.brep] a
|
||||||
|
|
||||||
|
dchrono ch reset
|
||||||
|
dchrono ch start
|
||||||
|
puts [fastsewing result -tol 2.0e-5 a]
|
||||||
|
dchrono ch stop
|
||||||
|
|
||||||
|
set q [dchrono ch show]
|
||||||
|
|
||||||
|
regexp {CPU user time: ([-0-9.+eE]+) seconds} $q full z
|
||||||
|
puts "$z"
|
||||||
|
|
||||||
|
if { $z > ${max_time} } {
|
||||||
|
puts "Elapsed time is more than ${max_time} seconds - Error"
|
||||||
|
} else {
|
||||||
|
puts "Elapsed time is less than ${max_time} seconds - OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
donly result
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
set nbshapes_expected "
|
||||||
|
Number of shapes in shape
|
||||||
|
VERTEX : 5556
|
||||||
|
EDGE : 11118
|
||||||
|
WIRE : 5552
|
||||||
|
FACE : 5552
|
||||||
|
SHELL : 1
|
||||||
|
SOLID : 0
|
||||||
|
COMPSOLID : 0
|
||||||
|
COMPOUND : 1
|
||||||
|
SHAPE : 27780
|
||||||
|
"
|
||||||
|
|
||||||
|
checknbshapes result -ref "${nbshapes_expected}" -t -m "Partition of 2 shapes"
|
49
tests/sewing/fast/A2
Normal file
49
tests/sewing/fast/A2
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
if { [regexp {Debug mode} [dversion]] } {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 9
|
||||||
|
} else {
|
||||||
|
set max_time 9
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 3
|
||||||
|
} else {
|
||||||
|
set max_time 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restore [locate_data_file 5000-16.brep] a
|
||||||
|
|
||||||
|
dchrono ch reset
|
||||||
|
dchrono ch start
|
||||||
|
puts [fastsewing result -tol 2.0e-5 a]
|
||||||
|
dchrono ch stop
|
||||||
|
|
||||||
|
set q [dchrono ch show]
|
||||||
|
|
||||||
|
regexp {CPU user time: ([-0-9.+eE]+) seconds} $q full z
|
||||||
|
puts "$z"
|
||||||
|
|
||||||
|
if { $z > ${max_time} } {
|
||||||
|
puts "Elapsed time is more than ${max_time} seconds - Error"
|
||||||
|
} else {
|
||||||
|
puts "Elapsed time is less than ${max_time} seconds - OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
donly result
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
set nbshapes_expected "
|
||||||
|
Number of shapes in shape
|
||||||
|
VERTEX : 5527
|
||||||
|
EDGE : 11056
|
||||||
|
WIRE : 5520
|
||||||
|
FACE : 5520
|
||||||
|
SHELL : 1
|
||||||
|
SOLID : 0
|
||||||
|
COMPSOLID : 0
|
||||||
|
COMPOUND : 1
|
||||||
|
SHAPE : 27625
|
||||||
|
"
|
||||||
|
|
||||||
|
checknbshapes result -ref "${nbshapes_expected}" -t -m "Partition of 2 shapes"
|
49
tests/sewing/fast/A3
Normal file
49
tests/sewing/fast/A3
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
if { [regexp {Debug mode} [dversion]] } {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 9
|
||||||
|
} else {
|
||||||
|
set max_time 9
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 3
|
||||||
|
} else {
|
||||||
|
set max_time 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restore [locate_data_file Cover_VXmodel.brep] a
|
||||||
|
|
||||||
|
dchrono ch reset
|
||||||
|
dchrono ch start
|
||||||
|
puts [fastsewing result -tol 1.5e-4 a]
|
||||||
|
dchrono ch stop
|
||||||
|
|
||||||
|
set q [dchrono ch show]
|
||||||
|
|
||||||
|
regexp {CPU user time: ([-0-9.+eE]+) seconds} $q full z
|
||||||
|
puts "$z"
|
||||||
|
|
||||||
|
if { $z > ${max_time} } {
|
||||||
|
puts "Elapsed time is more than ${max_time} seconds - Error"
|
||||||
|
} else {
|
||||||
|
puts "Elapsed time is less than ${max_time} seconds - OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
donly result
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
set nbshapes_expected "
|
||||||
|
Number of shapes in shape
|
||||||
|
VERTEX : 844
|
||||||
|
EDGE : 1592
|
||||||
|
WIRE : 749
|
||||||
|
FACE : 749
|
||||||
|
SHELL : 1
|
||||||
|
SOLID : 0
|
||||||
|
COMPSOLID : 0
|
||||||
|
COMPOUND : 1
|
||||||
|
SHAPE : 3936
|
||||||
|
"
|
||||||
|
|
||||||
|
checknbshapes result -ref "${nbshapes_expected}" -t -m "Partition of 2 shapes"
|
49
tests/sewing/fast/A4
Normal file
49
tests/sewing/fast/A4
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
if { [regexp {Debug mode} [dversion]] } {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 9
|
||||||
|
} else {
|
||||||
|
set max_time 9
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 3
|
||||||
|
} else {
|
||||||
|
set max_time 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restore [locate_data_file Mustang_250.brep] a
|
||||||
|
|
||||||
|
dchrono ch reset
|
||||||
|
dchrono ch start
|
||||||
|
puts [fastsewing result -tol 2.5e-4 a]
|
||||||
|
dchrono ch stop
|
||||||
|
|
||||||
|
set q [dchrono ch show]
|
||||||
|
|
||||||
|
regexp {CPU user time: ([-0-9.+eE]+) seconds} $q full z
|
||||||
|
puts "$z"
|
||||||
|
|
||||||
|
if { $z > ${max_time} } {
|
||||||
|
puts "Elapsed time is more than ${max_time} seconds - Error"
|
||||||
|
} else {
|
||||||
|
puts "Elapsed time is less than ${max_time} seconds - OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
donly result
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
set nbshapes_expected "
|
||||||
|
Number of shapes in shape
|
||||||
|
VERTEX : 250
|
||||||
|
EDGE : 496
|
||||||
|
WIRE : 248
|
||||||
|
FACE : 248
|
||||||
|
SHELL : 1
|
||||||
|
SOLID : 0
|
||||||
|
COMPSOLID : 0
|
||||||
|
COMPOUND : 1
|
||||||
|
SHAPE : 1244
|
||||||
|
"
|
||||||
|
|
||||||
|
checknbshapes result -ref "${nbshapes_expected}" -t -m "Partition of 2 shapes"
|
49
tests/sewing/fast/A5
Normal file
49
tests/sewing/fast/A5
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
if { [regexp {Debug mode} [dversion]] } {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 9
|
||||||
|
} else {
|
||||||
|
set max_time 9
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 3
|
||||||
|
} else {
|
||||||
|
set max_time 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restore [locate_data_file Mustang_500.brep] a
|
||||||
|
|
||||||
|
dchrono ch reset
|
||||||
|
dchrono ch start
|
||||||
|
puts [fastsewing result -tol 7.0e-5 a]
|
||||||
|
dchrono ch stop
|
||||||
|
|
||||||
|
set q [dchrono ch show]
|
||||||
|
|
||||||
|
regexp {CPU user time: ([-0-9.+eE]+) seconds} $q full z
|
||||||
|
puts "$z"
|
||||||
|
|
||||||
|
if { $z > ${max_time} } {
|
||||||
|
puts "Elapsed time is more than ${max_time} seconds - Error"
|
||||||
|
} else {
|
||||||
|
puts "Elapsed time is less than ${max_time} seconds - OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
donly result
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
set nbshapes_expected "
|
||||||
|
Number of shapes in shape
|
||||||
|
VERTEX : 514
|
||||||
|
EDGE : 1024
|
||||||
|
WIRE : 512
|
||||||
|
FACE : 512
|
||||||
|
SHELL : 1
|
||||||
|
SOLID : 0
|
||||||
|
COMPSOLID : 0
|
||||||
|
COMPOUND : 1
|
||||||
|
SHAPE : 2564
|
||||||
|
"
|
||||||
|
|
||||||
|
checknbshapes result -ref "${nbshapes_expected}" -t -m "Partition of 2 shapes"
|
49
tests/sewing/fast/A6
Normal file
49
tests/sewing/fast/A6
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
if { [regexp {Debug mode} [dversion]] } {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 9
|
||||||
|
} else {
|
||||||
|
set max_time 9
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 3
|
||||||
|
} else {
|
||||||
|
set max_time 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restore [locate_data_file Pipe_Full.brep] a
|
||||||
|
|
||||||
|
dchrono ch reset
|
||||||
|
dchrono ch start
|
||||||
|
puts [fastsewing result -tol 5.0e-4 a]
|
||||||
|
dchrono ch stop
|
||||||
|
|
||||||
|
set q [dchrono ch show]
|
||||||
|
|
||||||
|
regexp {CPU user time: ([-0-9.+eE]+) seconds} $q full z
|
||||||
|
puts "$z"
|
||||||
|
|
||||||
|
if { $z > ${max_time} } {
|
||||||
|
puts "Elapsed time is more than ${max_time} seconds - Error"
|
||||||
|
} else {
|
||||||
|
puts "Elapsed time is less than ${max_time} seconds - OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
donly result
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
set nbshapes_expected "
|
||||||
|
Number of shapes in shape
|
||||||
|
VERTEX : 5327
|
||||||
|
EDGE : 10656
|
||||||
|
WIRE : 5326
|
||||||
|
FACE : 5326
|
||||||
|
SHELL : 1
|
||||||
|
SOLID : 0
|
||||||
|
COMPSOLID : 0
|
||||||
|
COMPOUND : 1
|
||||||
|
SHAPE : 26637
|
||||||
|
"
|
||||||
|
|
||||||
|
checknbshapes result -ref "${nbshapes_expected}" -t -m "Partition of 2 shapes"
|
49
tests/sewing/fast/A7
Normal file
49
tests/sewing/fast/A7
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
if { [regexp {Debug mode} [dversion]] } {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 9
|
||||||
|
} else {
|
||||||
|
set max_time 9
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if { [regexp {Windows} [dversion]] } {
|
||||||
|
set max_time 3
|
||||||
|
} else {
|
||||||
|
set max_time 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restore [locate_data_file Pipe_Partial.brep] a
|
||||||
|
|
||||||
|
dchrono ch reset
|
||||||
|
dchrono ch start
|
||||||
|
puts [fastsewing result -tol 5.1e-4 a]
|
||||||
|
dchrono ch stop
|
||||||
|
|
||||||
|
set q [dchrono ch show]
|
||||||
|
|
||||||
|
regexp {CPU user time: ([-0-9.+eE]+) seconds} $q full z
|
||||||
|
puts "$z"
|
||||||
|
|
||||||
|
if { $z > ${max_time} } {
|
||||||
|
puts "Elapsed time is more than ${max_time} seconds - Error"
|
||||||
|
} else {
|
||||||
|
puts "Elapsed time is less than ${max_time} seconds - OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
donly result
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
set nbshapes_expected "
|
||||||
|
Number of shapes in shape
|
||||||
|
VERTEX : 5994
|
||||||
|
EDGE : 11715
|
||||||
|
WIRE : 5698
|
||||||
|
FACE : 5698
|
||||||
|
SHELL : 3
|
||||||
|
SOLID : 0
|
||||||
|
COMPSOLID : 0
|
||||||
|
COMPOUND : 1
|
||||||
|
SHAPE : 29109
|
||||||
|
"
|
||||||
|
|
||||||
|
checknbshapes result -ref "${nbshapes_expected}" -t -m "Partition of 2 shapes"
|
@ -1,3 +1,4 @@
|
|||||||
001 tol_0_01
|
001 tol_0_01
|
||||||
002 tol_1
|
002 tol_1
|
||||||
003 tol_100
|
003 tol_100
|
||||||
|
004 fast
|
||||||
|
Loading…
x
Reference in New Issue
Block a user