mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-07 18:30:55 +03:00
Upgrade method of computing vertex tolerance. Update function, which used the old method. Test case for issue CR26241 Delete obsolete variables. Small correction of test cases for issue CR26241
4751 lines
166 KiB
C++
4751 lines
166 KiB
C++
// Created on: 1995-03-24
|
|
// Created by: Jing Cheng MEI
|
|
// Copyright (c) 1995-1999 Matra Datavision
|
|
// Copyright (c) 1999-2014 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.
|
|
|
|
// dcl CCI60011 : Correction of degeneratedSection
|
|
// Improvement of SameParameter Edge to treat case of failure in BRepLib::SameParameter
|
|
// dcl Thu Aug 20 09:24:49 1998
|
|
// Suppression of little faces.
|
|
// dcl Fri Aug 7 15:27:46 1998
|
|
// Refection of function SameParameter Edge.
|
|
// Merge on the edge which has the less of poles.
|
|
// Suppression of the Connected Edge function.
|
|
// dcl Tue Jun 9 14:21:53 1998
|
|
// Do not merge edge if they belong the same face
|
|
// Tolerance management in VerticesAssembling
|
|
// Tolerance management in Cutting
|
|
// dcl Thu May 14 15:51:46 1998
|
|
// optimization of cutting
|
|
// dcl Thu May 7 15:51:46 1998
|
|
// Add of cutting option
|
|
// Add of SameParameter call
|
|
|
|
|
|
//-- lbr April 1 97
|
|
//-- dpf December 10 1997 Processing of pcurve collections
|
|
|
|
//rln 02.02.99 BUC60449 Making compilable on NT in DEB mode
|
|
//rln 02.02.99 BUC60449 Protection against exception on NT
|
|
|
|
#define TEST 1
|
|
|
|
#include <BRepBuilderAPI_Sewing.ixx>
|
|
|
|
#include <Bnd_Box.hxx>
|
|
#include <Bnd_Box2d.hxx>
|
|
#include <Bnd_HArray1OfBox.hxx>
|
|
#include <BndLib_Add2dCurve.hxx>
|
|
#include <BndLib_Add3dCurve.hxx>
|
|
#include <BRep_Builder.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRepLib.hxx>
|
|
#include <BRepTools_Quilt.hxx>
|
|
#include <BSplCLib.hxx>
|
|
#include <Extrema_ExtPC.hxx>
|
|
#include <GCPnts_AbscissaPoint.hxx>
|
|
#include <GCPnts_UniformAbscissa.hxx>
|
|
#include <GCPnts_UniformDeflection.hxx>
|
|
#include <Geom2d_BezierCurve.hxx>
|
|
#include <Geom2d_BSplineCurve.hxx>
|
|
#include <Geom2d_Curve.hxx>
|
|
#include <Geom2d_Line.hxx>
|
|
#include <Geom2d_TrimmedCurve.hxx>
|
|
#include <Geom2dAdaptor_Curve.hxx>
|
|
#include <Geom2dConvert.hxx>
|
|
#include <Geom_BezierCurve.hxx>
|
|
#include <Geom_BSplineCurve.hxx>
|
|
#include <Geom_Curve.hxx>
|
|
#include <Geom_Line.hxx>
|
|
#include <Geom_Surface.hxx>
|
|
#include <GeomAdaptor_Curve.hxx>
|
|
#include <GeomAdaptor_Surface.hxx>
|
|
#include <GeomLib.hxx>
|
|
#include <gp_Pnt.hxx>
|
|
#include <gp_Vec.hxx>
|
|
//#include <LocalAnalysis_SurfaceContinuity.hxx>
|
|
#include <Precision.hxx>
|
|
#include <Standard_ErrorHandler.hxx>
|
|
#include <Standard_Failure.hxx>
|
|
#include <TColgp_Array1OfVec.hxx>
|
|
#include <TColgp_SequenceOfPnt.hxx>
|
|
#include <TColStd_Array1OfInteger.hxx>
|
|
#include <TColStd_Array1OfReal.hxx>
|
|
#include <TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger.hxx>
|
|
#include <TColStd_DataMapOfIntegerListOfInteger.hxx>
|
|
#include <TColStd_IndexedMapOfInteger.hxx>
|
|
#include <TColStd_ListIteratorOfListOfInteger.hxx>
|
|
#include <TColStd_ListOfInteger.hxx>
|
|
#include <TColStd_MapOfInteger.hxx>
|
|
#include <TColStd_SequenceOfReal.hxx>
|
|
#include <TopAbs.hxx>
|
|
#include <TopExp.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <TopLoc_Location.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Iterator.hxx>
|
|
#include <TopoDS_Shape.hxx>
|
|
#include <TopoDS_Vertex.hxx>
|
|
#include <TopoDS_Wire.hxx>
|
|
#include <TopoDS_Shell.hxx>
|
|
#include <TopTools_Array1OfShape.hxx>
|
|
#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
|
|
#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
|
|
#include <TopTools_DataMapOfShapeInteger.hxx>
|
|
#include <TopTools_DataMapOfShapeListOfShape.hxx>
|
|
#include <TopTools_ListIteratorOfListOfShape.hxx>
|
|
#include <TopTools_ListOfShape.hxx>
|
|
#include <TopTools_MapIteratorOfMapOfShape.hxx>
|
|
#include <TopTools_MapOfShape.hxx>
|
|
#include <TopTools_SequenceOfShape.hxx>
|
|
#include <TopoDS_Compound.hxx>
|
|
#include <TColStd_Array2OfReal.hxx>
|
|
#include <TColStd_MapIteratorOfMapOfInteger.hxx>
|
|
#include <BRepTools.hxx>
|
|
#include <Geom_RectangularTrimmedSurface.hxx>
|
|
#include <Geom_OffsetSurface.hxx>
|
|
#include <BRep_PointOnCurve.hxx>
|
|
#include <BRep_ListOfPointRepresentation.hxx>
|
|
#include <BRep_TVertex.hxx>
|
|
#include <Message_ProgressSentry.hxx>
|
|
#include <BRepBuilderAPI_VertexInspector.hxx>
|
|
#include <BRepBuilderAPI_CellFilter.hxx>
|
|
#include <BRepBuilderAPI_BndBoxTreeSelector.hxx>
|
|
#include <NCollection_UBTreeFiller.hxx>
|
|
|
|
//=======================================================================
|
|
//function : SameRange
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
|
|
const Standard_Real FirstOnCurve,
|
|
const Standard_Real LastOnCurve,
|
|
const Standard_Real RequestedFirst,
|
|
const Standard_Real RequestedLast) const
|
|
{
|
|
Handle(Geom2d_Curve) NewCurvePtr;
|
|
try {
|
|
|
|
GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
|
|
RequestedFirst,RequestedLast,NewCurvePtr);
|
|
}
|
|
catch (Standard_Failure) {
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
|
|
Standard_Failure::Caught()->Print(cout); cout << endl;
|
|
#endif
|
|
}
|
|
return NewCurvePtr;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : WhichFace
|
|
//purpose : Give the face whose edge is the border
|
|
//=======================================================================
|
|
|
|
TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
|
|
{
|
|
TopoDS_Shape bound = theEdg;
|
|
if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
|
|
if (myBoundFaces.Contains(bound)) {
|
|
Standard_Integer i = 1;
|
|
TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
|
|
for (; itf.More(); itf.Next(), i++)
|
|
if (i == index) return TopoDS::Face(itf.Value());
|
|
}
|
|
return TopoDS_Face();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsClosedShape
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
|
|
const TopoDS_Shape& v1, const TopoDS_Shape& v2)
|
|
{
|
|
Standard_Real TotLength = 0.0;
|
|
TopExp_Explorer aexp;
|
|
for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
|
|
TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
|
|
if (aedge.IsNull()) continue;
|
|
TopoDS_Vertex ve1,ve2;
|
|
TopExp::Vertices(aedge,ve1,ve2);
|
|
if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
|
|
if (BRep_Tool::Degenerated(aedge)) continue;
|
|
Standard_Real first,last;
|
|
Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
|
|
if (!c3d.IsNull()) {
|
|
GeomAdaptor_Curve cAdapt(c3d);
|
|
Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
|
|
TotLength += length;
|
|
if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
|
|
}
|
|
}
|
|
if (TotLength > 0.0) {
|
|
gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
|
|
gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
|
|
return (p1.Distance(p2) < TotLength/(1.2 * M_PI));
|
|
}
|
|
return Standard_False;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsClosedByIsos
|
|
//purpose :
|
|
//=======================================================================
|
|
static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
|
|
const Handle(Geom2d_Curve)& acrv2d,
|
|
const Standard_Real f2d,
|
|
const Standard_Real l2d,
|
|
const Standard_Boolean isUIsos)
|
|
{
|
|
Standard_Boolean isClosed = Standard_False;
|
|
|
|
gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ?
|
|
acrv2d->Value(f2d) : acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
|
|
gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ?
|
|
acrv2d->Value(l2d) : acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
|
|
Handle(Geom_Curve) aCrv1;
|
|
Handle(Geom_Curve) aCrv2;
|
|
if(isUIsos) {
|
|
aCrv1 = thesurf->UIso(psurf1.X());
|
|
aCrv2 = thesurf->UIso(psurf2.X());
|
|
}
|
|
else {
|
|
aCrv1 = thesurf->VIso(psurf1.Y());
|
|
aCrv2 = thesurf->VIso(psurf2.Y());
|
|
}
|
|
gp_Pnt p11,p1m,p12,p21,p2m,p22;
|
|
Standard_Real af1 = aCrv1->FirstParameter();
|
|
Standard_Real al1 = aCrv1->LastParameter();
|
|
Standard_Real af2 = aCrv2->FirstParameter();
|
|
Standard_Real al2 = aCrv2->LastParameter();
|
|
aCrv1->D0(af1,p11);
|
|
aCrv1->D0((af1+al1)*0.5,p1m);
|
|
aCrv1->D0(al1,p12);
|
|
aCrv2->D0(af2,p21);
|
|
aCrv2->D0((af2+al2)*0.5,p2m);
|
|
aCrv2->D0(al2,p22);
|
|
isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() <
|
|
(p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
|
|
((p21.XYZ() - p22.XYZ()).Modulus() <
|
|
(p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
|
|
return isClosed;
|
|
}
|
|
//=======================================================================
|
|
//function : IsUClosedSurface
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
|
|
const TopoDS_Shape& theEdge,
|
|
const TopLoc_Location& theloc) const
|
|
{
|
|
Handle(Geom_Surface) tmpsurf = surf;
|
|
if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
|
|
tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
|
|
else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
|
|
tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
|
|
else {
|
|
Standard_Boolean isClosed = tmpsurf->IsUClosed();
|
|
if(!isClosed) {
|
|
Standard_Real f2d, l2d;
|
|
Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
|
|
if(!acrv2d.IsNull())
|
|
isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
|
|
|
|
}
|
|
return isClosed;
|
|
}
|
|
return IsUClosedSurface(tmpsurf,theEdge,theloc);
|
|
//return surf->IsUClosed();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsVClosedSurface
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
|
|
const TopoDS_Shape& theEdge,
|
|
const TopLoc_Location& theloc) const
|
|
{
|
|
Handle(Geom_Surface) tmpsurf = surf;
|
|
if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
|
|
tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
|
|
else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
|
|
tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
|
|
else {
|
|
Standard_Boolean isClosed = tmpsurf->IsVClosed();
|
|
if(!isClosed) {
|
|
Standard_Real f2d, l2d;
|
|
Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
|
|
if(!acrv2d.IsNull())
|
|
isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
|
|
}
|
|
return isClosed;
|
|
}
|
|
return IsVClosedSurface(tmpsurf,theEdge,theloc);
|
|
//return surf->IsVClosed();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SameParameter
|
|
//purpose : internal use
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
|
|
{
|
|
try {
|
|
|
|
BRepLib::SameParameter(edge);
|
|
}
|
|
catch (Standard_Failure) {
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
|
|
Standard_Failure::Caught()->Print(cout); cout << endl;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SameParameterEdge
|
|
//purpose : internal use
|
|
// Merge the Sequence Of Section on one edge.
|
|
// This function keep the curve3d,curve2d,range and parametrization
|
|
// from the first section, and report and made sameparameter the
|
|
// pcurves of the other function.
|
|
// This function works when the are not more than two Pcurves
|
|
// on a same face.
|
|
//=======================================================================
|
|
|
|
TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
|
|
const TopTools_SequenceOfShape& seqEdges,
|
|
const TColStd_SequenceOfInteger& seqForward,
|
|
TopTools_MapOfShape& mapMerged,
|
|
const Handle(BRepTools_ReShape)& locReShape)
|
|
{
|
|
// Retrieve reference section
|
|
TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
|
|
TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
|
|
aTmpShape = locReShape->Apply(Edge1);
|
|
if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
|
|
Standard_Boolean isDone = Standard_False;
|
|
|
|
// Create data structures for temporary merged edges
|
|
TopTools_ListOfShape listFaces1;
|
|
TopTools_MapOfShape MergedFaces;
|
|
|
|
if (mySewing) {
|
|
|
|
// Fill MergedFaces with faces of Edge1
|
|
TopoDS_Shape bnd1 = edge;
|
|
if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
|
|
if (myBoundFaces.Contains(bnd1)) {
|
|
TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
|
|
for (; itf.More(); itf.Next())
|
|
if (MergedFaces.Add(itf.Value()))
|
|
listFaces1.Append(itf.Value());
|
|
}
|
|
}
|
|
else {
|
|
|
|
// Create presentation edge
|
|
TopoDS_Vertex V1, V2;
|
|
TopExp::Vertices(Edge1,V1,V2);
|
|
if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
|
|
if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
|
|
|
|
TopoDS_Edge NewEdge = Edge1;
|
|
NewEdge.EmptyCopy();
|
|
|
|
// Add the vertices
|
|
BRep_Builder aBuilder;
|
|
TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
|
|
aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
|
|
aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
|
|
|
|
Edge1 = NewEdge;
|
|
}
|
|
|
|
Standard_Boolean isForward = Standard_True;
|
|
|
|
// Merge candidate sections
|
|
for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
|
|
|
|
// Retrieve candidate section
|
|
TopoDS_Shape oedge2 = seqEdges(i);
|
|
|
|
if (mySewing) {
|
|
|
|
aTmpShape = myReShape->Apply(oedge2); //for porting
|
|
TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
|
|
aTmpShape = locReShape->Apply(Edge2);
|
|
if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
|
|
|
|
// Calculate relative orientation
|
|
Standard_Integer Orientation = seqForward(i);
|
|
if (!isForward) Orientation = (Orientation? 0 : 1);
|
|
|
|
// Retrieve faces information for the second edge
|
|
TopoDS_Shape bnd2 = oedge2;
|
|
if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
|
|
if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
|
|
const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
|
|
|
|
Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
|
|
TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
|
|
if (NewEdge.IsNull()) continue;
|
|
|
|
// Record faces information for the temporary merged edge
|
|
TopTools_ListIteratorOfListOfShape itf(listFaces2);
|
|
for (; itf.More(); itf.Next())
|
|
if (MergedFaces.Add(itf.Value()))
|
|
listFaces1.Append(itf.Value());
|
|
|
|
// Record merged section orientation
|
|
if (!Orientation && whichSec != 1)
|
|
isForward = isForward? Standard_False : Standard_True;
|
|
Edge1 = NewEdge;
|
|
}
|
|
|
|
// Append actually merged edge
|
|
mapMerged.Add(oedge2);
|
|
isDone = Standard_True;
|
|
|
|
if (!myNonmanifold) break;
|
|
}
|
|
|
|
if (isDone) {
|
|
// Change result orientation
|
|
Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
|
|
}
|
|
else Edge1.Nullify();
|
|
|
|
return Edge1;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SameParameterEdge
|
|
//purpose : internal use
|
|
//=======================================================================
|
|
static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
|
|
TopTools_SequenceOfShape& theSeqNMVert,
|
|
TColStd_SequenceOfReal& theSeqPars)
|
|
{
|
|
TopoDS_Iterator aItV(theEdge,Standard_False);
|
|
for( ; aItV.More(); aItV.Next()) {
|
|
if(aItV.Value().Orientation() == TopAbs_INTERNAL ||
|
|
aItV.Value().Orientation() == TopAbs_EXTERNAL)
|
|
theSeqNMVert.Append(aItV.Value());
|
|
}
|
|
Standard_Integer nbV = theSeqNMVert.Length();
|
|
if(!nbV)
|
|
return Standard_False;
|
|
Standard_Real first, last;
|
|
Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
|
|
GeomAdaptor_Curve GAC(c3d);
|
|
Extrema_ExtPC locProj;
|
|
locProj.Initialize(GAC, first, last);
|
|
gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
|
|
|
|
|
|
for (Standard_Integer i = 1; i <= nbV; i++) {
|
|
TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
|
|
gp_Pnt pt = BRep_Tool::Pnt(aV);
|
|
|
|
Standard_Real distF2 = pfirst.SquareDistance(pt);
|
|
Standard_Real distL2 = plast.SquareDistance(pt);
|
|
Standard_Real apar = (distF2 > distL2 ? last : first);
|
|
// Project current point on curve
|
|
locProj.Perform(pt);
|
|
if (locProj.IsDone() && locProj.NbExt() > 0) {
|
|
Standard_Real dist2Min = Min(distF2,distL2);
|
|
Standard_Integer ind, indMin = 0;
|
|
for (ind = 1; ind <= locProj.NbExt(); ind++) {
|
|
Standard_Real dProj2 = locProj.SquareDistance(ind);
|
|
if (dProj2 < dist2Min) {
|
|
indMin = ind; dist2Min = dProj2;
|
|
}
|
|
}
|
|
if(indMin)
|
|
apar = locProj.Point(indMin).Parameter();
|
|
|
|
theSeqPars.Append(apar);
|
|
|
|
}
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
static void ComputeToleranceVertex(TopoDS_Vertex theV1, TopoDS_Vertex theV2,
|
|
TopoDS_Vertex& theNewV)
|
|
{
|
|
Standard_Integer m, n;
|
|
Standard_Real aR[2], dR, aD, aEps;
|
|
TopoDS_Vertex aV[2];
|
|
gp_Pnt aP[2];
|
|
BRep_Builder aBB;
|
|
//
|
|
aEps = RealEpsilon();
|
|
aV[0] = theV1;
|
|
aV[1] = theV2;
|
|
for (m = 0; m < 2; ++m) {
|
|
aP[m] = BRep_Tool::Pnt(aV[m]);
|
|
aR[m] = BRep_Tool::Tolerance(aV[m]);
|
|
}
|
|
//
|
|
m=0; // max R
|
|
n=1; // min R
|
|
if (aR[0] < aR[1]) {
|
|
m=1;
|
|
n=0;
|
|
}
|
|
//
|
|
dR = aR[m] - aR[n]; // dR >= 0.
|
|
gp_Vec aVD(aP[m], aP[n]);
|
|
aD = aVD.Magnitude();
|
|
//
|
|
if (aD <= dR || aD < aEps) {
|
|
aBB.MakeVertex (theNewV, aP[m], aR[m]);
|
|
}
|
|
else {
|
|
Standard_Real aRr;
|
|
gp_XYZ aXYZr;
|
|
gp_Pnt aPr;
|
|
//
|
|
aRr = 0.5 * (aR[m] + aR[n] + aD);
|
|
aXYZr = 0.5 * (aP[m].XYZ() + aP[n].XYZ() - aVD.XYZ() * (dR/aD));
|
|
aPr.SetXYZ(aXYZr);
|
|
//
|
|
aBB.MakeVertex (theNewV, aPr, aRr);
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void ComputeToleranceVertex(TopoDS_Vertex theV1, TopoDS_Vertex theV2,
|
|
TopoDS_Vertex theV3, TopoDS_Vertex& theNewV)
|
|
{
|
|
Standard_Real aDi, aDmax;
|
|
gp_Pnt aCenter;
|
|
gp_Pnt aP[3];
|
|
Standard_Real aR[3];
|
|
TopoDS_Vertex aV[3];
|
|
gp_XYZ aXYZ(0.,0.,0.);
|
|
aV[0] = theV1;
|
|
aV[1] = theV2;
|
|
aV[2] = theV3;
|
|
for (Standard_Integer i = 0; i < 3; ++i) {
|
|
aP[i] = BRep_Tool::Pnt(aV[i]);
|
|
aR[i] = BRep_Tool::Tolerance(aV[i]);
|
|
aXYZ = aXYZ + aP[i].XYZ();
|
|
}
|
|
//
|
|
aXYZ.Divide(3.0);
|
|
aCenter.SetXYZ(aXYZ);
|
|
//
|
|
aDmax=-1.;
|
|
for ( Standard_Integer i = 0; i < 3; ++i) {
|
|
aDi = aCenter.Distance(aP[i]);
|
|
aDi += aR[i];
|
|
if (aDi > aDmax)
|
|
aDmax = aDi;
|
|
}
|
|
|
|
BRep_Builder aBB;
|
|
aBB.MakeVertex (theNewV, aCenter, aDmax);
|
|
return;
|
|
}
|
|
|
|
TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
|
|
const TopoDS_Edge& edgeLast,
|
|
const TopTools_ListOfShape& listFacesFirst,
|
|
const TopTools_ListOfShape& listFacesLast,
|
|
const Standard_Boolean secForward,
|
|
Standard_Integer& whichSec,
|
|
const Standard_Boolean firstCall)
|
|
{
|
|
// Do not process floating edges
|
|
if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
|
|
|
|
// Sort input edges
|
|
TopoDS_Edge edge1, edge2;
|
|
if (firstCall) {
|
|
// Take the longest edge as first
|
|
Standard_Real f, l;
|
|
Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
|
|
GeomAdaptor_Curve cAdapt1(c3d1);
|
|
Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
|
|
Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
|
|
GeomAdaptor_Curve cAdapt2(c3d2);
|
|
Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
|
|
if (len1 < len2) {
|
|
edge1 = edgeLast;
|
|
edge2 = edgeFirst;
|
|
whichSec = 2;
|
|
}
|
|
else {
|
|
edge1 = edgeFirst;
|
|
edge2 = edgeLast;
|
|
whichSec = 1;
|
|
}
|
|
}
|
|
else {
|
|
if (whichSec == 1) {
|
|
edge1 = edgeLast;
|
|
edge2 = edgeFirst;
|
|
whichSec = 2;
|
|
}
|
|
else {
|
|
edge1 = edgeFirst;
|
|
edge2 = edgeLast;
|
|
whichSec = 1;
|
|
}
|
|
}
|
|
|
|
Standard_Real first, last;
|
|
BRep_Tool::Range(edge1, first, last);
|
|
BRep_Builder aBuilder;
|
|
|
|
//To keep NM vertices on edge
|
|
TopTools_SequenceOfShape aSeqNMVert;
|
|
TColStd_SequenceOfReal aSeqNMPars;
|
|
findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
|
|
findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
|
|
|
|
// Create new edge
|
|
TopoDS_Edge edge;
|
|
aBuilder.MakeEdge(edge);
|
|
edge.Orientation( edge1.Orientation());
|
|
|
|
|
|
// Retrieve edge curve
|
|
TopLoc_Location loc3d;
|
|
Standard_Real first3d, last3d;
|
|
Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
|
|
if (!loc3d.IsIdentity()) {
|
|
c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
|
|
c3d->Transform(loc3d.Transformation());
|
|
}
|
|
aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
|
|
aBuilder.Range(edge, first, last);
|
|
aBuilder.SameRange(edge, Standard_False); //Standard_True
|
|
aBuilder.SameParameter(edge, Standard_False);
|
|
// Create and add new vertices
|
|
{
|
|
TopoDS_Vertex V1New, V2New;
|
|
|
|
// Retrieve original vertices from edges
|
|
TopoDS_Vertex V11,V12,V21,V22;
|
|
TopExp::Vertices(edge1,V11,V12);
|
|
TopExp::Vertices(edge2,V21,V22);
|
|
|
|
//check that edges merged valid way (for edges having length less than specified
|
|
//tolerance
|
|
// Check if edges are closed
|
|
Standard_Boolean isClosed1 = V11.IsSame(V12);
|
|
Standard_Boolean isClosed2 = V21.IsSame(V22);
|
|
if(!isClosed1 && !isClosed2)
|
|
{
|
|
if(secForward )
|
|
{
|
|
if( V11.IsSame(V22) || V12.IsSame(V21) )
|
|
return TopoDS_Edge();
|
|
}
|
|
else
|
|
{
|
|
if( V11.IsSame(V21) || V12.IsSame(V22) )
|
|
return TopoDS_Edge();
|
|
}
|
|
}
|
|
|
|
//szv: do not reshape here!!!
|
|
//V11 = TopoDS::Vertex(myReShape->Apply(V11));
|
|
//V12 = TopoDS::Vertex(myReShape->Apply(V12));
|
|
//V21 = TopoDS::Vertex(myReShape->Apply(V21));
|
|
//V22 = TopoDS::Vertex(myReShape->Apply(V22));
|
|
|
|
//Standard_Boolean isRev = Standard_False;
|
|
if (isClosed1 || isClosed2) {
|
|
// at least one of the edges is closed
|
|
if (isClosed1 && isClosed2) {
|
|
// both edges are closed
|
|
ComputeToleranceVertex(V11, V21, V1New);
|
|
}
|
|
else if (isClosed1) {
|
|
// only first edge is closed
|
|
ComputeToleranceVertex(V22, V21, V11, V1New);
|
|
}
|
|
else {
|
|
// only second edge is closed
|
|
ComputeToleranceVertex(V11, V12, V21, V1New);
|
|
}
|
|
V2New = V1New;
|
|
}
|
|
else {
|
|
// both edges are open
|
|
Standard_Boolean isOldFirst = ( secForward ? V11.IsSame(V21) : V11.IsSame(V22) );
|
|
Standard_Boolean isOldLast = ( secForward ? V12.IsSame(V22) : V12.IsSame(V21)) ;
|
|
if (secForward) {
|
|
//case if vertices already sewed
|
|
if(!isOldFirst)
|
|
{
|
|
ComputeToleranceVertex(V11, V21, V1New);
|
|
}
|
|
if(!isOldLast)
|
|
{
|
|
ComputeToleranceVertex(V12, V22, V2New);
|
|
}
|
|
}
|
|
else {
|
|
if(!isOldFirst)
|
|
{
|
|
ComputeToleranceVertex(V11, V22, V1New);
|
|
}
|
|
if(!isOldLast)
|
|
{
|
|
ComputeToleranceVertex(V12, V21, V2New);
|
|
}
|
|
}
|
|
if(isOldFirst)
|
|
V1New = V11;
|
|
|
|
if(isOldLast)
|
|
V2New = V12;
|
|
}
|
|
// Add the vertices in the good sense
|
|
TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
|
|
TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
|
|
aBuilder.Add(anEdge,aLocalEdge);
|
|
aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
|
|
aBuilder.Add(anEdge,aLocalEdge);
|
|
|
|
Standard_Integer k =1;
|
|
for( ; k <= aSeqNMVert.Length(); k++)
|
|
aBuilder.Add(anEdge,aSeqNMVert.Value(k));
|
|
|
|
}
|
|
|
|
// Retrieve second PCurves
|
|
TopLoc_Location loc2;
|
|
Handle(Geom_Surface) surf2;
|
|
|
|
//Handle(Geom2d_Curve) c2d2, c2d21;
|
|
// Standard_Real firstOld, lastOld;
|
|
|
|
TopTools_ListIteratorOfListOfShape itf2;
|
|
if (whichSec == 1) itf2.Initialize(listFacesLast);
|
|
else itf2.Initialize(listFacesFirst);
|
|
Standard_Boolean isResEdge = Standard_False;
|
|
TopoDS_Face fac2;
|
|
for (; itf2.More(); itf2.Next()) {
|
|
Handle(Geom2d_Curve) c2d2, c2d21;
|
|
Standard_Real firstOld, lastOld;
|
|
fac2 = TopoDS::Face(itf2.Value());
|
|
|
|
surf2 = BRep_Tool::Surface(fac2, loc2);
|
|
Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
|
|
BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
|
|
if (isSeam2) {
|
|
if (!myNonmanifold) return TopoDS_Edge();
|
|
TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
|
|
c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
|
|
}
|
|
c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
|
|
if (c2d2.IsNull() && c2d21.IsNull()) continue;
|
|
|
|
if (!c2d21.IsNull()) {
|
|
c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
|
|
if (!secForward) {
|
|
if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
|
|
c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
|
|
Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
|
|
Standard_Real last2d = lastOld; //c2dTmp->LastParameter();
|
|
firstOld = c2d21->ReversedParameter(last2d);
|
|
lastOld = c2d21->ReversedParameter(first2d);
|
|
c2d21->Reverse();
|
|
}
|
|
c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
|
|
}
|
|
|
|
// Make second PCurve sameRange with the 3d curve
|
|
c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
|
|
|
|
if (!secForward) {
|
|
if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
|
|
c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
|
|
Standard_Real first2d = firstOld;
|
|
Standard_Real last2d = lastOld;
|
|
firstOld = c2d2->ReversedParameter(last2d);
|
|
lastOld = c2d2->ReversedParameter(first2d);
|
|
c2d2->Reverse();
|
|
}
|
|
|
|
c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
|
|
if (c2d2.IsNull()) continue;
|
|
|
|
// Add second PCurve
|
|
Standard_Boolean isSeam = Standard_False;
|
|
TopAbs_Orientation Ori = TopAbs_FORWARD;
|
|
//Handle(Geom2d_Curve) c2d1, c2d11;
|
|
|
|
TopTools_ListIteratorOfListOfShape itf1;
|
|
if (whichSec == 1) itf1.Initialize(listFacesFirst);
|
|
else itf1.Initialize(listFacesLast);
|
|
for (; itf1.More() && !isSeam; itf1.Next()) {
|
|
Handle(Geom2d_Curve) c2d1, c2d11;
|
|
const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
|
|
|
|
TopLoc_Location loc1;
|
|
Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
|
|
|
|
Standard_Real first2d, last2d;
|
|
Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
|
|
BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
|
|
c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
|
|
Ori = edge1.Orientation();
|
|
if (fac1.Orientation() == TopAbs_REVERSED)
|
|
Ori = TopAbs::Reverse(Ori);
|
|
|
|
if (isSeam1) {
|
|
if (!myNonmanifold) return TopoDS_Edge();
|
|
TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
|
|
c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
|
|
//if(fac1.Orientation() == TopAbs_REVERSED) //
|
|
if(Ori == TopAbs_FORWARD)
|
|
aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
|
|
else
|
|
aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
|
|
}
|
|
else aBuilder.UpdateEdge(edge,c2d1,fac1,0);
|
|
|
|
if (c2d1.IsNull() && c2d11.IsNull()) continue;
|
|
|
|
if (surf2 == surf1) {
|
|
// Merge sections which are on the same face
|
|
if (!loc2.IsDifferent(loc1)) {
|
|
Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
|
|
Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
|
|
if (uclosed || vclosed) {
|
|
Standard_Real pf = c2d1->FirstParameter();
|
|
// Standard_Real pl = c2d1->LastParameter();
|
|
gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
|
|
// gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
|
|
gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
|
|
gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
|
|
Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
|
|
Standard_Real U1, U2, V1, V2;
|
|
surf2->Bounds(U1, U2, V1, V2);
|
|
isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
|
|
(vclosed && aDist > 0.75*(fabs(V2-V1))));
|
|
if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
isResEdge = Standard_True;
|
|
if (isSeam) {
|
|
if (Ori == TopAbs_FORWARD)
|
|
aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
|
|
else
|
|
aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
|
|
}
|
|
else if (isSeam2) {
|
|
TopAbs_Orientation InitOri = edge2.Orientation();
|
|
TopAbs_Orientation SecOri = edge.Orientation();
|
|
if (fac2.Orientation() == TopAbs_REVERSED) {
|
|
|
|
InitOri = TopAbs::Reverse(InitOri);
|
|
SecOri = TopAbs::Reverse(SecOri);
|
|
}
|
|
if(!secForward)
|
|
InitOri = TopAbs::Reverse(InitOri);
|
|
|
|
if (InitOri == TopAbs_FORWARD)
|
|
aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
|
|
else
|
|
aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
|
|
}
|
|
else {
|
|
aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
|
|
}
|
|
|
|
}
|
|
}
|
|
Standard_Real tolReached = Precision::Infinite();
|
|
Standard_Boolean isSamePar = Standard_False;
|
|
try
|
|
{
|
|
if( isResEdge)
|
|
SameParameter(edge);
|
|
|
|
|
|
if( BRep_Tool::SameParameter(edge))
|
|
{
|
|
isSamePar = Standard_True;
|
|
tolReached = BRep_Tool::Tolerance(edge);
|
|
}
|
|
}
|
|
|
|
catch(Standard_Failure)
|
|
{
|
|
isSamePar = Standard_False;
|
|
}
|
|
|
|
|
|
if (firstCall && ( !isResEdge || !isSamePar || tolReached > myTolerance)) {
|
|
Standard_Integer whichSecn = whichSec;
|
|
// Try to merge on the second section
|
|
Standard_Boolean second_ok = Standard_False;
|
|
TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
|
|
secForward,whichSecn,Standard_False);
|
|
if( !s_edge.IsNull())
|
|
{
|
|
Standard_Real tolReached_2 = BRep_Tool::Tolerance(s_edge);
|
|
second_ok = ( BRep_Tool::SameParameter(s_edge) && tolReached_2 < tolReached );
|
|
if( second_ok)
|
|
{
|
|
edge = s_edge;
|
|
whichSec = whichSecn;
|
|
tolReached = tolReached_2;
|
|
}
|
|
}
|
|
|
|
if (!second_ok && !edge.IsNull()) {
|
|
|
|
GeomAdaptor_Curve c3dAdapt(c3d);
|
|
|
|
// Discretize edge curve
|
|
Standard_Integer i, j, nbp = 23;
|
|
Standard_Real deltaT = (last3d - first3d) / (nbp -1);
|
|
TColgp_Array1OfPnt c3dpnt(1,nbp);
|
|
for (i = 1; i <= nbp; i++)
|
|
c3dpnt(i) = c3dAdapt.Value(first3d + (i-1)*deltaT);
|
|
|
|
Standard_Real dist = 0., maxTol = -1.0;
|
|
Standard_Boolean more = Standard_True;
|
|
|
|
for (j = 1; more; j++) {
|
|
Handle(Geom2d_Curve) c2d2;
|
|
BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
|
|
|
|
more = !c2d2.IsNull();
|
|
if (more) {
|
|
Handle(Geom_Surface) aS = surf2;
|
|
if(!loc2.IsIdentity())
|
|
aS = Handle(Geom_Surface)::DownCast(surf2->Transformed ( loc2 ));
|
|
|
|
Standard_Real dist2 = 0.;
|
|
deltaT = (last - first) / (nbp - 1);
|
|
for (i = 1; i <= nbp; i++) {
|
|
gp_Pnt2d aP2d = c2d2->Value(first + (i -1)*deltaT);
|
|
gp_Pnt aP2(0.,0.,0.);
|
|
aS->D0(aP2d.X(),aP2d.Y(), aP2);
|
|
gp_Pnt aP1 = c3dpnt(i);
|
|
dist = aP2.SquareDistance(aP1);
|
|
if (dist > dist2)
|
|
dist2 = dist;
|
|
}
|
|
maxTol = Max(sqrt(dist2), Precision::Confusion());
|
|
}
|
|
}
|
|
if(maxTol >= 0. && maxTol < tolReached)
|
|
aBuilder.UpdateEdge(edge, maxTol);
|
|
aBuilder.SameParameter(edge,Standard_True);
|
|
}
|
|
}
|
|
|
|
BRepLib::EncodeRegularity(edge,0.01);
|
|
Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
|
|
if (tolEdge1 > MaxTolerance()) edge.Nullify();
|
|
return edge;
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : EvaluateAngulars
|
|
// purpose : internal use
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
|
|
TColStd_Array1OfBoolean& secForward,
|
|
TColStd_Array1OfReal& tabAng,
|
|
const Standard_Integer indRef) const
|
|
{
|
|
tabAng.Init(-1.0);
|
|
|
|
Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
|
|
|
|
TopoDS_Edge edge;
|
|
TopoDS_Face face;
|
|
TopLoc_Location loc;
|
|
Standard_Real first, last;
|
|
Handle(Geom_Curve) c3d;
|
|
Handle(Geom2d_Curve) c2d;
|
|
Handle(Geom_Surface) surf;
|
|
TColgp_Array1OfVec normRef(1,npt);
|
|
|
|
for (i = indRef; i <= lengSec; i++) {
|
|
|
|
edge = TopoDS::Edge(sequenceSec(i));
|
|
|
|
TopoDS_Shape bnd = edge;
|
|
if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
|
|
if (myBoundFaces.Contains(bnd)) {
|
|
face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
|
|
surf = BRep_Tool::Surface(face,loc);
|
|
if (!loc.IsIdentity()) {
|
|
surf = Handle(Geom_Surface)::DownCast(surf->Copy());
|
|
surf->Transform(loc.Transformation());
|
|
}
|
|
c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
|
|
}
|
|
else if (i == indRef) return;
|
|
else continue;
|
|
|
|
c3d = BRep_Tool::Curve(edge, loc, first, last);
|
|
if (!loc.IsIdentity()) {
|
|
c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
|
|
c3d->Transform(loc.Transformation());
|
|
}
|
|
|
|
GeomAdaptor_Curve adapt(c3d);
|
|
GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
|
|
|
|
Standard_Real cumulateAngular = 0.0;
|
|
Standard_Integer nbComputedAngle = 0;
|
|
|
|
for (j = 1; j <= npt; j++) {
|
|
gp_Pnt2d P;
|
|
c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
|
|
gp_Vec w1, w2;
|
|
gp_Pnt unused;
|
|
surf->D1(P.X(), P.Y(), unused, w1, w2);
|
|
gp_Vec n = w1^w2; // Compute the normal vector
|
|
if (i == indRef) normRef(j) = n;
|
|
else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
|
|
nbComputedAngle++;
|
|
Standard_Real angular = n.Angle(normRef(j));
|
|
if (angular > M_PI/2.) angular = M_PI - angular;
|
|
cumulateAngular += angular;
|
|
}
|
|
}
|
|
|
|
if (nbComputedAngle)
|
|
tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : EvaluateDistances
|
|
// purpose : internal use
|
|
// Evaluate distance beetween edges with indice indRef and the following edges in the list
|
|
// Remarks (lengSec - indRef) must be >= 1
|
|
//=======================================================================
|
|
void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
|
|
TColStd_Array1OfBoolean& secForward,
|
|
TColStd_Array1OfReal& tabDst,
|
|
TColStd_Array1OfReal& arrLen,
|
|
TColStd_Array1OfReal& tabMinDist,
|
|
const Standard_Integer indRef) const
|
|
{
|
|
secForward.Init(Standard_True);
|
|
tabDst.Init(-1.0);
|
|
arrLen.Init(0.);
|
|
tabMinDist.Init(Precision::Infinite());
|
|
const Standard_Integer npt = 8; // Number of points for curve discretization
|
|
TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
|
|
|
|
Standard_Integer i, j, lengSec = sequenceSec.Length();
|
|
TColgp_SequenceOfPnt seqSec;
|
|
|
|
Handle(Geom_Curve) c3dRef;
|
|
Standard_Real firstRef=0., lastRef=0.;
|
|
|
|
for (i = indRef; i <= lengSec; i++) {
|
|
|
|
// reading of the edge (attention for the first one: reference)
|
|
const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
|
|
|
|
TopLoc_Location loc;
|
|
Standard_Real first, last;
|
|
Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
|
|
if (c3d.IsNull()) continue;
|
|
if (!loc.IsIdentity()) {
|
|
c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
|
|
c3d->Transform(loc.Transformation());
|
|
}
|
|
|
|
if (i == indRef) {
|
|
c3dRef = c3d; firstRef = first; lastRef = last;
|
|
}
|
|
|
|
Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
|
|
Standard_Real aMinDist = Precision::Infinite();
|
|
|
|
Standard_Real T, deltaT = (last - first) / (npt - 1);
|
|
Standard_Real aLenSec2 = 0.;
|
|
|
|
Standard_Integer nbFound = 0;
|
|
for (j = 1; j <= npt; j++) {
|
|
|
|
// Uniform parameter on curve
|
|
if (j == 1) T = first;
|
|
else if (j == npt) T = last;
|
|
else T = first + (j - 1) * deltaT;
|
|
|
|
// Take point on curve
|
|
gp_Pnt pt = c3d->Value(T);
|
|
|
|
if (i == indRef) {
|
|
ptsRef(j) = pt;
|
|
if(j > 1)
|
|
aLenSec2 += pt.SquareDistance(ptsRef(j-1));
|
|
}
|
|
else {
|
|
ptsSec(j) = pt;
|
|
//protection to avoid merging with small sections
|
|
if(j > 1)
|
|
aLenSec2 += pt.SquareDistance(ptsSec(j-1));
|
|
// To evaluate mutual orientation and distance
|
|
dist = pt.Distance(ptsRef(j));
|
|
if(aMinDist > dist)
|
|
aMinDist = dist;
|
|
if (distFor < dist) distFor = dist;
|
|
dist = pt.Distance(ptsRef(npt-j+1));
|
|
|
|
if(aMinDist > dist)
|
|
aMinDist = dist;
|
|
if (distRev < dist) distRev = dist;
|
|
|
|
// Check that point lays between vertices of reference curve
|
|
const gp_Pnt &p11 = ptsRef(1);
|
|
const gp_Pnt &p12 = ptsRef(npt);
|
|
const gp_Vec aVec1(pt,p11);
|
|
const gp_Vec aVec2(pt,p12);
|
|
const gp_Vec aVecRef(p11,p12);
|
|
if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
|
|
nbFound++;
|
|
}
|
|
}
|
|
|
|
Standard_Real aLenSec = sqrt(aLenSec2);
|
|
|
|
//if(aLenSec < myMinTolerance )
|
|
// continue;
|
|
arrLen.SetValue(i,aLenSec);
|
|
// Record mutual orientation
|
|
Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
|
|
secForward(i) = isForward;
|
|
|
|
dist = (isForward? distFor : distRev);
|
|
if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
|
|
{
|
|
tabDst(i) = dist;
|
|
tabMinDist(i) = aMinDist;
|
|
}
|
|
else
|
|
{
|
|
nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
|
|
TColgp_Array1OfPnt arrProj(1, npt);
|
|
TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
|
|
if( arrLen(indRef) >= arrLen(i))
|
|
ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
|
|
else
|
|
ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
|
|
for( j = 1; j <= npt; j++ )
|
|
{
|
|
if(arrDist(j) < 0.)
|
|
continue;
|
|
if(dist < arrDist(j))
|
|
dist = arrDist(j);
|
|
if( aMinDist > arrDist(j))
|
|
aMinDist = arrDist(j);
|
|
nbFound++;
|
|
}
|
|
if(nbFound > 1)
|
|
{
|
|
tabDst(i) = dist;
|
|
tabMinDist(i) = aMinDist;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
// Project distant points
|
|
Standard_Integer nbFailed = seqSec.Length();
|
|
if (!nbFailed) return;
|
|
|
|
TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
|
|
for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
|
|
TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
|
|
|
|
ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
|
|
|
|
// Process distant sections
|
|
Standard_Integer idx1 = 1;
|
|
for (i = indRef + 1; i <= lengSec; i++) {
|
|
|
|
// Skip section if already evaluated
|
|
if (tabDst(i) >= 0.0) continue;
|
|
|
|
Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
|
|
|
|
Standard_Integer idx2 = (idx1 - 1)*npt;
|
|
|
|
for (j = 1; j <= npt; j++) {
|
|
|
|
dist = arrDist(idx2 + j);
|
|
// If point is not projected - stop evaluation
|
|
if (dist < 0.0) { distMax = -1.0; break; }
|
|
if (distMax < dist) distMax = dist;
|
|
if(aMinDist > dist) aMinDist = dist;
|
|
}
|
|
|
|
// If section is close - record distance
|
|
if (distMax >= 0.0) {
|
|
if (secForward(i)) {
|
|
dist = arrPnt(idx2+1).Distance(ptsRef(1));
|
|
if (distMax < dist) distMax = dist;
|
|
if(aMinDist > dist) aMinDist = dist;
|
|
dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
|
|
if (distMax < dist) distMax = dist;
|
|
if(aMinDist > dist) aMinDist = dist;
|
|
}
|
|
else {
|
|
dist = arrPnt(idx2+1).Distance(ptsRef(npt));
|
|
if (distMax < dist) distMax = dist;
|
|
if(aMinDist > dist) aMinDist = dist;
|
|
dist = arrPnt(idx2+npt).Distance(ptsRef(1));
|
|
if (distMax < dist) distMax = dist;
|
|
if(aMinDist > dist) aMinDist = dist;
|
|
}
|
|
|
|
if (distMax < myTolerance)
|
|
{
|
|
tabDst(i) = distMax;
|
|
tabMinDist(i) = aMinDist;
|
|
}
|
|
}
|
|
|
|
idx1++; // To the next distant curve
|
|
}*/
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsMergedClosed
|
|
//purpose : internal use
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
|
|
const TopoDS_Edge& Edge2,
|
|
const TopoDS_Face& face) const
|
|
{
|
|
// Check for closed surface
|
|
TopLoc_Location loc;
|
|
Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
|
|
Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
|
|
Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
|
|
if (!isUClosed && !isVClosed) return Standard_False;
|
|
// Check condition on closed surface
|
|
/*
|
|
Standard_Real first1,last1,first2,last2;
|
|
Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
|
|
Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
|
|
if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
|
|
*/
|
|
Standard_Real first2d1,last2d1,first2d2,last2d2;
|
|
Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
|
|
Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
|
|
if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
|
|
/*
|
|
gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
|
|
gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
|
|
Standard_Real dist = p1.Distance(p2);
|
|
gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
|
|
gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
|
|
Standard_Real dist2d = p12d.Distance(p22d);
|
|
GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
|
|
Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
|
|
return (dist2d*0.2 >= distSurf);
|
|
*/
|
|
Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
|
|
Standard_Real SUmin, SUmax, SVmin, SVmax;
|
|
Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
|
|
Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
|
|
{ //szv: Use brackets to destroy local variables
|
|
Bnd_Box2d B1, B2;
|
|
Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
|
|
BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
|
|
BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
|
|
B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
|
|
B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
|
|
Standard_Real du, dv;
|
|
du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
|
|
isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
|
|
du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
|
|
isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
|
|
surf->Bounds(SUmin,SUmax,SVmin,SVmax);
|
|
}
|
|
if (isUClosed && isVLongC1 && isVLongC2) {
|
|
// Do not merge if not overlapped by V
|
|
Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
|
|
if (dist < 0.0) {
|
|
Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
|
|
Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
|
|
if (distOuter <= distInner) return Standard_True;
|
|
}
|
|
}
|
|
if (isVClosed && isULongC1 && isULongC2) {
|
|
// Do not merge if not overlapped by U
|
|
Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
|
|
if (dist < 0.0) {
|
|
Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
|
|
Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
|
|
if (distOuter <= distInner) return Standard_True;
|
|
}
|
|
}
|
|
return Standard_False;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : AnalysisNearestEdges
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
|
|
TColStd_SequenceOfInteger& seqIndCandidate,
|
|
TColStd_SequenceOfInteger& seqOrientations,
|
|
const Standard_Boolean evalDist)
|
|
{
|
|
|
|
Standard_Integer workIndex = seqIndCandidate.First();
|
|
TopoDS_Shape workedge = sequenceSec.Value(workIndex);
|
|
TopoDS_Shape bnd = workedge;
|
|
TopTools_ListOfShape workfaces;
|
|
if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
|
|
if (myBoundFaces.Contains(bnd))
|
|
workfaces = myBoundFaces.FindFromKey(bnd);
|
|
if(workfaces.IsEmpty()) return;
|
|
TopTools_MapOfShape mapFaces;
|
|
TopTools_ListIteratorOfListOfShape lIt;
|
|
for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
|
|
mapFaces.Add(lIt.Value());
|
|
TColStd_SequenceOfInteger seqNotCandidate;
|
|
TColStd_SequenceOfInteger seqNewForward;
|
|
// Separates edges belonging the same face as work edge
|
|
// for exception of edges belonging closed faces
|
|
|
|
seqNotCandidate.Append(workIndex);
|
|
for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
|
|
Standard_Integer index = seqIndCandidate.Value(i);
|
|
Standard_Boolean isRemove = Standard_False;
|
|
if(index == workIndex) {
|
|
seqIndCandidate.Remove(i);
|
|
seqOrientations.Remove(i);
|
|
isRemove = Standard_True;
|
|
}
|
|
if(!isRemove) {
|
|
TopoDS_Shape bnd2 = sequenceSec.Value(index);
|
|
if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
|
|
|
|
if(myBoundFaces.Contains(bnd2)) {
|
|
const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
|
|
Standard_Boolean isMerged = Standard_True;
|
|
for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
|
|
if(mapFaces.Contains(lIt.Value())) {
|
|
TopLoc_Location loc;
|
|
Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
|
|
isMerged = ((IsUClosedSurface(surf,bnd2,loc) || IsVClosedSurface(surf,bnd2,loc)) &&
|
|
IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
|
|
}
|
|
}
|
|
if(!isMerged) {
|
|
seqNotCandidate.Append(index);
|
|
seqIndCandidate.Remove(i);
|
|
seqOrientations.Remove(i);
|
|
isRemove = Standard_True;
|
|
}
|
|
}
|
|
else {
|
|
seqIndCandidate.Remove(i);
|
|
seqOrientations.Remove(i);
|
|
isRemove = Standard_True;
|
|
}
|
|
}
|
|
if(!isRemove) i++;
|
|
}
|
|
if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
|
|
if(!evalDist) return;
|
|
TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
|
|
TColStd_MapOfInteger MapIndex;
|
|
TColStd_SequenceOfInteger seqForward;
|
|
|
|
// Definition and removing edges wich are not candidate for work edge
|
|
// ( they have other nearest edges belonging to the work face)
|
|
for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
|
|
Standard_Integer index1 = seqNotCandidate.Value(k);
|
|
TopoDS_Shape edge = sequenceSec.Value(index1);
|
|
TopTools_SequenceOfShape tmpSeq;
|
|
tmpSeq.Append(edge);
|
|
for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++)
|
|
tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
|
|
|
|
Standard_Integer lengSec = tmpSeq.Length();
|
|
TColStd_Array1OfBoolean tabForward(1,lengSec);
|
|
TColStd_Array1OfReal tabDist(1,lengSec);
|
|
TColStd_Array1OfReal arrLen(1,lengSec);
|
|
TColStd_Array1OfReal tabMinDist(1,lengSec);
|
|
for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++)
|
|
tabDist(i1) =-1;
|
|
|
|
EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
|
|
if(k == 1) {
|
|
for(Standard_Integer n = 1; n < lengSec; n++) {
|
|
if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
|
|
MapIndex.Add(n);
|
|
continue;
|
|
}
|
|
TotTabDist(k,n) = tabDist(n+1 );
|
|
seqForward.Append(tabForward(n+1) ? 1:0);
|
|
}
|
|
}
|
|
else {
|
|
for(Standard_Integer n = 1; n < lengSec; n++) {
|
|
if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
|
|
if(tabDist(n+1) < TotTabDist(1,n)) {
|
|
MapIndex.Add(n);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
Standard_Integer i2 = seqIndCandidate.Length();
|
|
for( ; i2 >=1 ; i2--)
|
|
{
|
|
if(MapIndex.Contains(i2))
|
|
{
|
|
seqIndCandidate.Remove(i2);
|
|
seqOrientations.Remove(i2);
|
|
}
|
|
|
|
}
|
|
//for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) {
|
|
// seqIndCandidate.Remove(IMap.Key());
|
|
// seqOrientations.Remove(IMap.Key());
|
|
//}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FindCandidates
|
|
//purpose : internal use
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections,
|
|
TColStd_IndexedMapOfInteger& mapReference,
|
|
TColStd_SequenceOfInteger& seqCandidates,
|
|
TColStd_SequenceOfInteger& seqOrientations)
|
|
{
|
|
Standard_Integer i, nbSections = seqSections.Length();
|
|
if(nbSections <= 1)
|
|
return Standard_False;
|
|
// Retrieve last reference index
|
|
Standard_Integer indReference = mapReference(mapReference.Extent());
|
|
Standard_Integer nbCandidates = 0;
|
|
TopTools_MapOfShape Faces1;
|
|
//if (nbSections > 1) {
|
|
|
|
TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference));
|
|
|
|
// Retrieve faces for reference section
|
|
|
|
{ //szv: Use brackets to destroy local variables
|
|
TopoDS_Shape bnd = Edge1;
|
|
if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
|
|
if (myBoundFaces.Contains(bnd)) {
|
|
TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd));
|
|
for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value());
|
|
}
|
|
}
|
|
|
|
// Check merging conditions for candidates and remove unsatisfactory
|
|
TopTools_SequenceOfShape seqSectionsNew;
|
|
TColStd_SequenceOfInteger seqCandidatesNew;
|
|
for (i = 1; i <= nbSections; i++) {
|
|
if (i == indReference) {
|
|
seqSectionsNew.Prepend(Edge1);
|
|
seqCandidatesNew.Prepend(i);
|
|
}
|
|
else {
|
|
const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i));
|
|
seqSectionsNew.Append(Edge2);
|
|
seqCandidatesNew.Append(i);
|
|
}
|
|
}
|
|
|
|
Standard_Integer nbSectionsNew = seqSectionsNew.Length();
|
|
if (nbSectionsNew > 1) {
|
|
|
|
// Evaluate distances between reference and other sections
|
|
TColStd_Array1OfBoolean arrForward(1,nbSectionsNew);
|
|
TColStd_Array1OfReal arrDistance(1,nbSectionsNew);
|
|
TColStd_Array1OfReal arrLen(1,nbSectionsNew);
|
|
TColStd_Array1OfReal arrMinDist(1,nbSectionsNew);
|
|
EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1);
|
|
|
|
// Fill sequence of candidate indices sorted by distance
|
|
for (i = 2; i <= nbSectionsNew; i++) {
|
|
Standard_Real aMaxDist = arrDistance(i);
|
|
if (aMaxDist >= 0.0 && aMaxDist <= myTolerance && arrLen(i) > myMinTolerance) {
|
|
|
|
// Reference section is connected to section #i
|
|
Standard_Boolean isInserted = Standard_False;
|
|
Standard_Integer j, ori = (arrForward(i)? 1 : 0);
|
|
for (j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) {
|
|
Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j));
|
|
|
|
if( aDelta < Precision::Confusion()) {
|
|
|
|
if(fabs(aDelta) > RealSmall() ||
|
|
arrMinDist(i) < arrMinDist(seqCandidates.Value(j)))
|
|
{
|
|
seqCandidates.InsertBefore(j,i);
|
|
seqOrientations.InsertBefore(j,ori);
|
|
isInserted = Standard_True;
|
|
}
|
|
}
|
|
}
|
|
if (!isInserted) {
|
|
seqCandidates.Append(i);
|
|
seqOrientations.Append(ori);
|
|
}
|
|
}
|
|
}
|
|
|
|
nbCandidates = seqCandidates.Length();
|
|
if (!nbCandidates)
|
|
return Standard_False; // Section has no candidates to merge
|
|
|
|
// Replace candidate indices
|
|
|
|
for (i = 1; i <= nbCandidates; i++)
|
|
seqCandidates(i) = seqCandidatesNew(seqCandidates(i));
|
|
|
|
}
|
|
|
|
if (!nbCandidates) return Standard_False; // Section has no candidates to merge
|
|
|
|
if (myNonmanifold && nbCandidates >1) {
|
|
TColStd_SequenceOfInteger seqNewCandidates;
|
|
TColStd_SequenceOfInteger seqOrientationsNew;
|
|
seqCandidates.Prepend(1);
|
|
seqOrientations.Prepend(1);
|
|
for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) {
|
|
AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1));
|
|
if(k == 1 && !seqCandidates.Length()) return Standard_False;
|
|
if(seqCandidates.Length()) {
|
|
seqNewCandidates.Append(seqCandidates.First());
|
|
seqOrientationsNew.Append(seqOrientations.First());
|
|
}
|
|
}
|
|
seqCandidates.Prepend(seqNewCandidates);
|
|
seqOrientations.Prepend(seqOrientationsNew);
|
|
return Standard_True;
|
|
}
|
|
else {
|
|
|
|
// For manifold case leave only one candidate from equidistant candidates
|
|
/*Standard_Integer minIndex = seqCandidateIndex.First();
|
|
Standard_Real minDistance = arrDistance(minIndex);
|
|
|
|
// Find equidistant candidates
|
|
TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1);
|
|
for (i = 2; i <= nbCandidates; i++) {
|
|
Standard_Integer index = seqCandidateIndex(i);
|
|
if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion())
|
|
seqEqDistantIndex.Append(index);
|
|
}
|
|
|
|
Standard_Integer eqLen = seqEqDistantIndex.Length();
|
|
if (eqLen > 2) {
|
|
|
|
// Fill map of faces which equidistant sections belong to
|
|
TopTools_MapOfShape mapFace;
|
|
for (i = 1; i <= eqLen; i++) {
|
|
Standard_Integer index = seqEqDistantIndex.Value(i);
|
|
if (isCandidate(index)) {
|
|
mapFace.Add(arrFace(index));
|
|
}
|
|
}
|
|
|
|
// Non Manifold case
|
|
// Edges are merged by pair among a face continuity C1 criterion
|
|
if (mapFace.Extent() == eqLen) {
|
|
|
|
tabDist.Init(-1);
|
|
tabMinInd.Init(-1);
|
|
min=10000000.;
|
|
//indMin = -1;
|
|
Standard_Integer indMin = -1;// To check if the edge can be merged.
|
|
// Computation of distances between the edges.
|
|
TopTools_SequenceOfShape seqSh;
|
|
Standard_Integer nbInd = EqDistSeq.Length();
|
|
TColStd_Array1OfBoolean tmptabForward(1,nbInd);
|
|
seqSh.Append(sequenceSec.Value(1));
|
|
for (j = 2; j <= EqDistSeq.Length(); j++) {
|
|
Standard_Integer index = EqDistSeq.Value(j);
|
|
tmptabForward(j) = tabForward(index);
|
|
seqSh.Append(sequenceSec.Value(index));
|
|
}
|
|
|
|
EvaluateAngulars(seqSh, tmptabForward, tabDist,1);
|
|
|
|
for(j=2; j <= seqSh.Length(); j++) {
|
|
if (tabDist(j) > -1.) { // if edge(j) is connected to edge(i)
|
|
if (min > tabDist(j)) {
|
|
min = tabDist(j);
|
|
indMin = j;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j);
|
|
if (indMin > 0) {
|
|
seqSh.Remove(indMin);
|
|
for(j =2; j <= tmpSeq.Length(); ) {
|
|
TopoDS_Shape sh = tmpSeq.Value(j);
|
|
Standard_Boolean isRem = Standard_False;
|
|
for(Standard_Integer k = 1; k<= seqSh.Length();k++) {
|
|
if(seqSh.Value(k) == sh) {
|
|
isRem = Standard_True;
|
|
break;
|
|
}
|
|
}
|
|
if(isRem) {
|
|
tmpSeq.Remove(j);
|
|
tabMinForward.Remove(j); // = -1;
|
|
}
|
|
else j++;
|
|
}
|
|
}
|
|
}
|
|
}*/
|
|
|
|
// Find the best approved candidate
|
|
while (nbCandidates) {
|
|
// Retrieve first candidate
|
|
Standard_Integer indCandidate = seqCandidates.First();
|
|
// Candidate is approved if it is in the map
|
|
if (mapReference.Contains(indCandidate)) break;
|
|
// Find candidates for candidate #indCandidate
|
|
mapReference.Add(indCandidate); // Push candidate in the map
|
|
TColStd_SequenceOfInteger seqCandidates1, seqOrientations1;
|
|
Standard_Boolean isFound =
|
|
FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
|
|
mapReference.RemoveLast(); // Pop candidate from the map
|
|
if (isFound) isFound = (seqCandidates1.Length() > 0);
|
|
if (isFound) {
|
|
Standard_Integer indCandidate1 = seqCandidates1.First();
|
|
// If indReference is the best candidate for indCandidate
|
|
// then indCandidate is the best candidate for indReference
|
|
if (indCandidate1 == indReference) break;
|
|
// If some other reference in the map is the best candidate for indCandidate
|
|
// then assume that reference is the best candidate for indReference
|
|
if (mapReference.Contains(indCandidate1)) {
|
|
seqCandidates.Prepend(indCandidate1);
|
|
nbCandidates++;
|
|
break;
|
|
}
|
|
isFound = Standard_False;
|
|
}
|
|
if (!isFound) {
|
|
// Remove candidate #1
|
|
seqCandidates.Remove(1);
|
|
seqOrientations.Remove(1);
|
|
nbCandidates--;
|
|
}
|
|
}
|
|
}
|
|
//gka
|
|
if(nbCandidates > 0)
|
|
{
|
|
Standard_Integer anInd = seqCandidates.Value(1);
|
|
TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
|
|
TopoDS_Shape bnd = Edge2;
|
|
if (mySectionBound.IsBound(bnd))
|
|
bnd = mySectionBound(bnd);
|
|
//gka
|
|
if (myBoundFaces.Contains(bnd)) {
|
|
Standard_Boolean isOK = Standard_True;
|
|
TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
|
|
for (; itf2.More() && isOK; itf2.Next()) {
|
|
const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
|
|
// Check whether condition is satisfied
|
|
isOK = !Faces1.Contains(Face2);
|
|
if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
|
|
}
|
|
if(!isOK)
|
|
return Standard_False;
|
|
}
|
|
}
|
|
return (nbCandidates > 0);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Constructor
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
|
|
const Standard_Boolean optionSewing,
|
|
const Standard_Boolean optionAnalysis,
|
|
const Standard_Boolean optionCutting,
|
|
const Standard_Boolean optionNonmanifold)
|
|
{
|
|
myReShape = new BRepTools_ReShape;
|
|
Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Init
|
|
//purpose : Initialise Talerance, and options sewing, faceAnalysis and cutting
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
|
|
const Standard_Boolean optionSewing,
|
|
const Standard_Boolean optionAnalysis,
|
|
const Standard_Boolean optionCutting,
|
|
const Standard_Boolean optionNonmanifold)
|
|
{
|
|
// Set tolerance and Perform options
|
|
myTolerance = Max (tolerance, Precision::Confusion());
|
|
mySewing = optionSewing;
|
|
myAnalysis = optionAnalysis;
|
|
myCutting = optionCutting;
|
|
myNonmanifold = optionNonmanifold;
|
|
// Set min and max tolerances
|
|
myMinTolerance = myTolerance * 1e-4; //szv: proposal
|
|
if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
|
|
myMaxTolerance = Precision::Infinite();
|
|
// Set other modes
|
|
myFaceMode = Standard_True;
|
|
myFloatingEdgesMode = Standard_False;
|
|
//myCuttingFloatingEdgesMode = Standard_False; //gka
|
|
mySameParameterMode = Standard_True;
|
|
myLocalToleranceMode = Standard_False;
|
|
mySewedShape.Nullify();
|
|
// Load empty shape
|
|
Load(TopoDS_Shape());
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Load
|
|
//purpose : Loads the context shape
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
|
|
{
|
|
myReShape->Clear();
|
|
if (theShape.IsNull()) myShape.Nullify();
|
|
else myShape = myReShape->Apply(theShape);
|
|
mySewedShape.Nullify();
|
|
// Nullify flags and counters
|
|
myNbShapes = myNbEdges = myNbVertices = 0;
|
|
// Clear all maps
|
|
myOldShapes.Clear();
|
|
//myOldFaces.Clear();
|
|
myDegenerated.Clear();
|
|
myFreeEdges.Clear();
|
|
myMultipleEdges.Clear();
|
|
myContigousEdges.Clear();
|
|
myContigSecBound.Clear();
|
|
myBoundFaces.Clear();
|
|
myBoundSections.Clear();
|
|
myVertexNode.Clear();
|
|
myVertexNodeFree.Clear();
|
|
myNodeSections.Clear();
|
|
myCuttingNode.Clear();
|
|
mySectionBound.Clear();
|
|
myLittleFace.Clear();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Add
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
|
|
{
|
|
if (aShape.IsNull()) return;
|
|
TopoDS_Shape oShape = myReShape->Apply(aShape);
|
|
myOldShapes.Add(aShape,oShape);
|
|
myNbShapes = myOldShapes.Extent();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Perform
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
#ifdef OCCT_DEBUG
|
|
#include <OSD_Timer.hxx>
|
|
#endif
|
|
|
|
void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI)
|
|
{
|
|
const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
|
|
Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1);
|
|
#ifdef OCCT_DEBUG
|
|
Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
|
|
OSD_Chronometer chr_total, chr_local;
|
|
chr_total.Reset();
|
|
chr_total.Start();
|
|
#endif
|
|
|
|
// face analysis
|
|
if (myAnalysis)
|
|
{
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Begin face analysis..." << endl;
|
|
chr_local.Reset();
|
|
chr_local.Start();
|
|
#endif
|
|
FaceAnalysis (thePI);
|
|
if (!aPS.More())
|
|
return;
|
|
aPS.Next();
|
|
#ifdef OCCT_DEBUG
|
|
chr_local.Stop();
|
|
chr_local.Show(t_analysis);
|
|
cout << "Face analysis finished after " << t_analysis << " s" << endl;
|
|
#endif
|
|
}
|
|
|
|
if (myNbShapes || !myShape.IsNull())
|
|
{
|
|
|
|
FindFreeBoundaries();
|
|
|
|
if (myBoundFaces.Extent())
|
|
{
|
|
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Begin vertices assembling..." << endl;
|
|
chr_local.Reset();
|
|
chr_local.Start();
|
|
#endif
|
|
VerticesAssembling (thePI);
|
|
if (!aPS.More())
|
|
return;
|
|
aPS.Next();
|
|
#ifdef OCCT_DEBUG
|
|
chr_local.Stop();
|
|
chr_local.Show(t_assembling);
|
|
cout << "Vertices assembling finished after " << t_assembling << " s" << endl;
|
|
#endif
|
|
if (myCutting)
|
|
{
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Begin cutting..." << endl;
|
|
chr_local.Reset();
|
|
chr_local.Start();
|
|
#endif
|
|
Cutting (thePI);
|
|
if (!aPS.More())
|
|
return;
|
|
aPS.Next();
|
|
#ifdef OCCT_DEBUG
|
|
chr_local.Stop();
|
|
chr_local.Show(t_cutting);
|
|
cout << "Cutting finished after " << t_cutting << " s" << endl;
|
|
#endif
|
|
}
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Begin merging..." << endl;
|
|
chr_local.Reset();
|
|
chr_local.Start();
|
|
#endif
|
|
Merging (Standard_True, thePI);
|
|
if (!aPS.More())
|
|
return;
|
|
aPS.Next();
|
|
#ifdef OCCT_DEBUG
|
|
chr_local.Stop();
|
|
chr_local.Show(t_merging);
|
|
cout << "Merging finished after " << t_merging << " s" << endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
aPS.Next( 1, Handle(TCollection_HAsciiString)());
|
|
if (myCutting)
|
|
aPS.Next( 1, Handle(TCollection_HAsciiString)());
|
|
aPS.Next( 1, Handle(TCollection_HAsciiString)());
|
|
if (!aPS.More())
|
|
return;
|
|
}
|
|
|
|
if (mySewing)
|
|
{
|
|
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Creating sewed shape..." << endl;
|
|
#endif
|
|
// examine the multiple edges if any and process sameparameter for edges if necessary
|
|
EdgeProcessing (thePI);
|
|
if (!aPS.More())
|
|
return;
|
|
CreateSewedShape();
|
|
if (!aPS.More())
|
|
{
|
|
mySewedShape.Nullify();
|
|
return;
|
|
}
|
|
if (mySameParameterMode && myFaceMode)
|
|
SameParameterShape();
|
|
if (!aPS.More())
|
|
{
|
|
mySewedShape.Nullify();
|
|
return;
|
|
}
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Sewed shape created" << endl;
|
|
#endif
|
|
}
|
|
|
|
// create edge informations for output
|
|
CreateOutputInformations();
|
|
if (!aPS.More())
|
|
{
|
|
mySewedShape.Nullify();
|
|
return;
|
|
}
|
|
}
|
|
#ifdef OCCT_DEBUG
|
|
chr_total.Stop();
|
|
chr_total.Show(t_total);
|
|
cout << "Sewing finished!" << endl;
|
|
cout << " analysis time : " << t_analysis << " s" << endl;
|
|
cout << " assembling time : " << t_assembling << " s" << endl;
|
|
cout << " cutting time : " << t_cutting << " s" << endl;
|
|
cout << " merging time : " << t_merging << " s" << endl;
|
|
cout << "Total time : " << t_total << " s" << endl;
|
|
#endif
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SewedShape
|
|
//purpose : give the sewed shape
|
|
// if a null shape, reasons:
|
|
// -- no useable input shapes : all input shapes are degenerated
|
|
// -- has multiple edges
|
|
//=======================================================================
|
|
|
|
const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const
|
|
{
|
|
return mySewedShape;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : NbFreeEdges
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const
|
|
{
|
|
return myFreeEdges.Extent();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FreeEdge
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const
|
|
{
|
|
Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge");
|
|
return TopoDS::Edge(myFreeEdges(index));
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : NbMultipleEdges
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const
|
|
{
|
|
return myMultipleEdges.Extent();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : MultipleEdge
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const
|
|
{
|
|
Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge");
|
|
return TopoDS::Edge(myMultipleEdges(index));
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : NbContigousEdges
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const
|
|
{
|
|
return myContigousEdges.Extent();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ContigousEdge
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const
|
|
{
|
|
Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge");
|
|
return TopoDS::Edge(myContigousEdges.FindKey(index));
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ContigousEdgeCouple
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const
|
|
{
|
|
Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple");
|
|
return myContigousEdges(index);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsSectionBound
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const
|
|
{
|
|
if(myContigSecBound.IsBound(section)) {
|
|
return Standard_True;
|
|
}
|
|
else {
|
|
return Standard_False;
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SectionToBoundary
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const
|
|
{
|
|
Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary");
|
|
return TopoDS::Edge(myContigSecBound(section));
|
|
}
|
|
//=======================================================================
|
|
//function : NbDeletedFaces
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const
|
|
{
|
|
return myLittleFace.Extent();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : DeletedFace
|
|
//purpose :
|
|
//=======================================================================
|
|
const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const
|
|
{
|
|
Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace");
|
|
return TopoDS::Face(myLittleFace(index));
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : NbDegeneratedShapes
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const
|
|
{
|
|
return myDegenerated.Extent();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : DegeneratedShape
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const
|
|
{
|
|
Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape");
|
|
return myDegenerated(index);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsDegenerated
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const
|
|
{
|
|
TopoDS_Shape NewShape = myReShape->Apply(aShape);
|
|
// Degenerated face
|
|
if (aShape.ShapeType() == TopAbs_FACE)
|
|
return NewShape.IsNull();
|
|
if (NewShape.IsNull()) return Standard_False;
|
|
// Degenerated edge
|
|
if (NewShape.ShapeType() == TopAbs_EDGE)
|
|
return BRep_Tool::Degenerated(TopoDS::Edge(NewShape));
|
|
// Degenerated wire
|
|
if (NewShape.ShapeType() == TopAbs_WIRE) {
|
|
Standard_Boolean isDegenerated = Standard_True;
|
|
for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next())
|
|
isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value()));
|
|
return isDegenerated;
|
|
}
|
|
return Standard_False;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsModified
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const
|
|
{
|
|
TopoDS_Shape NewShape = aShape;
|
|
if (myOldShapes.Contains(aShape))
|
|
NewShape = myOldShapes.FindFromKey(aShape);
|
|
if(!NewShape.IsSame(aShape)) return Standard_True;
|
|
return Standard_False;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Modified
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const
|
|
{
|
|
if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape);
|
|
//if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape);
|
|
return aShape;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsModifiedSubShape
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const
|
|
{
|
|
TopoDS_Shape NewShape = myReShape->Apply(aShape);
|
|
if(!NewShape.IsSame(aShape)) return Standard_True;
|
|
return Standard_False;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ModifiedSubShape
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const
|
|
{
|
|
return myReShape->Apply(aShape);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Dump
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::Dump() const
|
|
{
|
|
Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0;
|
|
TopTools_MapOfShape mapVertices, mapEdges;
|
|
for (i = 1; i <= NbBounds; i++) {
|
|
TopoDS_Shape bound = myBoundFaces.FindKey(i);
|
|
if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent();
|
|
else NbSections++;
|
|
TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
TopoDS_Edge E = TopoDS::Edge(aExp.Current());
|
|
mapEdges.Add(E);
|
|
TopoDS_Vertex V1, V2;
|
|
TopExp::Vertices(E,V1,V2);
|
|
mapVertices.Add(V1);
|
|
mapVertices.Add(V2);
|
|
}
|
|
}
|
|
cout << " " << endl;
|
|
cout << " Informations " << endl;
|
|
cout << " ===========================================================" << endl;
|
|
cout << " " << endl;
|
|
cout << " Number of input shapes : " << myOldShapes.Extent() << endl;
|
|
cout << " Number of actual shapes : " << myNbShapes << endl;
|
|
cout << " Number of Bounds : " << NbBounds << endl;
|
|
cout << " Number of Sections : " << NbSections << endl;
|
|
cout << " Number of Edges : " << mapEdges.Extent() << endl;
|
|
cout << " Number of Vertices : " << myNbVertices << endl;
|
|
cout << " Number of Nodes : " << mapVertices.Extent() << endl;
|
|
cout << " Number of Free Edges : " << myFreeEdges.Extent() << endl;
|
|
cout << " Number of Contigous Edges : " << myContigousEdges.Extent() << endl;
|
|
cout << " Number of Multiple Edges : " << myMultipleEdges.Extent() << endl;
|
|
cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl;
|
|
cout << " ===========================================================" << endl;
|
|
cout << " " << endl;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FaceAnalysis
|
|
//purpose : Remove
|
|
// Modifies:
|
|
// myNbShapes
|
|
// myOldShapes
|
|
//
|
|
// Constructs:
|
|
// myDegenerated
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI)
|
|
{
|
|
if (!myShape.IsNull() && myOldShapes.IsEmpty()) {
|
|
Add(myShape);
|
|
myShape.Nullify();
|
|
}
|
|
|
|
BRep_Builder B;
|
|
TopTools_MapOfShape SmallEdges;
|
|
TopTools_DataMapOfShapeListOfShape GluedVertices;
|
|
Standard_Integer i = 1;
|
|
Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1);
|
|
for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) {
|
|
for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) {
|
|
|
|
// Retrieve current face
|
|
TopoDS_Shape aTmpShape = fexp.Current(); //for porting
|
|
TopoDS_Face face = TopoDS::Face(aTmpShape);
|
|
Standard_Integer nbEdges = 0, nbSmall = 0;
|
|
|
|
// Build replacing face
|
|
aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting
|
|
TopoDS_Face nface = TopoDS::Face(aTmpShape);
|
|
Standard_Boolean isFaceChanged = Standard_False;
|
|
|
|
TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD));
|
|
for (; witer.More(); witer.Next()) {
|
|
|
|
// Retrieve current wire
|
|
aTmpShape = witer.Value(); //for porting
|
|
if( aTmpShape.ShapeType() != TopAbs_WIRE) continue;
|
|
TopoDS_Wire wire = TopoDS::Wire(aTmpShape);
|
|
|
|
// Build replacing wire
|
|
aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD);
|
|
TopoDS_Wire nwire = TopoDS::Wire(aTmpShape);
|
|
Standard_Boolean isWireChanged = Standard_False;
|
|
|
|
TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD));
|
|
for (; eiter.More(); eiter.Next()) {
|
|
|
|
// Retrieve current edge
|
|
aTmpShape = eiter.Value(); //for porting
|
|
TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
|
|
nbEdges++;
|
|
|
|
// Process degenerated edge
|
|
if (BRep_Tool::Degenerated(edge)) {
|
|
B.Add(nwire,edge); // Old edge kept
|
|
myDegenerated.Add(edge);
|
|
nbSmall++;
|
|
continue;
|
|
}
|
|
|
|
Standard_Boolean isSmall = SmallEdges.Contains(edge);
|
|
if (!isSmall) {
|
|
|
|
// Check for small edge
|
|
Standard_Real first, last;
|
|
Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last);
|
|
if (c3d.IsNull()) {
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl;
|
|
#endif
|
|
}
|
|
else {
|
|
// Evaluate curve compactness
|
|
const Standard_Integer npt = 5;
|
|
gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5);
|
|
Standard_Real dist, maxdist = 0.0;
|
|
Standard_Real delta = (last - first)/(npt - 1);
|
|
for (Standard_Integer idx = 0; idx < npt; idx++) {
|
|
dist = cp.Distance(c3d->Value(first + idx*delta));
|
|
if (maxdist < dist) maxdist = dist;
|
|
}
|
|
isSmall = (2.*maxdist <= MinTolerance());
|
|
/*try {
|
|
GeomAdaptor_Curve cAdapt(c3d);
|
|
Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last);
|
|
isSmall = (length <= MinTolerance());
|
|
}
|
|
catch (Standard_Failure) {
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Warning: Possibly small edge can be sewed: ";
|
|
Standard_Failure::Caught()->Print(cout); cout << endl;
|
|
#endif
|
|
}*/
|
|
}
|
|
|
|
if (isSmall) {
|
|
|
|
// Store small edge in the map
|
|
SmallEdges.Add(edge);
|
|
|
|
TopoDS_Vertex v1, v2;
|
|
TopExp::Vertices(edge,v1,v2);
|
|
TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2);
|
|
|
|
// Store glued vertices
|
|
if (!nv1.IsSame(v1)) {
|
|
TopTools_ListOfShape& vlist1 = GluedVertices(nv1);
|
|
// First vertex was already glued
|
|
if (!nv2.IsSame(v2)) {
|
|
// Merge lists of glued vertices
|
|
if (!nv1.IsSame(nv2)) {
|
|
TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2));
|
|
for (; liter.More(); liter.Next()) {
|
|
TopoDS_Shape v = liter.Value();
|
|
myReShape->Replace(v,nv1.Oriented(v.Orientation()));
|
|
vlist1.Append(v);
|
|
}
|
|
GluedVertices.UnBind(nv2);
|
|
}
|
|
}
|
|
else {
|
|
// Add second vertex to the existing list
|
|
vlist1.Append(v2);
|
|
myReShape->Replace(v2,nv1.Oriented(v2.Orientation()));
|
|
}
|
|
}
|
|
else if (!nv2.IsSame(v2)) {
|
|
// Add first vertex to the existing list
|
|
GluedVertices(nv2).Append(v1);
|
|
myReShape->Replace(v1,nv2.Oriented(v1.Orientation()));
|
|
}
|
|
else if (!v1.IsSame(v2)) {
|
|
// Record new glued vertices
|
|
TopoDS_Vertex nv;
|
|
B.MakeVertex(nv);
|
|
TopTools_ListOfShape vlist;
|
|
vlist.Append(v1);
|
|
vlist.Append(v2);
|
|
GluedVertices.Bind(nv,vlist);
|
|
myReShape->Replace(v1,nv.Oriented(v1.Orientation()));
|
|
myReShape->Replace(v2,nv.Oriented(v2.Orientation()));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Replace small edge
|
|
if (isSmall) {
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl;
|
|
#endif
|
|
nbSmall++;
|
|
// Create new degenerated edge
|
|
aTmpShape = edge.Oriented(TopAbs_FORWARD);
|
|
TopoDS_Edge fedge = TopoDS::Edge(aTmpShape);
|
|
Standard_Real pfirst, plast;
|
|
Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast);
|
|
if (!c2d.IsNull()) {
|
|
TopoDS_Edge nedge;
|
|
B.MakeEdge(nedge);
|
|
B.UpdateEdge(nedge,c2d,face,Precision::Confusion());
|
|
B.Range(nedge,pfirst,plast);
|
|
B.Degenerated(nedge,Standard_True);
|
|
TopoDS_Vertex v1, v2;
|
|
TopExp::Vertices(fedge,v1,v2);
|
|
B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation()));
|
|
B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation()));
|
|
B.Add(nwire,nedge.Oriented(edge.Orientation()));
|
|
myDegenerated.Add(nedge);
|
|
}
|
|
isWireChanged = Standard_True;
|
|
}
|
|
else B.Add(nwire,edge); // Old edge kept
|
|
}
|
|
|
|
// Record wire in the new face
|
|
if (isWireChanged) {
|
|
B.Add(nface,nwire.Oriented(wire.Orientation()));
|
|
isFaceChanged = Standard_True;
|
|
}
|
|
else B.Add(nface,wire);
|
|
}
|
|
|
|
// Remove small face
|
|
if (nbSmall == nbEdges) {
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Warning: Small face removed by FaceAnalysis" << endl;
|
|
#endif
|
|
myLittleFace.Add(face);
|
|
myReShape->Remove(face);
|
|
}
|
|
else if (isFaceChanged) {
|
|
|
|
myReShape->Replace(face,nface.Oriented(face.Orientation()));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update glued vertices
|
|
TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices);
|
|
for (; miter.More(); miter.Next()) {
|
|
TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key());
|
|
gp_XYZ coord(0.,0.,0.);
|
|
Standard_Integer nbPoints = 0;
|
|
const TopTools_ListOfShape& vlist = miter.Value();
|
|
TopTools_ListIteratorOfListOfShape liter1(vlist);
|
|
for (; liter1.More(); liter1.Next()) {
|
|
coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ();
|
|
nbPoints++;
|
|
}
|
|
if (nbPoints) {
|
|
gp_Pnt vp(coord / nbPoints);
|
|
Standard_Real tol = 0.0, mtol = 0.0;
|
|
TopTools_ListIteratorOfListOfShape liter2(vlist);
|
|
for (; liter2.More(); liter2.Next()) {
|
|
Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value()));
|
|
if (mtol < vtol) mtol = vtol;
|
|
vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value())));
|
|
if (tol < vtol) tol = vtol;
|
|
}
|
|
B.UpdateVertex(vnew,vp,tol+mtol);
|
|
}
|
|
}
|
|
|
|
// Update input shapes
|
|
for (i = 1; i <= myOldShapes.Extent(); i++)
|
|
myOldShapes(i) = myReShape->Apply(myOldShapes(i));
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : FindFreeBoundaries
|
|
//purpose : Constructs :
|
|
// myBoundFaces (bound = list of faces) - REFERENCE
|
|
// myVertexNode (vertex = node)
|
|
// myVertexNodeFree (floating vertex = node)
|
|
//
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::FindFreeBoundaries()
|
|
{
|
|
// Take into account the context shape if needed
|
|
TopTools_IndexedMapOfShape NewShapes;
|
|
if (!myShape.IsNull()) {
|
|
if (myOldShapes.IsEmpty()) {
|
|
Add(myShape);
|
|
myShape.Nullify();
|
|
}
|
|
else {
|
|
TopoDS_Shape newShape = myReShape->Apply(myShape);
|
|
if (!newShape.IsNull()) NewShapes.Add(newShape);
|
|
}
|
|
}
|
|
// Create map Edge -> Faces
|
|
TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces;
|
|
Standard_Integer i, nbShapes = myOldShapes.Extent();
|
|
for (i = 1; i <= nbShapes; i++) {
|
|
// Retrieve new shape
|
|
TopoDS_Shape shape = myOldShapes(i);
|
|
if (shape.IsNull()) continue;
|
|
NewShapes.Add(shape);
|
|
// Explore shape to find all boundaries
|
|
for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) {
|
|
TopoDS_Shape edge = eExp.Current();
|
|
if (!EdgeFaces.Contains(edge)) {
|
|
TopTools_ListOfShape listFaces;
|
|
EdgeFaces.Add(edge,listFaces);
|
|
}
|
|
}
|
|
}
|
|
// Fill map Edge -> Faces
|
|
nbShapes = NewShapes.Extent();
|
|
TopTools_MapOfShape mapFaces;
|
|
for (i = 1; i <= nbShapes; i++) {
|
|
// Explore shape to find all faces
|
|
TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE);
|
|
for (; fExp.More(); fExp.Next()) {
|
|
TopoDS_Shape face = fExp.Current();
|
|
if(mapFaces.Contains(face)) continue;
|
|
else
|
|
mapFaces.Add(face);
|
|
// Explore face to find all boundaries
|
|
for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
|
|
if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
|
|
for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {
|
|
|
|
TopoDS_Shape edge = aIIe.Value();
|
|
|
|
if (EdgeFaces.Contains(edge)) {
|
|
EdgeFaces.ChangeFromKey(edge).Append(face);
|
|
//TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge);
|
|
//Standard_Boolean isContained = Standard_False;
|
|
//TopTools_ListIteratorOfListOfShape itf(listFaces);
|
|
//for (; itf.More() && !isContained; itf.Next())
|
|
// isContained = face.IsSame(itf.Value());
|
|
//if (!isContained) listFaces.Append(face);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Find free boundaries
|
|
nbShapes = EdgeFaces.Extent();
|
|
for (i = 1; i <= nbShapes; i++) {
|
|
TopTools_ListOfShape& listFaces = EdgeFaces(i);
|
|
Standard_Integer nbFaces = listFaces.Extent();
|
|
TopoDS_Shape edge = EdgeFaces.FindKey(i);
|
|
if(edge.Orientation() == TopAbs_INTERNAL)
|
|
continue;
|
|
Standard_Boolean isSeam = Standard_False;
|
|
if (nbFaces == 1) {
|
|
TopoDS_Face face = TopoDS::Face(listFaces.First());
|
|
isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face);
|
|
if (isSeam) {
|
|
///Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
|
|
//isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf));
|
|
//if(!isSeam) {
|
|
BRep_Builder aB;
|
|
TopoDS_Shape anewEdge = edge.EmptyCopied();
|
|
TopoDS_Iterator aItV(edge);
|
|
for( ; aItV.More() ; aItV.Next())
|
|
aB.Add(anewEdge,aItV.Value());
|
|
|
|
|
|
|
|
Standard_Real first2d,last2d;
|
|
Handle(Geom2d_Curve) c2dold =
|
|
BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d);
|
|
|
|
Handle(Geom2d_Curve) c2d;
|
|
BRep_Builder B;
|
|
B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0);
|
|
B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0);
|
|
|
|
Standard_Real aFirst, aLast;
|
|
BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast);
|
|
aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast);
|
|
aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d);
|
|
myReShape->Replace(edge,anewEdge);
|
|
edge = anewEdge;
|
|
|
|
//}
|
|
isSeam = Standard_False;
|
|
}
|
|
}
|
|
Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces);
|
|
Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam)));
|
|
if (isBound || isBoundFloat) {
|
|
// Ignore degenerated edge
|
|
if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue;
|
|
// Ignore edge with internal vertices
|
|
// Standard_Integer nbVtx = 0;
|
|
// for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++;
|
|
// if (nbVtx != 2) continue;
|
|
// Add to BoundFaces
|
|
TopTools_ListOfShape listFacesCopy;
|
|
listFacesCopy.Append(listFaces);
|
|
myBoundFaces.Add(edge,listFacesCopy);
|
|
// Process edge vertices
|
|
TopoDS_Vertex vFirst, vLast;
|
|
TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast);
|
|
if(vFirst.IsNull() || vLast.IsNull()) continue;
|
|
if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL)
|
|
continue;
|
|
if (isBound) {
|
|
// Add to VertexNode
|
|
if (!myVertexNode.Contains(vFirst))
|
|
myVertexNode.Add(vFirst,vFirst);
|
|
if (!myVertexNode.Contains(vLast))
|
|
myVertexNode.Add(vLast,vLast);
|
|
}
|
|
else {
|
|
// Add to VertexNodeFree
|
|
if (!myVertexNodeFree.Contains(vFirst))
|
|
myVertexNodeFree.Add(vFirst,vFirst);
|
|
if (!myVertexNodeFree.Contains(vLast))
|
|
myVertexNodeFree.Add(vLast,vLast);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : VerticesAssembling
|
|
//purpose : Modifies :
|
|
// myVertexNode (nodes glued)
|
|
// myVertexNodeFree (nodes glued)
|
|
// myNodeSections (lists of sections merged for glued nodes)
|
|
//
|
|
//=======================================================================
|
|
|
|
static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode,
|
|
const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices,
|
|
TopTools_IndexedDataMapOfShapeShape& aVertexNode,
|
|
TopTools_DataMapOfShapeListOfShape& aNodeEdges)
|
|
{
|
|
Standard_Integer i, nbNearest = NodeNearestNode.Extent();
|
|
|
|
// Create new nodes
|
|
BRep_Builder B;
|
|
TopTools_DataMapOfShapeShape OldNodeNewNode;
|
|
TopTools_DataMapOfShapeListOfShape NewNodeOldNodes;
|
|
for (i = 1; i <= nbNearest; i++) {
|
|
// Retrieve a pair of nodes to merge
|
|
TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i);
|
|
TopoDS_Shape oldnode2 = NodeNearestNode(i);
|
|
// Second node should also be in the map
|
|
if (!NodeNearestNode.Contains(oldnode2)) continue;
|
|
// Get new node for old node #1
|
|
if (OldNodeNewNode.IsBound(oldnode1)) {
|
|
TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1);
|
|
if (OldNodeNewNode.IsBound(oldnode2)) {
|
|
TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
|
|
if (!newnode1.IsSame(newnode2)) {
|
|
// Change data for new node #2
|
|
TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1);
|
|
TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2));
|
|
for (; itn.More(); itn.Next()) {
|
|
TopoDS_Shape node2 = itn.Value();
|
|
lnode1.Append(node2);
|
|
OldNodeNewNode(node2) = newnode1;
|
|
}
|
|
NewNodeOldNodes.UnBind(newnode2);
|
|
}
|
|
}
|
|
else {
|
|
// Old node #2 is not bound - add to old node #1
|
|
OldNodeNewNode.Bind(oldnode2,newnode1);
|
|
NewNodeOldNodes(newnode1).Append(oldnode2);
|
|
}
|
|
}
|
|
else {
|
|
if (OldNodeNewNode.IsBound(oldnode2)) {
|
|
// Old node #1 is not bound - add to old node #2
|
|
TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
|
|
OldNodeNewNode.Bind(oldnode1,newnode2);
|
|
NewNodeOldNodes(newnode2).Append(oldnode1);
|
|
}
|
|
else {
|
|
// Nodes are not bound - create new node
|
|
TopoDS_Vertex newnode;
|
|
B.MakeVertex(newnode);
|
|
OldNodeNewNode.Bind(oldnode1,newnode);
|
|
OldNodeNewNode.Bind(oldnode2,newnode);
|
|
TopTools_ListOfShape lnodes;
|
|
lnodes.Append(oldnode1);
|
|
lnodes.Append(oldnode2);
|
|
NewNodeOldNodes.Bind(newnode,lnodes);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Stop if no new nodes created
|
|
if (!NewNodeOldNodes.Extent()) return Standard_False;
|
|
|
|
TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes);
|
|
for (; iter1.More(); iter1.Next()) {
|
|
const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key());
|
|
// Calculate new node center point
|
|
gp_XYZ theCoordinates(0.,0.,0.);
|
|
TopTools_ListOfShape lvert; // Accumulate node vertices
|
|
TopTools_MapOfShape medge;
|
|
TopTools_ListOfShape ledge; // Accumulate node edges
|
|
// Iterate on old nodes
|
|
TopTools_ListIteratorOfListOfShape itn(iter1.Value());
|
|
for (; itn.More(); itn.Next()) {
|
|
const TopoDS_Shape& oldnode = itn.Value();
|
|
// Iterate on node vertices
|
|
TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
|
|
for (; itv.More(); itv.Next()) {
|
|
TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value());
|
|
// Change node for vertex
|
|
aVertexNode.ChangeFromKey(vertex) = newnode;
|
|
// Accumulate coordinates
|
|
theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
|
|
lvert.Append(vertex);
|
|
}
|
|
// Iterate on node edges
|
|
const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
|
|
TopTools_ListIteratorOfListOfShape ite(edges);
|
|
for (; ite.More(); ite.Next()) {
|
|
TopoDS_Shape edge = ite.Value();
|
|
if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
|
|
}
|
|
// Unbind old node edges
|
|
aNodeEdges.UnBind(oldnode);
|
|
}
|
|
// Bind new node edges
|
|
aNodeEdges.Bind(newnode,ledge);
|
|
gp_Pnt center(theCoordinates / lvert.Extent());
|
|
// Calculate new node tolerance
|
|
Standard_Real toler = 0.0;
|
|
TopTools_ListIteratorOfListOfShape itv(lvert);
|
|
for (; itv.More(); itv.Next()) {
|
|
const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
|
|
Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
|
|
if (toler < t) toler = t;
|
|
}
|
|
// Update new node parameters
|
|
B.UpdateVertex(newnode,center,toler);
|
|
}
|
|
|
|
return Standard_True;
|
|
}
|
|
|
|
static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
|
|
const TopoDS_Shape& e1, const TopoDS_Shape& e2,
|
|
const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
|
|
{
|
|
//Case of floating edges
|
|
if (face1.IsNull())
|
|
return (!IsClosedShape(e1,vtx1,vtx2));
|
|
|
|
// Find wires containing given edges
|
|
TopoDS_Shape wire1, wire2;
|
|
TopExp_Explorer itw(face1,TopAbs_WIRE);
|
|
for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
|
|
TopoDS_Iterator ite(itw.Current(),Standard_False);
|
|
for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
|
|
if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
|
|
if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
|
|
}
|
|
}
|
|
Standard_Integer Status = 0;
|
|
if (!wire1.IsNull() && !wire2.IsNull()) {
|
|
if (wire1.IsSame(wire2)) {
|
|
for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
|
|
TopoDS_Vertex ve1,ve2;
|
|
TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
|
|
if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
|
|
(ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
|
|
return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
|
|
}
|
|
if (IsClosedShape(wire1,vtx1,vtx2)) {
|
|
TopoDS_Vertex V1, V2;
|
|
TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
|
|
Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
|
|
(V2.IsSame(vtx1) && V1.IsSame(vtx2)));
|
|
if (!isEndVertex) Status = 1;
|
|
}
|
|
else Status = 1;
|
|
}
|
|
else Status = -1;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
|
|
TopTools_DataMapOfShapeListOfShape& aNodeEdges,
|
|
const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
|
|
const Standard_Real Tolerance,
|
|
const Handle(Message_ProgressIndicator)& theProgress)
|
|
{
|
|
Standard_Integer i, nbVertices = aVertexNode.Extent();
|
|
// Create map of node -> vertices
|
|
TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
|
|
BRepBuilderAPI_CellFilter aFilter (Tolerance);
|
|
BRepBuilderAPI_VertexInspector anInspector (Tolerance);
|
|
for (i = 1; i <= nbVertices; i++) {
|
|
TopoDS_Shape vertex = aVertexNode.FindKey(i);
|
|
TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i));
|
|
if (NodeVertices.Contains(node)) {
|
|
NodeVertices.ChangeFromKey(node).Append(vertex);
|
|
}
|
|
else {
|
|
TopTools_ListOfShape vlist;
|
|
vlist.Append(vertex);
|
|
NodeVertices.Add(node,vlist);
|
|
gp_Pnt aPnt = BRep_Tool::Pnt (TopoDS::Vertex (node));
|
|
aFilter.Add (NodeVertices.FindIndex (node), aPnt.XYZ());
|
|
anInspector.Add (aPnt.XYZ());
|
|
}
|
|
}
|
|
Standard_Integer nbNodes = NodeVertices.Extent();
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Glueing " << nbNodes << " nodes..." << endl;
|
|
#endif
|
|
// Merge nearest nodes
|
|
TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
|
|
Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True);
|
|
for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
|
|
TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
|
|
// Find near nodes
|
|
gp_Pnt pt1 = BRep_Tool::Pnt (node1);
|
|
anInspector.SetCurrent (pt1.XYZ());
|
|
gp_XYZ aPntMin = anInspector.Shift (pt1.XYZ(), -Tolerance);
|
|
gp_XYZ aPntMax = anInspector.Shift (pt1.XYZ(), Tolerance);
|
|
aFilter.Inspect (aPntMin, aPntMax, anInspector);
|
|
if (anInspector.ResInd().IsEmpty()) continue;
|
|
// Retrieve list of edges for the first node
|
|
const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
|
|
// Explore list of near nodes and fill the sequence of glued nodes
|
|
TopTools_SequenceOfShape SeqNodes;
|
|
TopTools_ListOfShape listNodesSameEdge;
|
|
//gp_Pnt pt1 = BRep_Tool::Pnt(node1);
|
|
TColStd_ListIteratorOfListOfInteger iter1(anInspector.ResInd());
|
|
for (; iter1.More(); iter1.Next()) {
|
|
TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
|
|
if (node1 == node2) continue;
|
|
// Retrieve list of edges for the second node
|
|
const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
|
|
// Check merging condition for the pair of nodes
|
|
Standard_Integer Status = 0, isSameEdge = Standard_False;
|
|
// Explore edges of the first node
|
|
TopTools_ListIteratorOfListOfShape Ie1(ledges1);
|
|
for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
|
|
const TopoDS_Shape& e1 = Ie1.Value();
|
|
// Obtain real vertex from edge
|
|
TopoDS_Shape v1 = node1;
|
|
{ //szv: Use brackets to destroy local variables
|
|
TopoDS_Vertex ov1, ov2;
|
|
TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
|
|
if (aVertexNode.Contains(ov1)) {
|
|
if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
|
|
}
|
|
if (aVertexNode.Contains(ov2)) {
|
|
if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
|
|
}
|
|
}
|
|
// Create map of faces for e1
|
|
TopTools_MapOfShape Faces1;
|
|
const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
|
|
if (lfac1.Extent()) {
|
|
TopTools_ListIteratorOfListOfShape itf(lfac1);
|
|
for (; itf.More(); itf.Next())
|
|
if (!itf.Value().IsNull())
|
|
Faces1.Add(itf.Value());
|
|
}
|
|
// Explore edges of the second node
|
|
TopTools_ListIteratorOfListOfShape Ie2(ledges2);
|
|
for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
|
|
const TopoDS_Shape& e2 = Ie2.Value();
|
|
// Obtain real vertex from edge
|
|
TopoDS_Shape v2 = node2;
|
|
{ //szv: Use brackets to destroy local variables
|
|
TopoDS_Vertex ov1, ov2;
|
|
TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
|
|
if (aVertexNode.Contains(ov1)) {
|
|
if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
|
|
}
|
|
if (aVertexNode.Contains(ov2)) {
|
|
if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
|
|
}
|
|
}
|
|
// Explore faces for e2
|
|
const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
|
|
if (lfac2.Extent()) {
|
|
TopTools_ListIteratorOfListOfShape itf(lfac2);
|
|
for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
|
|
// Check merging conditions for the same face
|
|
if (Faces1.Contains(itf.Value())) {
|
|
Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
|
|
if (stat == 1) isSameEdge = Standard_True;
|
|
else Status = stat;
|
|
}
|
|
}
|
|
}
|
|
else if (Faces1.IsEmpty() && e1 == e2) {
|
|
Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
|
|
if (stat == 1) isSameEdge = Standard_True;
|
|
else Status = stat;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (Status) continue;
|
|
if (isSameEdge) listNodesSameEdge.Append(node2);
|
|
// Append near node to the sequence
|
|
gp_Pnt pt2 = BRep_Tool::Pnt(node2);
|
|
Standard_Real dist = pt1.Distance(pt2);
|
|
if (dist < Tolerance) {
|
|
Standard_Boolean isIns = Standard_False;
|
|
for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
|
|
gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
|
|
if (dist < pt1.Distance(pt)) {
|
|
SeqNodes.InsertBefore(kk,node2);
|
|
isIns = Standard_True;
|
|
}
|
|
}
|
|
if (!isIns) SeqNodes.Append(node2);
|
|
}
|
|
}
|
|
if (SeqNodes.Length()) {
|
|
// Remove nodes near to some other from the same edge
|
|
if (listNodesSameEdge.Extent()) {
|
|
TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
|
|
for (; lInt.More(); lInt.Next()) {
|
|
const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
|
|
gp_Pnt p2 = BRep_Tool::Pnt(n2);
|
|
for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
|
|
const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
|
|
if (n1 != n2) {
|
|
gp_Pnt p1 = BRep_Tool::Pnt(n1);
|
|
if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
|
|
}
|
|
SeqNodes.Remove(k);
|
|
}
|
|
}
|
|
}
|
|
// Bind nearest node if at least one exists
|
|
if (SeqNodes.Length())
|
|
NodeNearestNode.Add(node1,SeqNodes.First());
|
|
}
|
|
anInspector.ClearResList();
|
|
}
|
|
|
|
// Create new nodes for chained nearest nodes
|
|
if (NodeNearestNode.IsEmpty()) return Standard_False;
|
|
|
|
return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
|
|
}
|
|
|
|
void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI)
|
|
{
|
|
Standard_Integer nbVert = myVertexNode.Extent();
|
|
Standard_Integer nbVertFree = myVertexNodeFree.Extent();
|
|
Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1);
|
|
if (nbVert || nbVertFree) {
|
|
// Fill map node -> sections
|
|
Standard_Integer i;
|
|
for (i = 1; i <= myBoundFaces.Extent(); i++) {
|
|
TopoDS_Shape bound = myBoundFaces.FindKey(i);
|
|
for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
|
|
TopoDS_Shape node = itv.Value();
|
|
if (myNodeSections.IsBound(node))
|
|
myNodeSections(node).Append(bound);
|
|
else {
|
|
TopTools_ListOfShape lbnd;
|
|
lbnd.Append(bound);
|
|
myNodeSections.Bind(node,lbnd);
|
|
}
|
|
}
|
|
}
|
|
// Glue vertices
|
|
if (nbVert) {
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Assemble " << nbVert << " vertices on faces..." << endl;
|
|
#endif
|
|
while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI));
|
|
}
|
|
if (!aPS.More())
|
|
return;
|
|
aPS.Next();
|
|
if (nbVertFree) {
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl;
|
|
#endif
|
|
while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI));
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : replaceNMVertices
|
|
//purpose : internal use (static)
|
|
//=======================================================================
|
|
static void replaceNMVertices(const TopoDS_Edge& theEdge,
|
|
const TopoDS_Vertex& theV1,
|
|
const TopoDS_Vertex& theV2,
|
|
const Handle(BRepTools_ReShape)& theReShape)
|
|
{
|
|
//To keep NM vertices on edge
|
|
TopTools_SequenceOfShape aSeqNMVert;
|
|
TColStd_SequenceOfReal aSeqNMPars;
|
|
Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
|
|
if(!hasNMVert)
|
|
return;
|
|
Standard_Real first, last;
|
|
BRep_Tool::Range(theEdge, first, last);
|
|
TopLoc_Location aLoc;
|
|
Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
|
|
if(c3d.IsNull())
|
|
return;
|
|
TopTools_SequenceOfShape aEdVert;
|
|
TColStd_SequenceOfReal aEdParams;
|
|
Standard_Integer i =1, nb = aSeqNMPars.Length();
|
|
|
|
for( ; i <= nb;i++) {
|
|
Standard_Real apar = aSeqNMPars.Value(i);
|
|
if(fabs(apar - first) <= Precision::PConfusion()) {
|
|
theReShape->Replace(aSeqNMVert.Value(i),theV1);
|
|
continue;
|
|
}
|
|
if(fabs(apar - last) <= Precision::PConfusion()) {
|
|
theReShape->Replace(aSeqNMVert.Value(i),theV2);
|
|
continue;
|
|
}
|
|
TopoDS_Shape aV = aSeqNMVert.Value(i);
|
|
Standard_Integer j =1;
|
|
for( ; j <= aEdParams.Length();j++) {
|
|
Standard_Real apar2 = aEdParams.Value(j);
|
|
if(fabs(apar - apar2) <= Precision::PConfusion()) {
|
|
theReShape->Replace(aV,aEdVert.Value(j));
|
|
break;
|
|
}
|
|
else if(apar < apar2) {
|
|
TopoDS_Shape anewV = aV.EmptyCopied();
|
|
aEdVert.InsertBefore(j,anewV);
|
|
aEdParams.InsertBefore(j,apar);
|
|
BRep_ListOfPointRepresentation& alistrep =
|
|
(*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
|
|
Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
|
|
alistrep.Append(aPRep);
|
|
theReShape->Replace(aV,anewV);
|
|
break;
|
|
}
|
|
}
|
|
if (j > aEdParams.Length()) {
|
|
TopoDS_Shape anewV = aV.EmptyCopied();
|
|
aEdVert.Append(anewV);
|
|
aEdParams.Append(apar);
|
|
BRep_ListOfPointRepresentation& alistrep =
|
|
(*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
|
|
Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
|
|
alistrep.Append(aPRep);
|
|
theReShape->Replace(aV,anewV);
|
|
}
|
|
}
|
|
|
|
Standard_Integer newnb = aEdParams.Length();
|
|
if(newnb < nb) {
|
|
|
|
TopoDS_Shape anewEdge = theEdge.EmptyCopied();
|
|
TopAbs_Orientation anOri = theEdge.Orientation();
|
|
anewEdge.Orientation(TopAbs_FORWARD);
|
|
BRep_Builder aB;
|
|
aB.Add(anewEdge,theV1);
|
|
aB.Add(anewEdge,theV2);
|
|
|
|
for( i =1; i <= aEdVert.Length();i++)
|
|
aB.Add(anewEdge,aEdVert.Value(i));
|
|
anewEdge.Orientation(anOri);
|
|
theReShape->Replace(theEdge,anewEdge);
|
|
}
|
|
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ReplaceEdge
|
|
//purpose : internal use (static)
|
|
//=======================================================================
|
|
|
|
static void ReplaceEdge(const TopoDS_Shape& oldEdge,
|
|
const TopoDS_Shape& theNewShape,
|
|
const Handle(BRepTools_ReShape)& aReShape)
|
|
{
|
|
TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
|
|
TopoDS_Shape newShape = aReShape->Apply(theNewShape);
|
|
if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
|
|
|
|
|
|
aReShape->Replace(oldShape,newShape);
|
|
TopoDS_Vertex V1old,V2old,V1new,V2new;
|
|
TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
|
|
TopAbs_Orientation Orold = oldShape.Orientation();
|
|
TopAbs_Orientation Ornew = Orold;
|
|
if (newShape.ShapeType() == TopAbs_EDGE) {
|
|
TopoDS_Edge aEn = TopoDS::Edge(newShape);
|
|
TopExp::Vertices(aEn,V1new,V2new);
|
|
Ornew = aEn.Orientation();
|
|
replaceNMVertices(aEn,V1new,V2new,aReShape);
|
|
}
|
|
else if (newShape.ShapeType() == TopAbs_WIRE) {
|
|
for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
|
|
TopoDS_Edge ed = TopoDS::Edge(aex.Current());
|
|
Ornew = ed.Orientation();
|
|
TopoDS_Vertex aV1,aV2;
|
|
TopExp::Vertices(ed,aV1,aV2);
|
|
replaceNMVertices(ed,aV1,aV2,aReShape);
|
|
if (V1new.IsNull())
|
|
V1new = aV1;
|
|
V2new =aV2;
|
|
}
|
|
}
|
|
|
|
V1new.Orientation(V1old.Orientation());
|
|
V2new.Orientation(V2old.Orientation());
|
|
if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
|
|
aReShape->Replace(V1old,V1new);
|
|
return;
|
|
}
|
|
if (Orold == Ornew) {
|
|
V1new.Orientation(V1old.Orientation());
|
|
V2new.Orientation(V2old.Orientation());
|
|
if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
|
|
aReShape->Replace(V1old,V1new);
|
|
if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
|
|
aReShape->Replace(V2old,V2new);
|
|
}
|
|
else {
|
|
V1new.Orientation(V2old.Orientation());
|
|
V2new.Orientation(V1old.Orientation());
|
|
if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
|
|
aReShape->Replace(V1old,V2new);
|
|
if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
|
|
aReShape->Replace(V2old,V1new);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Merging
|
|
//purpose : Modifies :
|
|
// myHasFreeBound
|
|
//
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */,
|
|
const Handle(Message_ProgressIndicator)& thePI)
|
|
{
|
|
BRep_Builder B;
|
|
// TopTools_MapOfShape MergedEdges;
|
|
Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1);
|
|
for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
|
|
|
|
TopoDS_Shape bound = myBoundFaces.FindKey(i);
|
|
|
|
// If bound was already merged - continue
|
|
if (myMergedEdges.Contains(bound)) continue;
|
|
|
|
if (!myBoundFaces(i).Extent()) {
|
|
// Merge free edge - only vertices
|
|
TopoDS_Vertex no1, no2;
|
|
TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
|
|
TopoDS_Shape nno1 = no1, nno2 = no2;
|
|
if (myVertexNodeFree.Contains(no1))
|
|
nno1 = myVertexNodeFree.FindFromKey(no1);
|
|
if (myVertexNodeFree.Contains(no2))
|
|
nno2 = myVertexNodeFree.FindFromKey(no2);
|
|
if (!no1.IsSame(nno1)) {
|
|
nno1.Orientation(no1.Orientation());
|
|
myReShape->Replace(no1,nno1);
|
|
}
|
|
if (!no2.IsSame(nno2)) {
|
|
nno2.Orientation(no2.Orientation());
|
|
myReShape->Replace(no2,nno2);
|
|
}
|
|
myMergedEdges.Add(bound);
|
|
continue;
|
|
}
|
|
|
|
// Check for previous splitting, build replacing wire
|
|
TopoDS_Wire BoundWire;
|
|
Standard_Boolean isPrevSplit = Standard_False;
|
|
Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
|
|
if (hasCuttingSections) {
|
|
B.MakeWire(BoundWire);
|
|
BoundWire.Orientation(bound.Orientation());
|
|
// Iterate on cutting sections
|
|
TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
|
|
for (; its.More(); its.Next()) {
|
|
TopoDS_Shape section = its.Value();
|
|
B.Add(BoundWire,section);
|
|
if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
|
|
}
|
|
}
|
|
|
|
// Merge with bound
|
|
TopTools_DataMapOfShapeShape MergedWithBound;
|
|
if (!isPrevSplit) {
|
|
// Obtain sequence of edges merged with bound
|
|
TopTools_SequenceOfShape seqMergedWithBound;
|
|
TColStd_SequenceOfInteger seqMergedWithBoundOri;
|
|
if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
|
|
// Store bound in the map
|
|
MergedWithBound.Bind(bound,bound);
|
|
// Iterate on edges merged with bound
|
|
Standard_Integer ii = 1;
|
|
while (ii <= seqMergedWithBound.Length()) {
|
|
TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
|
|
// Remove edge if recorded as merged
|
|
Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) ||
|
|
MergedWithBound.IsBound(iedge));
|
|
if (!isRejected) {
|
|
if (myBoundSections.IsBound(iedge)) {
|
|
// Edge is splitted - check sections
|
|
TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
|
|
for (; lit.More() && !isRejected; lit.Next()) {
|
|
const TopoDS_Shape& sec = lit.Value();
|
|
// Remove edge (bound) if at least one of its sections already merged
|
|
isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec));
|
|
}
|
|
}
|
|
if (!isRejected) {
|
|
if (mySectionBound.IsBound(iedge)) {
|
|
// Edge is a section - check bound
|
|
const TopoDS_Shape& bnd = mySectionBound(iedge);
|
|
// Remove edge (section) if its bound already merged
|
|
isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd));
|
|
}
|
|
}
|
|
}
|
|
// To the next merged edge
|
|
if (isRejected) {
|
|
// Remove rejected edge
|
|
seqMergedWithBound.Remove(ii);
|
|
seqMergedWithBoundOri.Remove(ii);
|
|
}
|
|
else {
|
|
// Process accepted edge
|
|
MergedWithBound.Bind(iedge,iedge);
|
|
ii++;
|
|
}
|
|
}
|
|
Standard_Integer nbMerged = seqMergedWithBound.Length();
|
|
if (nbMerged) {
|
|
// Create same parameter edge
|
|
TopTools_MapOfShape ActuallyMerged;
|
|
TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
|
|
seqMergedWithBoundOri,
|
|
ActuallyMerged,myReShape);
|
|
Standard_Boolean isForward = Standard_False;
|
|
if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
|
|
// Process actually merged edges
|
|
Standard_Integer nbActuallyMerged = 0;
|
|
for (ii = 1; ii <= nbMerged; ii++) {
|
|
TopoDS_Shape iedge = seqMergedWithBound(ii);
|
|
if (ActuallyMerged.Contains(iedge)) {
|
|
nbActuallyMerged++;
|
|
// Record merged edge in the map
|
|
TopAbs_Orientation orient = iedge.Orientation();
|
|
if (!isForward) orient = TopAbs::Reverse(orient);
|
|
if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
|
|
MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient);
|
|
}
|
|
else MergedWithBound.UnBind(iedge);
|
|
}
|
|
if (nbActuallyMerged) {
|
|
// Record merged bound in the map
|
|
TopAbs_Orientation orient = bound.Orientation();
|
|
if (!isForward) orient = TopAbs::Reverse(orient);
|
|
MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient);
|
|
}
|
|
nbMerged = nbActuallyMerged;
|
|
}
|
|
// Remove bound from the map if not finally merged
|
|
if (!nbMerged) MergedWithBound.UnBind(bound);
|
|
}
|
|
}
|
|
Standard_Boolean isMerged = MergedWithBound.Extent();
|
|
|
|
// Merge with cutting sections
|
|
Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
|
|
TopTools_DataMapOfShapeShape MergedWithSections;
|
|
if (hasCuttingSections) {
|
|
// Iterate on cutting sections
|
|
TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
|
|
for (; its.More(); its.Next()) {
|
|
// Retrieve cutting section
|
|
TopoDS_Shape section = its.Value();
|
|
// Skip section if already merged
|
|
if (myMergedEdges.Contains(section)) continue;
|
|
// Merge cutting section
|
|
TopTools_SequenceOfShape seqMergedWithSection;
|
|
TColStd_SequenceOfInteger seqMergedWithSectionOri;
|
|
if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
|
|
// Store section in the map
|
|
MergedWithSections.Bind(section,section);
|
|
// Iterate on edges merged with section
|
|
Standard_Integer ii = 1;
|
|
while (ii <= seqMergedWithSection.Length()) {
|
|
TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
|
|
// Remove edge if recorded as merged
|
|
Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge));
|
|
if (!isRejected) {
|
|
if (myBoundSections.IsBound(iedge)) {
|
|
// Edge is splitted - check sections
|
|
TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
|
|
for (; lit.More() && !isRejected; lit.Next()) {
|
|
const TopoDS_Shape& sec = lit.Value();
|
|
// Remove edge (bound) if at least one of its sections already merged
|
|
isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec));
|
|
}
|
|
}
|
|
if (!isRejected) {
|
|
if (mySectionBound.IsBound(iedge)) {
|
|
// Edge is a section - check bound
|
|
const TopoDS_Shape& bnd = mySectionBound(iedge);
|
|
// Remove edge (section) if its bound already merged
|
|
isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd));
|
|
}
|
|
}
|
|
}
|
|
// To the next merged edge
|
|
if (isRejected) {
|
|
// Remove rejected edge
|
|
seqMergedWithSection.Remove(ii);
|
|
seqMergedWithSectionOri.Remove(ii);
|
|
}
|
|
else {
|
|
// Process accepted edge
|
|
MergedWithSections.Bind(iedge,iedge);
|
|
ii++;
|
|
}
|
|
}
|
|
Standard_Integer nbMerged = seqMergedWithSection.Length();
|
|
if (nbMerged) {
|
|
// Create same parameter edge
|
|
TopTools_MapOfShape ActuallyMerged;
|
|
TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
|
|
seqMergedWithSectionOri,
|
|
ActuallyMerged,SectionsReShape);
|
|
Standard_Boolean isForward = Standard_False;
|
|
if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
|
|
// Process actually merged edges
|
|
Standard_Integer nbActuallyMerged = 0;
|
|
for (ii = 1; ii <= nbMerged; ii++) {
|
|
TopoDS_Shape iedge = seqMergedWithSection(ii);
|
|
if (ActuallyMerged.Contains(iedge)) {
|
|
nbActuallyMerged++;
|
|
// Record merged edge in the map
|
|
TopAbs_Orientation orient = iedge.Orientation();
|
|
if (!isForward) orient = TopAbs::Reverse(orient);
|
|
if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
|
|
TopoDS_Shape oedge = MergedEdge.Oriented(orient);
|
|
MergedWithSections.ChangeFind(iedge) = oedge;
|
|
ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
|
|
}
|
|
else MergedWithSections.UnBind(iedge);
|
|
}
|
|
if (nbActuallyMerged) {
|
|
// Record merged section in the map
|
|
TopAbs_Orientation orient = section.Orientation();
|
|
if (!isForward) orient = TopAbs::Reverse(orient);
|
|
TopoDS_Shape oedge = MergedEdge.Oriented(orient);
|
|
MergedWithSections.ChangeFind(section) = oedge;
|
|
ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
|
|
}
|
|
nbMerged = nbActuallyMerged;
|
|
}
|
|
// Remove section from the map if not finally merged
|
|
if (!nbMerged) MergedWithSections.UnBind(section);
|
|
}
|
|
else if (isMerged) {
|
|
// Reject merging of sections
|
|
MergedWithSections.Clear();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Standard_Boolean isMergedSplit = MergedWithSections.Extent();
|
|
|
|
if (!isMerged && !isMergedSplit) {
|
|
// Nothing was merged in this iteration
|
|
if (isPrevSplit) {
|
|
// Replace previously splitted bound
|
|
myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
|
|
}
|
|
// else if (hasCuttingSections) {
|
|
// myBoundSections.UnBind(bound); //szv: are you sure ???
|
|
// }
|
|
continue;
|
|
}
|
|
|
|
// Set splitting flag
|
|
Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit);
|
|
|
|
// Choose between bound and sections merging
|
|
if (isMerged && isMergedSplit && !isPrevSplit) {
|
|
// Fill map of merged cutting sections
|
|
TopTools_MapOfShape MapSplitEdges;
|
|
TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
|
|
for (itm.Initialize(MergedWithSections); itm.More(); itm.Next()) {
|
|
TopoDS_Shape edge = itm.Key();
|
|
MapSplitEdges.Add(edge);
|
|
}
|
|
// Iterate on edges merged with bound
|
|
for (itm.Initialize(MergedWithBound); itm.More(); itm.Next()) {
|
|
// Retrieve edge merged with bound
|
|
TopoDS_Shape edge = itm.Key();
|
|
// Remove edge from the map
|
|
if (MapSplitEdges.Contains(edge)) MapSplitEdges.Remove(edge);
|
|
if (myBoundSections.IsBound(edge)) {
|
|
// Edge has cutting sections
|
|
TopTools_ListIteratorOfListOfShape its(myBoundSections(edge));
|
|
for (; its.More(); its.Next()) {
|
|
TopoDS_Shape sec = its.Value();
|
|
// Remove section from the map
|
|
if (MapSplitEdges.Contains(sec)) MapSplitEdges.Remove(sec);
|
|
}
|
|
}
|
|
}
|
|
// Calculate section merging tolerance
|
|
Standard_Real MinSplitTol = RealLast();
|
|
TopTools_MapIteratorOfMapOfShape im(MapSplitEdges);
|
|
for (; im.More(); im.Next()) {
|
|
TopoDS_Edge edge = TopoDS::Edge(MergedWithSections(im.Key()));
|
|
MinSplitTol = Min(MinSplitTol,BRep_Tool::Tolerance(edge));
|
|
}
|
|
// Calculate bound merging tolerance
|
|
TopoDS_Edge BoundEdge = TopoDS::Edge(MergedWithBound(bound));
|
|
Standard_Real BoundEdgeTol = BRep_Tool::Tolerance(BoundEdge);
|
|
isSplitted = ((MinSplitTol < BoundEdgeTol+MinTolerance()) || myNonmanifold);
|
|
isSplitted = (!MapSplitEdges.IsEmpty() && isSplitted);
|
|
}
|
|
|
|
if (isSplitted) {
|
|
// Merging of cutting sections
|
|
//myMergedEdges.Add(bound);
|
|
myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
|
|
TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithSections);
|
|
for (; itm.More(); itm.Next()) {
|
|
TopoDS_Shape oldedge = itm.Key();
|
|
TopoDS_Shape newedge = SectionsReShape->Apply(itm.Value());
|
|
ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
|
|
myMergedEdges.Add(oldedge);
|
|
if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
|
|
|
|
}
|
|
}
|
|
else {
|
|
// Merging of initial bound
|
|
TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithBound);
|
|
//myMergedEdges.Add(bound);
|
|
for (; itm.More(); itm.Next()) {
|
|
TopoDS_Shape oldedge = itm.Key();
|
|
TopoDS_Shape newedge = itm.Value();
|
|
ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
|
|
myMergedEdges.Add(oldedge);
|
|
if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
|
|
}
|
|
if (myBoundSections.IsBound(bound)) myBoundSections.UnBind(bound);
|
|
if(!myMergedEdges.Contains(bound))
|
|
myMergedEdges.Add(bound);
|
|
}
|
|
}
|
|
|
|
myNbVertices = myVertexNode.Extent() + myVertexNodeFree.Extent();
|
|
myNodeSections.Clear();
|
|
myVertexNode.Clear();
|
|
myVertexNodeFree.Clear();
|
|
myCuttingNode.Clear();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : MergedNearestEdges
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepBuilderAPI_Sewing::MergedNearestEdges(const TopoDS_Shape& edge,
|
|
TopTools_SequenceOfShape& SeqMergedEdge,
|
|
TColStd_SequenceOfInteger& SeqMergedOri)
|
|
{
|
|
// Retrieve edge nodes
|
|
TopoDS_Vertex no1, no2;
|
|
TopExp::Vertices(TopoDS::Edge(edge),no1,no2);
|
|
TopoDS_Shape nno1 = no1, nno2 = no2;
|
|
Standard_Boolean isNode1 = myVertexNode.Contains(no1);
|
|
Standard_Boolean isNode2 = myVertexNode.Contains(no2);
|
|
if (isNode1) nno1 = myVertexNode.FindFromKey(no1);
|
|
if (isNode2) nno2 = myVertexNode.FindFromKey(no2);
|
|
|
|
// Fill map of nodes connected to the node #1
|
|
TopTools_MapOfShape mapVert1;
|
|
mapVert1.Add(nno1);
|
|
if (myCuttingNode.IsBound(nno1)) {
|
|
TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno1));
|
|
for (; ilv.More(); ilv.Next()) {
|
|
TopoDS_Shape v1 = ilv.Value();
|
|
mapVert1.Add(v1);
|
|
if (!isNode1 && myCuttingNode.IsBound(v1)) {
|
|
TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
|
|
for (; ilvn.More(); ilvn.Next()) {
|
|
TopoDS_Shape vn = ilvn.Value();
|
|
mapVert1.Add(vn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fill map of nodes connected to the node #2
|
|
TopTools_MapOfShape mapVert2;
|
|
mapVert2.Add(nno2);
|
|
if (myCuttingNode.IsBound(nno2)) {
|
|
TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno2));
|
|
for (; ilv.More(); ilv.Next()) {
|
|
TopoDS_Shape v1 = ilv.Value();
|
|
mapVert2.Add(v1);
|
|
if (!isNode2 && myCuttingNode.IsBound(v1)) {
|
|
TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
|
|
for (; ilvn.More(); ilvn.Next()) {
|
|
TopoDS_Shape vn = ilvn.Value();
|
|
mapVert2.Add(vn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Find all possible contigous edges
|
|
TopTools_SequenceOfShape seqEdges;
|
|
seqEdges.Append(edge);
|
|
TopTools_MapOfShape mapEdges;
|
|
mapEdges.Add(edge);
|
|
for (TopTools_MapIteratorOfMapOfShape imv1(mapVert1); imv1.More(); imv1.Next()) {
|
|
TopoDS_Shape node1 = imv1.Key();
|
|
if (!myNodeSections.IsBound(node1)) continue;
|
|
TopTools_ListIteratorOfListOfShape ilsec(myNodeSections(node1));
|
|
for (; ilsec.More(); ilsec.Next()) {
|
|
TopoDS_Shape sec = ilsec.Value();
|
|
if (sec.IsSame(edge)) continue;
|
|
// Retrieve section nodes
|
|
TopoDS_Vertex vs1, vs2;
|
|
TopExp::Vertices(TopoDS::Edge(sec),vs1,vs2);
|
|
TopoDS_Shape vs1n = vs1, vs2n = vs2;
|
|
if (myVertexNode.Contains(vs1)) vs1n = myVertexNode.FindFromKey(vs1);
|
|
if (myVertexNode.Contains(vs2)) vs2n = myVertexNode.FindFromKey(vs2);
|
|
if ((mapVert1.Contains(vs1n) && mapVert2.Contains(vs2n)) ||
|
|
(mapVert1.Contains(vs2n) && mapVert2.Contains(vs1n)))
|
|
if (mapEdges.Add(sec)) {
|
|
// Check for rejected cutting
|
|
Standard_Boolean isRejected = myMergedEdges.Contains(sec);
|
|
if(!isRejected && myBoundSections.IsBound(sec))
|
|
{
|
|
TopTools_ListIteratorOfListOfShape its(myBoundSections(sec));
|
|
for (; its.More() && !isRejected; its.Next()) {
|
|
TopoDS_Shape section = its.Value();
|
|
|
|
if (myMergedEdges.Contains(section))
|
|
isRejected = Standard_True;
|
|
}
|
|
}
|
|
if( !isRejected && mySectionBound.IsBound(sec)) {
|
|
const TopoDS_Shape& bnd = mySectionBound(sec);
|
|
isRejected = (!myBoundSections.IsBound(bnd) ||
|
|
myMergedEdges.Contains(bnd));
|
|
}
|
|
|
|
if (!isRejected) seqEdges.Append(sec);
|
|
}
|
|
}
|
|
}
|
|
|
|
mapEdges.Clear();
|
|
|
|
Standard_Boolean success = Standard_False;
|
|
|
|
Standard_Integer nbSection = seqEdges.Length();
|
|
if (nbSection > 1) {
|
|
// Find the longest edge CCI60011
|
|
Standard_Integer i, indRef = 1;
|
|
if (myNonmanifold) {
|
|
Standard_Real lenRef = 0.;
|
|
for (i = 1; i <= nbSection; i++) {
|
|
Standard_Real f, l;
|
|
Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(seqEdges(i)), f, l);
|
|
GeomAdaptor_Curve cAdapt(c3d);
|
|
Standard_Real len = GCPnts_AbscissaPoint::Length(cAdapt, f, l);
|
|
if (len > lenRef) { indRef = i; lenRef = len; }
|
|
}
|
|
if (indRef != 1) {
|
|
TopoDS_Shape longEdge = seqEdges(indRef);
|
|
seqEdges(indRef) = seqEdges(1);
|
|
seqEdges(1) = longEdge;
|
|
}
|
|
}
|
|
|
|
// Find merging candidates
|
|
TColStd_SequenceOfInteger seqForward;
|
|
TColStd_SequenceOfInteger seqCandidates;
|
|
TColStd_IndexedMapOfInteger mapReference;
|
|
mapReference.Add(indRef); // Add index of reference section
|
|
if (FindCandidates(seqEdges,mapReference,seqCandidates,seqForward)) {
|
|
Standard_Integer nbCandidates = seqCandidates.Length();
|
|
// Record candidate sections
|
|
for (i = 1; i <= nbCandidates; i++) {
|
|
// Retrieve merged edge
|
|
TopoDS_Shape iedge = seqEdges(seqCandidates(i));
|
|
Standard_Integer ori = (seqForward(i))? 1 : 0;
|
|
SeqMergedEdge.Append(iedge);
|
|
SeqMergedOri.Append(ori);
|
|
if (!myNonmanifold) break;
|
|
}
|
|
success = nbCandidates;
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Cutting
|
|
//purpose : Modifies :
|
|
// myBoundSections
|
|
// myNodeSections
|
|
// myCuttingNode
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::Cutting(const Handle(Message_ProgressIndicator)& thePI)
|
|
{
|
|
Standard_Integer i, nbVertices = myVertexNode.Extent();
|
|
if (!nbVertices) return;
|
|
// Create a box tree with vertices
|
|
Standard_Real eps = myTolerance*0.5;
|
|
BRepBuilderAPI_BndBoxTree aTree;
|
|
NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller (aTree);
|
|
BRepBuilderAPI_BndBoxTreeSelector aSelector;
|
|
for (i = 1; i <= nbVertices; i++) {
|
|
gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(myVertexNode.FindKey(i)));
|
|
Bnd_Box aBox;
|
|
aBox.Set(pt);
|
|
aBox.Enlarge(eps);
|
|
aTreeFiller.Add (i, aBox);
|
|
}
|
|
aTreeFiller.Fill();
|
|
|
|
Handle(Geom_Curve) c3d;
|
|
TopLoc_Location loc;
|
|
Standard_Real first, last;
|
|
// Iterate on all boundaries
|
|
Standard_Integer nbBounds = myBoundFaces.Extent();
|
|
Message_ProgressSentry aPS (thePI, "Cutting bounds", 0, nbBounds, 1);
|
|
for (i = 1; i <= nbBounds && aPS.More(); i++, aPS.Next()) {
|
|
const TopoDS_Edge& bound = TopoDS::Edge(myBoundFaces.FindKey(i));
|
|
// Do not cut floating edges
|
|
if (!myBoundFaces(i).Extent()) continue;
|
|
// Obtain bound curve
|
|
c3d = BRep_Tool::Curve(bound, loc, first, last);
|
|
if (c3d.IsNull()) continue;
|
|
if (!loc.IsIdentity()) {
|
|
c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
|
|
c3d->Transform(loc.Transformation());
|
|
}
|
|
// Create cutting sections
|
|
TopTools_ListOfShape listSections;
|
|
{ //szv: Use brackets to destroy local variables
|
|
// Obtain candidate vertices
|
|
TopoDS_Vertex V1, V2;
|
|
TopTools_IndexedMapOfShape CandidateVertices;
|
|
{ //szv: Use brackets to destroy local variables
|
|
// Create bounding box around curve
|
|
Bnd_Box aGlobalBox;
|
|
GeomAdaptor_Curve adptC(c3d,first,last);
|
|
BndLib_Add3dCurve::Add(adptC,myTolerance,aGlobalBox);
|
|
// Sort vertices to find candidates
|
|
aSelector.SetCurrent (aGlobalBox);
|
|
aTree.Select (aSelector);
|
|
// Skip bound if no node is in the boundind box
|
|
if (!aSelector.ResInd().Extent()) continue;
|
|
// Retrieve bound nodes
|
|
TopExp::Vertices(bound,V1,V2);
|
|
const TopoDS_Shape& Node1 = myVertexNode.FindFromKey(V1);
|
|
const TopoDS_Shape& Node2 = myVertexNode.FindFromKey(V2);
|
|
// Fill map of candidate vertices
|
|
TColStd_ListIteratorOfListOfInteger itl(aSelector.ResInd());
|
|
for (; itl.More(); itl.Next()) {
|
|
const Standard_Integer index = itl.Value();
|
|
const TopoDS_Shape& Node = myVertexNode.FindFromIndex(index);
|
|
if (!Node.IsSame(Node1) && !Node.IsSame(Node2)) {
|
|
TopoDS_Shape vertex = myVertexNode.FindKey(index);
|
|
CandidateVertices.Add(vertex);
|
|
}
|
|
}
|
|
aSelector.ClearResList();
|
|
}
|
|
Standard_Integer nbCandidates = CandidateVertices.Extent();
|
|
if (!nbCandidates) continue;
|
|
// Project vertices on curve
|
|
TColStd_Array1OfReal arrPara(1,nbCandidates), arrDist(1,nbCandidates);
|
|
TColgp_Array1OfPnt arrPnt(1,nbCandidates), arrProj(1,nbCandidates);
|
|
for (Standard_Integer j = 1; j <= nbCandidates; j++)
|
|
arrPnt(j) = BRep_Tool::Pnt(TopoDS::Vertex(CandidateVertices(j)));
|
|
ProjectPointsOnCurve(arrPnt,c3d,first,last,arrDist,arrPara,arrProj,Standard_True);
|
|
// Create cutting nodes
|
|
TopTools_SequenceOfShape seqNode;
|
|
TColStd_SequenceOfReal seqPara;
|
|
CreateCuttingNodes(CandidateVertices,bound,
|
|
V1,V2,arrDist,arrPara,arrProj,seqNode,seqPara);
|
|
if (!seqPara.Length()) continue;
|
|
// Create cutting sections
|
|
CreateSections(bound, seqNode, seqPara, listSections);
|
|
}
|
|
if (listSections.Extent() > 1) {
|
|
// modification of maps:
|
|
// myBoundSections
|
|
TopTools_ListIteratorOfListOfShape its(listSections);
|
|
for (; its.More(); its.Next()) {
|
|
TopoDS_Shape section = its.Value();
|
|
// Iterate on section vertices
|
|
for (TopoDS_Iterator itv(section); itv.More(); itv.Next()) {
|
|
TopoDS_Shape vertex = itv.Value();
|
|
// Convert vertex to node
|
|
if (myVertexNode.Contains(vertex))
|
|
vertex = TopoDS::Vertex(myVertexNode.FindFromKey(vertex));
|
|
// Update node sections
|
|
if (myNodeSections.IsBound(vertex))
|
|
myNodeSections.ChangeFind(vertex).Append(section);
|
|
else {
|
|
TopTools_ListOfShape lsec;
|
|
lsec.Append(section);
|
|
myNodeSections.Bind(vertex,lsec);
|
|
}
|
|
}
|
|
// Store bound for section
|
|
mySectionBound.Bind(section,bound);
|
|
}
|
|
// Store splitted bound
|
|
myBoundSections.Bind(bound,listSections);
|
|
}
|
|
}
|
|
#ifdef OCCT_DEBUG
|
|
cout << "From " << nbBounds << " bounds " << myBoundSections.Extent()
|
|
<< " were cut into " << mySectionBound.Extent() << " sections" << endl;
|
|
#endif
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetSeqEdges
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
static void GetSeqEdges(const TopoDS_Shape& edge,
|
|
TopTools_SequenceOfShape& seqEdges,
|
|
TopTools_DataMapOfShapeListOfShape& VertEdge)
|
|
{
|
|
Standard_Integer numV = 0;
|
|
for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
|
|
TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
|
|
numV++;
|
|
if (VertEdge.IsBound(V1)) {
|
|
const TopTools_ListOfShape& listEdges = VertEdge.Find(V1);
|
|
for (TopTools_ListIteratorOfListOfShape lIt(listEdges); lIt.More(); lIt.Next()) {
|
|
TopoDS_Shape edge1 = lIt.Value();
|
|
if (edge1.IsSame(edge)) continue;
|
|
Standard_Boolean isContained = Standard_False;
|
|
Standard_Integer i, index = 1;
|
|
for (i = 1; i <= seqEdges.Length() && !isContained; i++) {
|
|
isContained = seqEdges.Value(i).IsSame(edge1);
|
|
if (!isContained && seqEdges.Value(i).IsSame(edge)) index = i;
|
|
}
|
|
if (!isContained) {
|
|
if (numV == 1) seqEdges.InsertBefore(index,edge1);
|
|
else seqEdges.InsertAfter(index,edge1);
|
|
GetSeqEdges(edge1,seqEdges,VertEdge);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetFreeWires
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::GetFreeWires(TopTools_MapOfShape& MapFreeEdges, TopTools_SequenceOfShape& seqWires)
|
|
{
|
|
TopTools_DataMapOfShapeListOfShape VertEdge;
|
|
TopTools_MapIteratorOfMapOfShape itMap(MapFreeEdges);
|
|
TopTools_SequenceOfShape seqFreeEdges;
|
|
for (; itMap.More(); itMap.Next()) {
|
|
TopoDS_Shape edge = itMap.Key();
|
|
seqFreeEdges.Append(edge);
|
|
for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
|
|
TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
|
|
if (VertEdge.IsBound(V1))
|
|
VertEdge.ChangeFind(V1).Append(edge);
|
|
else {
|
|
TopTools_ListOfShape ls;
|
|
ls.Append(edge);
|
|
VertEdge.Bind(V1,ls);
|
|
}
|
|
}
|
|
}
|
|
BRep_Builder B;
|
|
Standard_Integer i, j;
|
|
for (i = 1; i <= seqFreeEdges.Length(); i++) {
|
|
TopTools_SequenceOfShape seqEdges;
|
|
TopoDS_Shape edge = seqFreeEdges.Value(i);
|
|
if (!MapFreeEdges.Contains(edge)) continue;
|
|
seqEdges.Append(edge);
|
|
GetSeqEdges(edge,seqEdges,VertEdge);
|
|
TopoDS_Wire wire;
|
|
B.MakeWire(wire);
|
|
for (j = 1; j <= seqEdges.Length(); j++) {
|
|
B.Add(wire,seqEdges.Value(j));
|
|
MapFreeEdges.Remove(seqEdges.Value(j));
|
|
}
|
|
seqWires.Append(wire);
|
|
if (MapFreeEdges.IsEmpty()) break;
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsDegeneratedWire
|
|
//purpose : internal use
|
|
//=======================================================================
|
|
|
|
static Standard_Boolean IsDegeneratedWire(const TopoDS_Shape& wire)
|
|
{
|
|
if (wire.ShapeType() != TopAbs_WIRE) return Standard_False;
|
|
// Get maximal vertices tolerance
|
|
TopoDS_Vertex V1,V2;
|
|
//TopExp::Vertices(TopoDS::Wire(wire),V1,V2);
|
|
//Standard_Real tol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
|
|
Standard_Real wireLength = 0.0;
|
|
TopLoc_Location loc;
|
|
Standard_Real first, last;
|
|
Standard_Integer nume = 0;
|
|
Standard_Integer isSmall = 0;
|
|
for (TopoDS_Iterator aIt(wire,Standard_False); aIt.More(); aIt.Next()) {
|
|
nume++;
|
|
TopoDS_Shape edge = aIt.Value();
|
|
TopoDS_Vertex Ve1,Ve2;
|
|
TopExp::Vertices(TopoDS::Edge(edge),Ve1,Ve2);
|
|
if(nume == 1) {
|
|
V1 = Ve1;
|
|
V2 = Ve2;
|
|
}
|
|
else {
|
|
if(Ve1.IsSame(V1))
|
|
V1 = Ve2;
|
|
else if(Ve1.IsSame(V2))
|
|
V2 = Ve2;
|
|
if(Ve2.IsSame(V1))
|
|
V1 = Ve1;
|
|
else if(Ve2.IsSame(V2))
|
|
V2 = Ve1;
|
|
}
|
|
Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aIt.Value()),loc,first,last);
|
|
if (!c3d.IsNull()) {
|
|
c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
|
|
if (!loc.IsIdentity()) {
|
|
//c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
|
|
c3d->Transform(loc.Transformation());
|
|
}
|
|
gp_Pnt pfirst = c3d->Value(first);
|
|
gp_Pnt plast = c3d->Value(last);
|
|
gp_Pnt pmid = c3d->Value((first +last)*0.5);
|
|
Standard_Real length =0;
|
|
if(pfirst.Distance(plast) > pfirst.Distance(pmid)) {
|
|
length = pfirst.Distance(plast);
|
|
}
|
|
else {
|
|
GeomAdaptor_Curve cAdapt(c3d);
|
|
length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
|
|
}
|
|
Standard_Real tole = BRep_Tool::Tolerance(Ve1)+BRep_Tool::Tolerance(Ve2);
|
|
if(length <= tole) isSmall++;
|
|
wireLength += length;
|
|
}
|
|
}
|
|
if(isSmall == nume) return Standard_True;
|
|
Standard_Real tol = BRep_Tool::Tolerance(V1)+BRep_Tool::Tolerance(V2);//Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
|
|
if (wireLength > tol) return Standard_False;
|
|
return Standard_True;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : DegeneratedSection
|
|
//purpose : internal use
|
|
// create a new degenerated edge if the section is degenerated
|
|
//=======================================================================
|
|
|
|
static TopoDS_Edge DegeneratedSection(const TopoDS_Shape& section, const TopoDS_Shape& face)
|
|
{
|
|
// Return if section is already degenerated
|
|
if (BRep_Tool::Degenerated(TopoDS::Edge(section))) return TopoDS::Edge(section);
|
|
|
|
// Retrieve edge curve
|
|
TopLoc_Location loc;
|
|
Standard_Real first, last;
|
|
Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(section), loc, first, last);
|
|
if (c3d.IsNull()) { //gka
|
|
BRep_Builder aB;
|
|
TopoDS_Edge edge1 = TopoDS::Edge(section);
|
|
aB.Degenerated(edge1, Standard_True);
|
|
return edge1;
|
|
}
|
|
if (!loc.IsIdentity()) {
|
|
c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
|
|
c3d->Transform(loc.Transformation());
|
|
}
|
|
|
|
// Test if the new edge is degenerated
|
|
TopoDS_Vertex v1,v2;
|
|
TopExp::Vertices(TopoDS::Edge(section),v1,v2);
|
|
//Standard_Real tol = Max(BRep_Tool::Tolerance(v1),BRep_Tool::Tolerance(v2));
|
|
//tol = Max(tolerance,tol);
|
|
|
|
gp_Pnt p1, p2, p3;
|
|
p1 = BRep_Tool::Pnt(v1);
|
|
p3 = BRep_Tool::Pnt(v2);
|
|
c3d->D0(0.5*(first + last),p2);
|
|
|
|
//Standard_Boolean isDegenerated = Standard_False;
|
|
//if (p1.Distance(p3) < tol) {
|
|
//GeomAdaptor_Curve cAdapt(c3d);
|
|
//Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
|
|
//isDegenerated = Standard_True; //(length < tol);
|
|
//}
|
|
|
|
TopoDS_Edge edge;
|
|
//if (!isDegenerated) return edge;
|
|
|
|
// processing
|
|
BRep_Builder aBuilder;
|
|
edge = TopoDS::Edge(section);
|
|
edge.EmptyCopy();
|
|
if (v1.IsSame(v2)) {
|
|
TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
|
|
aBuilder.Add(anEdge, v1.Oriented(TopAbs_FORWARD));
|
|
aBuilder.Add(anEdge, v2.Oriented(TopAbs_REVERSED));
|
|
}
|
|
else {
|
|
TopoDS_Vertex newVertex;
|
|
if (p1.Distance(p3) < BRep_Tool::Tolerance(v1))
|
|
newVertex = v1;
|
|
else if (p1.Distance(p3) < BRep_Tool::Tolerance(v2))
|
|
newVertex = v2;
|
|
else {
|
|
Standard_Real d1 = BRep_Tool::Tolerance(v1) + p2.Distance(p1);
|
|
Standard_Real d2 = BRep_Tool::Tolerance(v2) + p2.Distance(p3);
|
|
Standard_Real newTolerance = Max(d1,d2);
|
|
aBuilder.MakeVertex(newVertex, p2, newTolerance);
|
|
}
|
|
TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
|
|
aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_FORWARD));
|
|
aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_REVERSED));
|
|
}
|
|
|
|
BRep_Tool::Range(TopoDS::Edge(section), first, last);
|
|
TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
|
|
aBuilder.Range(TopoDS::Edge(anEdge), first, last);
|
|
aBuilder.Degenerated(edge, Standard_True);
|
|
Handle(Geom_Curve) aC3dNew;
|
|
if (!face.IsNull()) {
|
|
Standard_Real af,al;
|
|
Handle(Geom2d_Curve) aC2dt = BRep_Tool::CurveOnSurface(TopoDS::Edge(section),TopoDS::Face(face),af,al);
|
|
aBuilder.UpdateEdge(edge,aC3dNew,0);
|
|
Handle(Geom2d_Curve) aC2dn = BRep_Tool::CurveOnSurface(edge,TopoDS::Face(face),af,al);
|
|
if (aC2dn.IsNull())
|
|
aBuilder.UpdateEdge(edge,aC2dt,TopoDS::Face(face),0);
|
|
}
|
|
|
|
return edge;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : EdgeProcessing
|
|
//purpose : modifies :
|
|
// myNbEdges
|
|
// myHasMultipleEdge
|
|
// myHasFreeBound
|
|
// . if multiple edge
|
|
// - length < 100.*myTolerance -> several free edge
|
|
// . if no multiple edge
|
|
// - make the contigous edges sameparameter
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::EdgeProcessing(const Handle(Message_ProgressIndicator)& thePI)
|
|
{
|
|
// constructs sectionEdge
|
|
TopTools_MapOfShape MapFreeEdges;
|
|
TopTools_DataMapOfShapeShape EdgeFace;
|
|
Message_ProgressSentry aPS (thePI, "Edge processing", 0, myBoundFaces.Extent(), 1);
|
|
for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
|
|
const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
|
|
const TopTools_ListOfShape& listFaces = myBoundFaces(i);
|
|
if (listFaces.Extent() == 1) {
|
|
if (myBoundSections.IsBound(bound)) {
|
|
TopTools_ListIteratorOfListOfShape liter(myBoundSections(bound));
|
|
for (; liter.More(); liter.Next()) {
|
|
if (!myMergedEdges.Contains(liter.Value())) { //myReShape->IsRecorded(liter.Value())) {
|
|
TopoDS_Shape edge = myReShape->Apply(liter.Value());
|
|
if (!MapFreeEdges.Contains(edge)) {
|
|
TopoDS_Shape face = listFaces.First();
|
|
EdgeFace.Bind(edge,face);
|
|
MapFreeEdges.Add(edge);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (!myMergedEdges.Contains(bound)) {
|
|
TopoDS_Shape edge = myReShape->Apply(bound);
|
|
if (!MapFreeEdges.Contains(edge)) {
|
|
TopoDS_Shape face = listFaces.First();
|
|
EdgeFace.Bind(edge,face);
|
|
MapFreeEdges.Add(edge);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!MapFreeEdges.IsEmpty()) {
|
|
TopTools_SequenceOfShape seqWires;
|
|
GetFreeWires(MapFreeEdges,seqWires);
|
|
for (Standard_Integer j = 1; j <= seqWires.Length(); j++) {
|
|
TopoDS_Wire wire = TopoDS::Wire(seqWires.Value(j));
|
|
if (!IsDegeneratedWire(wire)) continue;
|
|
for (TopoDS_Iterator Ie(wire,Standard_False); Ie.More(); Ie.Next()) {
|
|
TopoDS_Shape aTmpShape = myReShape->Apply(Ie.Value()); //for porting
|
|
TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
|
|
TopoDS_Shape face;
|
|
if (EdgeFace.IsBound(edge))
|
|
face = EdgeFace.Find(edge);
|
|
TopoDS_Shape degedge = DegeneratedSection(edge,face);
|
|
if (degedge.IsNull()) continue;
|
|
if (!degedge.IsSame(edge))
|
|
ReplaceEdge(edge,degedge,myReShape);
|
|
if (BRep_Tool::Degenerated(TopoDS::Edge(degedge)))
|
|
myDegenerated.Add(degedge);
|
|
}
|
|
}
|
|
}
|
|
myMergedEdges.Clear();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CreateSewedShape
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::CreateSewedShape()
|
|
{
|
|
// ---------------------
|
|
// create the new shapes
|
|
// ---------------------
|
|
BRepTools_Quilt aQuilt;
|
|
Standard_Boolean isLocal = !myShape.IsNull();
|
|
if (isLocal) {
|
|
// Local sewing
|
|
TopoDS_Shape ns = myReShape->Apply(myShape);
|
|
aQuilt.Add(ns);
|
|
}
|
|
Standard_Integer i;
|
|
for (i = 1; i <= myOldShapes.Extent(); i++) {
|
|
TopoDS_Shape sh = myOldShapes(i);
|
|
if (!sh.IsNull()) {
|
|
sh = myReShape->Apply(sh);
|
|
myOldShapes(i) = sh;
|
|
if (!isLocal) aQuilt.Add(sh);
|
|
}
|
|
}
|
|
TopoDS_Shape aNewShape = aQuilt.Shells();
|
|
Standard_Integer numsh = 0;
|
|
|
|
TopTools_IndexedMapOfShape OldShells;
|
|
|
|
BRep_Builder aB;
|
|
TopoDS_Compound aComp;
|
|
aB.MakeCompound(aComp);
|
|
for (TopoDS_Iterator aExpSh(aNewShape,Standard_False); aExpSh.More(); aExpSh.Next()) {
|
|
TopoDS_Shape sh = aExpSh.Value();
|
|
Standard_Boolean hasEdges = Standard_False;
|
|
if (sh.ShapeType() == TopAbs_SHELL) {
|
|
if (myNonmanifold)
|
|
hasEdges = !OldShells.Contains(sh);
|
|
else {
|
|
TopoDS_Shape face;
|
|
Standard_Integer numf = 0;
|
|
for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
|
|
face = aExpF.Current();
|
|
numf++;
|
|
}
|
|
if (numf == 1) aB.Add(aComp,face);
|
|
else if (numf > 1) aB.Add(aComp,sh);
|
|
if (numf) numsh++;
|
|
}
|
|
}
|
|
else if (sh.ShapeType() == TopAbs_FACE) {
|
|
if (myNonmanifold) {
|
|
TopoDS_Shell ss;
|
|
aB.MakeShell(ss);
|
|
aB.Add(ss,sh);
|
|
sh = ss;
|
|
hasEdges = Standard_True;
|
|
}
|
|
else { aB.Add(aComp,sh); numsh++; }
|
|
}
|
|
else { aB.Add(aComp,sh); numsh++; }
|
|
if (hasEdges) OldShells.Add(sh);
|
|
}
|
|
// Process collected shells
|
|
if (myNonmanifold) {
|
|
Standard_Integer nbOldShells = OldShells.Extent();
|
|
if (nbOldShells == 1) {
|
|
// Single shell - check for single face
|
|
TopoDS_Shape sh = OldShells.FindKey(1);
|
|
TopoDS_Shape face;
|
|
Standard_Integer numf = 0;
|
|
for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
|
|
face = aExpF.Current();
|
|
numf++;
|
|
}
|
|
if (numf == 1) aB.Add(aComp,face);
|
|
else if (numf > 1) aB.Add(aComp,sh);
|
|
if (numf) numsh++;
|
|
}
|
|
else if (nbOldShells) {
|
|
// Several shells should be merged
|
|
TColStd_MapOfInteger IndexMerged;
|
|
while (IndexMerged.Extent() < nbOldShells) {
|
|
TopoDS_Shell NewShell;
|
|
TopTools_MapOfShape NewEdges;
|
|
for (i = 1; i <= nbOldShells; i++) {
|
|
if (IndexMerged.Contains(i)) continue;
|
|
TopoDS_Shell shell = TopoDS::Shell(OldShells.FindKey(i));
|
|
if (NewShell.IsNull()) {
|
|
BRep_Builder aB;
|
|
aB.MakeShell(NewShell);
|
|
TopoDS_Iterator aItSS(shell) ;
|
|
for( ; aItSS.More(); aItSS.Next())
|
|
aB.Add(NewShell,aItSS.Value())
|
|
;
|
|
// Fill map of edges
|
|
for (TopExp_Explorer eexp(shell,TopAbs_EDGE); eexp.More(); eexp.Next()) {
|
|
TopoDS_Shape edge = eexp.Current();
|
|
NewEdges.Add(edge);
|
|
}
|
|
IndexMerged.Add(i);
|
|
}
|
|
else {
|
|
Standard_Boolean hasSharedEdge = Standard_False;
|
|
TopExp_Explorer eexp(shell,TopAbs_EDGE);
|
|
for (; eexp.More() && !hasSharedEdge; eexp.Next())
|
|
hasSharedEdge = NewEdges.Contains(eexp.Current());
|
|
if (hasSharedEdge) {
|
|
// Add edges to the map
|
|
for (TopExp_Explorer eexp1(shell,TopAbs_EDGE); eexp1.More(); eexp1.Next()) {
|
|
TopoDS_Shape edge = eexp1.Current();
|
|
NewEdges.Add(edge);
|
|
}
|
|
// Add faces to the shell
|
|
for (TopExp_Explorer fexp(shell,TopAbs_FACE); fexp.More(); fexp.Next()) {
|
|
TopoDS_Shape face = fexp.Current();
|
|
aB.Add(NewShell,face);
|
|
}
|
|
IndexMerged.Add(i);
|
|
}
|
|
}
|
|
}
|
|
// Process new shell
|
|
TopoDS_Shape face;
|
|
Standard_Integer numf = 0;
|
|
TopExp_Explorer aExpF(NewShell,TopAbs_FACE);
|
|
for (; aExpF.More() && (numf < 2); aExpF.Next()) {
|
|
face = aExpF.Current();
|
|
numf++;
|
|
}
|
|
if (numf == 1) aB.Add(aComp,face);
|
|
else if (numf > 1) aB.Add(aComp,NewShell);
|
|
if (numf) numsh++;
|
|
}
|
|
}
|
|
}
|
|
if (numsh == 1) {
|
|
// Extract single component
|
|
TopoDS_Iterator aIt(aComp,Standard_False);
|
|
mySewedShape = aIt.Value();
|
|
}
|
|
else
|
|
mySewedShape = aComp;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CreateOutputInformations
|
|
//purpose : constructs :
|
|
// myEdgeSections
|
|
// mySectionBound
|
|
// myNbFreeEdges
|
|
// myNbContigousEdges
|
|
// myNbMultipleEdges
|
|
// myNbDegenerated
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::CreateOutputInformations()
|
|
{
|
|
// Construct edgeSections
|
|
Standard_Integer i;
|
|
//TopTools_DataMapOfShapeListOfShape edgeSections;
|
|
TopTools_IndexedDataMapOfShapeListOfShape edgeSections; //use index map for regulating free edges
|
|
for (i = 1; i <= myBoundFaces.Extent(); i++) {
|
|
const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
|
|
TopTools_ListOfShape lsect;
|
|
if (myBoundSections.IsBound(bound)) lsect = myBoundSections(bound);
|
|
TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
TopoDS_Shape sec = bound, edge = aExp.Current();
|
|
TopTools_ListIteratorOfListOfShape aI(lsect);
|
|
for (; aI.More(); aI.Next()) {
|
|
const TopoDS_Shape& section = aI.Value();
|
|
if (edge.IsSame(myReShape->Apply(section))) { sec = section; break; }
|
|
}
|
|
if (edgeSections.Contains(edge))
|
|
edgeSections.ChangeFromKey(edge).Append(sec);
|
|
else {
|
|
TopTools_ListOfShape listSec;
|
|
listSec.Append(sec);
|
|
edgeSections.Add(edge,listSec);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fill maps of Free, Contigous and Multiple edges
|
|
//TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter2(edgeSections);
|
|
for (i = 1; i <= edgeSections.Extent(); i++) {
|
|
const TopoDS_Shape& edge = edgeSections.FindKey(i);
|
|
const TopTools_ListOfShape& listSection = edgeSections(i);
|
|
if (listSection.Extent() == 1) {
|
|
if (BRep_Tool::Degenerated(TopoDS::Edge(edge)))
|
|
myDegenerated.Add(edge);
|
|
else
|
|
myFreeEdges.Add(edge);
|
|
}
|
|
else if (listSection.Extent() == 2) {
|
|
myContigousEdges.Add(edge,listSection);
|
|
}
|
|
else {
|
|
myMultipleEdges.Add(edge);
|
|
}
|
|
}
|
|
|
|
// constructs myContigSectBound
|
|
TopTools_DataMapOfShapeListOfShape aEdgeMap; //gka
|
|
for (i = 1; i <= myBoundFaces.Extent(); i++) {
|
|
TopoDS_Shape bound = myBoundFaces.FindKey(i);
|
|
if (myBoundSections.IsBound(bound)) {
|
|
TopTools_ListIteratorOfListOfShape iter(myBoundSections(bound));
|
|
for (; iter.More(); iter.Next()) {
|
|
TopoDS_Shape section = iter.Value();
|
|
if(!myMergedEdges.Contains(section)) continue;
|
|
//if (!myReShape->IsRecorded(section)) continue; // section is free
|
|
TopoDS_Shape nedge = myReShape->Apply(section);
|
|
if (nedge.IsNull()) continue; //szv debug
|
|
if (!bound.IsSame(section))
|
|
if (myContigousEdges.Contains(nedge))
|
|
myContigSecBound.Bind(section, bound);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ProjectPointsOnCurve
|
|
//purpose : internal use
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::ProjectPointsOnCurve(const TColgp_Array1OfPnt& arrPnt,
|
|
const Handle(Geom_Curve)& c3d,
|
|
const Standard_Real first,
|
|
const Standard_Real last,
|
|
TColStd_Array1OfReal& arrDist,
|
|
TColStd_Array1OfReal& arrPara,
|
|
TColgp_Array1OfPnt& arrProj,
|
|
const Standard_Boolean isConsiderEnds) const
|
|
{
|
|
arrDist.Init(-1.0);
|
|
|
|
GeomAdaptor_Curve GAC(c3d);
|
|
Extrema_ExtPC locProj;
|
|
locProj.Initialize(GAC, first, last);
|
|
gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
|
|
Standard_Integer find = 1;//(isConsiderEnds ? 1 : 2);
|
|
Standard_Integer lind = arrPnt.Length();//(isConsiderEnds ? arrPnt.Length() : arrPnt.Length() -1);
|
|
|
|
for (Standard_Integer i1 = find; i1 <= lind ; i1++) {
|
|
gp_Pnt pt = arrPnt(i1);
|
|
Standard_Real worktol = myTolerance;
|
|
Standard_Real distF2 = pfirst.SquareDistance(pt);
|
|
Standard_Real distL2 = plast.SquareDistance(pt);
|
|
Standard_Boolean isProjected = Standard_False;
|
|
try {
|
|
|
|
// Project current point on curve
|
|
locProj.Perform(pt);
|
|
if (locProj.IsDone() && locProj.NbExt() > 0) {
|
|
Standard_Real dist2Min = (isConsiderEnds || i1 == find || i1 == lind ? Min(distF2,distL2) : Precision::Infinite());
|
|
Standard_Integer ind, indMin = 0;
|
|
for (ind = 1; ind <= locProj.NbExt(); ind++) {
|
|
Standard_Real dProj2 = locProj.SquareDistance(ind);
|
|
if (dProj2 < dist2Min) { indMin = ind; dist2Min = dProj2; }
|
|
}
|
|
if (indMin) {
|
|
isProjected = Standard_True;
|
|
Extrema_POnCurv pOnC = locProj.Point(indMin);
|
|
Standard_Real paramProj = pOnC.Parameter();
|
|
gp_Pnt ptProj = GAC.Value(paramProj);
|
|
Standard_Real distProj2 = ptProj.SquareDistance(pt);
|
|
if (!locProj.IsMin(indMin)) {
|
|
if (Min(distF2,distL2) < dist2Min) {
|
|
if (distF2 < distL2) {
|
|
paramProj = first;
|
|
distProj2 = distF2;
|
|
ptProj = pfirst;
|
|
}
|
|
else {
|
|
paramProj = last;
|
|
distProj2 = distL2;
|
|
ptProj = plast;
|
|
}
|
|
}
|
|
}
|
|
if (distProj2 < worktol * worktol || !isConsiderEnds) {
|
|
arrDist(i1) = sqrt (distProj2);
|
|
arrPara(i1) = paramProj;
|
|
arrProj(i1) = ptProj;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Standard_Failure) {
|
|
worktol = MinTolerance();
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Exception in BRepBuilderAPI_Sewing::ProjectPointsOnCurve: ";
|
|
Standard_Failure::Caught()->Print(cout); cout << endl;
|
|
#endif
|
|
}
|
|
if (!isProjected && isConsiderEnds) {
|
|
if (Min(distF2,distL2) < worktol * worktol) {
|
|
if (distF2 < distL2) {
|
|
arrDist(i1) = sqrt (distF2);
|
|
arrPara(i1) = first;
|
|
arrProj(i1) = pfirst;
|
|
}
|
|
else {
|
|
arrDist(i1) = sqrt (distL2);
|
|
arrPara(i1) = last;
|
|
arrProj(i1) = plast;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CreateCuttingNodes
|
|
//purpose : internal use
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::CreateCuttingNodes(const TopTools_IndexedMapOfShape& MapVert,
|
|
const TopoDS_Shape& bound,
|
|
const TopoDS_Shape& vfirst,
|
|
const TopoDS_Shape& vlast,
|
|
const TColStd_Array1OfReal& arrDist,
|
|
const TColStd_Array1OfReal& arrPara,
|
|
const TColgp_Array1OfPnt& arrPnt,
|
|
TopTools_SequenceOfShape& seqVert,
|
|
TColStd_SequenceOfReal& seqPara)
|
|
{
|
|
Standard_Integer i, j, nbProj = MapVert.Extent();
|
|
|
|
// Reorder projections by distance
|
|
TColStd_SequenceOfInteger seqOrderedIndex;
|
|
{ //szv: Use brackets to destroy local variables
|
|
TColStd_SequenceOfReal seqOrderedDistance;
|
|
for (i = 1; i <= nbProj; i++) {
|
|
Standard_Real distProj = arrDist(i);
|
|
if (distProj < 0.0) continue; // Skip vertex if not projected
|
|
Standard_Boolean isInserted = Standard_False;
|
|
for (j = 1; j <= seqOrderedIndex.Length() && !isInserted; j++) {
|
|
isInserted = (distProj < seqOrderedDistance(j));
|
|
if (isInserted) {
|
|
seqOrderedIndex.InsertBefore(j,i);
|
|
seqOrderedDistance.InsertBefore(j,distProj);
|
|
}
|
|
}
|
|
if (!isInserted) {
|
|
seqOrderedIndex.Append(i);
|
|
seqOrderedDistance.Append(distProj);
|
|
}
|
|
}
|
|
}
|
|
nbProj = seqOrderedIndex.Length();
|
|
if (!nbProj) return;
|
|
|
|
BRep_Builder aBuilder;
|
|
|
|
// Insert two initial vertices (to be removed later)
|
|
TColStd_SequenceOfReal seqDist;
|
|
TColgp_SequenceOfPnt seqPnt;
|
|
{ //szv: Use brackets to destroy local variables
|
|
// Retrieve bound curve
|
|
TopLoc_Location loc;
|
|
Standard_Real first,last;
|
|
Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(bound), loc, first, last);
|
|
if (!loc.IsIdentity()) {
|
|
c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
|
|
c3d->Transform(loc.Transformation());
|
|
}
|
|
GeomAdaptor_Curve GAC(c3d);
|
|
seqVert.Prepend(vfirst); seqVert.Append(vlast);
|
|
seqPara.Prepend(first); seqPara.Append(last);
|
|
seqDist.Prepend(-1.0); seqDist.Append(-1.0);
|
|
seqPnt.Prepend(GAC.Value(first)); seqPnt.Append(GAC.Value(last));
|
|
}
|
|
|
|
TopTools_DataMapOfShapeShape NodeCuttingVertex;
|
|
for (i = 1; i <= nbProj; i++) {
|
|
|
|
const Standard_Integer index = seqOrderedIndex(i);
|
|
Standard_Real disProj = arrDist(index);
|
|
gp_Pnt pntProj = arrPnt(index);
|
|
|
|
// Skip node if already bound to cutting vertex
|
|
TopoDS_Shape node = myVertexNode.FindFromKey(MapVert(index));
|
|
if (NodeCuttingVertex.IsBound(node)) continue;
|
|
|
|
// Find the closest vertex
|
|
Standard_Integer indexMin = 1;
|
|
Standard_Real dist, distMin = pntProj.Distance(seqPnt(1));
|
|
for (j = 2; j <= seqPnt.Length(); j++) {
|
|
dist = pntProj.Distance(seqPnt(j));
|
|
if (dist < distMin) { distMin = dist; indexMin = j; }
|
|
}
|
|
|
|
// Check if current point is close to one of the existent
|
|
if (distMin <= Max(disProj*0.1,MinTolerance())) {
|
|
// Check distance if close
|
|
Standard_Real jdist = seqDist.Value(indexMin);
|
|
if (jdist < 0.0) {
|
|
// Bind new cutting node (end vertex only)
|
|
seqDist.SetValue(indexMin,disProj);
|
|
TopoDS_Shape cvertex = seqVert.Value(indexMin);
|
|
NodeCuttingVertex.Bind(node,cvertex);
|
|
}
|
|
else {
|
|
// Bind secondary cutting nodes
|
|
NodeCuttingVertex.Bind(node,TopoDS_Vertex());
|
|
}
|
|
}
|
|
else {
|
|
// Build new cutting vertex
|
|
TopoDS_Vertex cvertex;
|
|
aBuilder.MakeVertex(cvertex, pntProj, Precision::Confusion());
|
|
// Bind new cutting vertex
|
|
NodeCuttingVertex.Bind(node,cvertex);
|
|
// Insert cutting vertex in the sequences
|
|
Standard_Real parProj = arrPara(index);
|
|
for (j = 2; j <= seqPara.Length(); j++) {
|
|
if (parProj <= seqPara.Value(j)) {
|
|
seqVert.InsertBefore(j,cvertex);
|
|
seqPara.InsertBefore(j,parProj);
|
|
seqDist.InsertBefore(j,disProj);
|
|
seqPnt.InsertBefore (j,pntProj);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// filling map for cutting nodes
|
|
TopTools_DataMapIteratorOfDataMapOfShapeShape mit(NodeCuttingVertex);
|
|
for (; mit.More(); mit.Next()) {
|
|
TopoDS_Shape cnode = mit.Value();
|
|
// Skip secondary nodes
|
|
if (cnode.IsNull()) continue;
|
|
// Obtain vertex node
|
|
TopoDS_Shape node = mit.Key();
|
|
if (myVertexNode.Contains(cnode)) {
|
|
// This is an end vertex
|
|
cnode = myVertexNode.FindFromKey(cnode);
|
|
}
|
|
else {
|
|
// Create link: cutting vertex -> node
|
|
TopTools_ListOfShape ls;
|
|
ls.Append(node);
|
|
myCuttingNode.Bind(cnode,ls);
|
|
}
|
|
// Create link: node -> cutting vertex
|
|
if (myCuttingNode.IsBound(node)) {
|
|
myCuttingNode.ChangeFind(node).Append(cnode);
|
|
}
|
|
else {
|
|
TopTools_ListOfShape ls;
|
|
ls.Append(cnode);
|
|
myCuttingNode.Bind(node,ls);
|
|
}
|
|
}
|
|
|
|
// Remove two initial vertices
|
|
seqVert.Remove(1); seqVert.Remove(seqVert.Length());
|
|
seqPara.Remove(1); seqPara.Remove(seqPara.Length());
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : CreateSections
|
|
//purpose : internal use
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::CreateSections(const TopoDS_Shape& section,
|
|
const TopTools_SequenceOfShape& seqNode,
|
|
const TColStd_SequenceOfReal& seqPara,
|
|
TopTools_ListOfShape& listEdge)
|
|
{
|
|
const TopoDS_Edge& sec = TopoDS::Edge(section);
|
|
// TopAbs_Orientation aInitOr = sec.Orientation();
|
|
|
|
|
|
//To keep NM vertices on edge
|
|
TopTools_SequenceOfShape aSeqNMVert;
|
|
TColStd_SequenceOfReal aSeqNMPars;
|
|
findNMVertices(sec,aSeqNMVert,aSeqNMPars);
|
|
|
|
BRep_Builder aBuilder;
|
|
|
|
Standard_Real first, last;
|
|
BRep_Tool::Range(sec, first, last);
|
|
|
|
// Create cutting sections
|
|
Standard_Real par1, par2;
|
|
TopoDS_Shape V1, V2;
|
|
Standard_Integer i, len = seqPara.Length() + 1;
|
|
for (i = 1; i <= len; i++) {
|
|
|
|
TopoDS_Edge edge = sec;
|
|
edge.EmptyCopy();
|
|
|
|
if (i == 1) {
|
|
par1 = first;
|
|
par2 = seqPara(i);
|
|
V1 = TopExp::FirstVertex(sec);
|
|
V2 = seqNode(i);
|
|
}
|
|
else if (i == len) {
|
|
par1 = seqPara(i-1);
|
|
par2 = last;
|
|
V1 = seqNode(i-1);
|
|
V2 = TopExp::LastVertex(sec);
|
|
}
|
|
else {
|
|
par1 = seqPara(i-1);
|
|
par2 = seqPara(i);
|
|
V1 = seqNode(i-1);
|
|
V2 = seqNode(i);
|
|
}
|
|
|
|
TopoDS_Shape aTmpShape = edge.Oriented(TopAbs_FORWARD);
|
|
TopoDS_Edge aTmpEdge = TopoDS::Edge (aTmpShape); // for porting
|
|
aTmpShape = V1.Oriented(TopAbs_FORWARD);
|
|
aBuilder.Add(aTmpEdge, aTmpShape);
|
|
aTmpShape = V2.Oriented(TopAbs_REVERSED);
|
|
aBuilder.Add(aTmpEdge, aTmpShape);
|
|
aBuilder.Range(aTmpEdge, par1, par2);
|
|
// if(aInitOr == TopAbs_REVERSED)
|
|
// listEdge.Prepend(edge);
|
|
// else
|
|
|
|
Standard_Integer k =1;
|
|
for( ; k <= aSeqNMPars.Length() ; k++) {
|
|
Standard_Real apar = aSeqNMPars.Value(k);
|
|
if(apar >= par1 && apar <= par2) {
|
|
aBuilder.Add(aTmpEdge,aSeqNMVert.Value(k));
|
|
aSeqNMVert.Remove(k);
|
|
aSeqNMPars.Remove(k);
|
|
k--;
|
|
}
|
|
}
|
|
listEdge.Append(edge);
|
|
}
|
|
|
|
const TopTools_ListOfShape& listFaces = myBoundFaces.FindFromKey(sec);
|
|
if (!listFaces.Extent()) return;
|
|
|
|
Standard_Real tolEdge = BRep_Tool::Tolerance(sec);
|
|
|
|
// Add cutting pcurves
|
|
TopTools_ListIteratorOfListOfShape itf(listFaces);
|
|
for (; itf.More(); itf.Next()) {
|
|
|
|
const TopoDS_Face& fac = TopoDS::Face(itf.Value());
|
|
|
|
// Retrieve curve on surface
|
|
Standard_Real first2d=0., last2d=0.,first2d1=0,last2d1=0.;
|
|
Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(sec, fac, first2d, last2d);
|
|
if (c2d.IsNull()) continue;
|
|
Handle(Geom2d_Curve) c2d1;
|
|
Standard_Boolean isSeam = BRep_Tool::IsClosed(sec,fac);
|
|
|
|
//gka - Convert to BSpline was commented because
|
|
//it is not necessary to create BSpline instead of Lines or cIrcles.
|
|
//Besides after conversion circles to BSpline
|
|
//it is necessary to recompute parameters of cutting because paramerization of created
|
|
//BSpline curve differs from parametrization of circle.
|
|
|
|
// Convert pcurve to BSpline
|
|
/*Handle(Geom2d_BSplineCurve) c2dBSP,c2dBSP1;
|
|
if (c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
|
|
c2dBSP = Handle(Geom2d_BSplineCurve)::DownCast(c2d);
|
|
}
|
|
else {
|
|
if (first > (c2d->FirstParameter() + Precision::PConfusion()) ||
|
|
last < (c2d->LastParameter() - Precision::PConfusion())) {
|
|
Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d, first, last);
|
|
c2dBSP = Geom2dConvert::CurveToBSplineCurve(TC);
|
|
}
|
|
else c2dBSP = Geom2dConvert::CurveToBSplineCurve(c2d);
|
|
}
|
|
if (c2dBSP.IsNull()) continue;*/
|
|
//gka fix for bug OCC12203 21.04.06 addition second curve for seam edges
|
|
|
|
if(isSeam)
|
|
{
|
|
TopoDS_Edge secRev = TopoDS::Edge(sec.Reversed());
|
|
|
|
c2d1 = BRep_Tool::CurveOnSurface(secRev, fac, first2d1, last2d1);
|
|
if (c2d1.IsNull()) continue;
|
|
|
|
/*if (c2d1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
|
|
c2dBSP1 = Handle(Geom2d_BSplineCurve)::DownCast(c2d1);
|
|
}
|
|
else {
|
|
if (first > (c2d1->FirstParameter() + Precision::PConfusion()) ||
|
|
last < (c2d1->LastParameter() - Precision::PConfusion())) {
|
|
Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d1, first, last);
|
|
//c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(TC);
|
|
}
|
|
//else c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(c2d);
|
|
|
|
}*/
|
|
}
|
|
|
|
/*first2d = c2dBSP->FirstParameter();
|
|
last2d = c2dBSP->LastParameter();
|
|
|
|
if(!c2dBSP1.IsNull()) {
|
|
first2d1 = c2dBSP1->FirstParameter();
|
|
last2d1 = c2dBSP1->LastParameter();
|
|
}*/
|
|
|
|
// Update cutting sections
|
|
Handle(Geom2d_Curve) c2dNew,c2d1New;
|
|
TopTools_ListIteratorOfListOfShape ite(listEdge);
|
|
for (; ite.More(); ite.Next()) {
|
|
|
|
// Retrieve cutting section
|
|
const TopoDS_Edge& edge = TopoDS::Edge(ite.Value());
|
|
BRep_Tool::Range(edge, par1, par2);
|
|
|
|
// Cut BSpline pcurve
|
|
// try {
|
|
c2dNew = Handle(Geom2d_Curve)::DownCast(c2d->Copy());
|
|
//c2dNew = Handle(Geom2d_Curve)::DownCast(c2dBSP->Copy());
|
|
//Handle(Geom2d_BSplineCurve)::DownCast(c2dNew)->Segment(Max(first2d,par1),Min(par2,last2d));
|
|
if(!c2d1.IsNull()) { //if(!c2dBSP1.IsNull()) {
|
|
c2d1New = Handle(Geom2d_Curve)::DownCast(c2d1->Copy());
|
|
//c2d1New = Handle(Geom2d_Curve)::DownCast(c2dBSP1->Copy());
|
|
//Handle(Geom2d_BSplineCurve)::DownCast(c2d1New)->Segment(Max(first2d1,par1),Min(par2,last2d1));
|
|
}
|
|
//}
|
|
/*catch (Standard_Failure) {
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Exception in CreateSections: segment [" << par1 << "," << par2 << "]: ";
|
|
Standard_Failure::Caught()->Print(cout); cout << endl;
|
|
#endif
|
|
Handle(Geom2d_TrimmedCurve) c2dT = new Geom2d_TrimmedCurve(c2dNew,Max(first2d,par1),Min(par2,last2d));
|
|
c2dNew = c2dT;
|
|
}*/
|
|
|
|
|
|
if(!isSeam && c2d1New.IsNull())
|
|
aBuilder.UpdateEdge(edge, c2dNew, fac, tolEdge);
|
|
else {
|
|
TopAbs_Orientation Ori = edge.Orientation();
|
|
if(fac.Orientation() == TopAbs_REVERSED)
|
|
Ori = TopAbs::Reverse(Ori);
|
|
|
|
if(Ori == TopAbs_FORWARD)
|
|
aBuilder.UpdateEdge(edge, c2dNew,c2d1New ,fac, tolEdge);
|
|
else
|
|
aBuilder.UpdateEdge(edge, c2d1New,c2dNew ,fac, tolEdge);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SameParameterShape
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void BRepBuilderAPI_Sewing::SameParameterShape()
|
|
{
|
|
if (!mySameParameterMode) return;
|
|
TopExp_Explorer exp(mySewedShape, TopAbs_EDGE);
|
|
// Le flag sameparameter est a false pour chaque edge cousue
|
|
for (; exp.More(); exp.Next()) {
|
|
const TopoDS_Edge& sec = TopoDS::Edge(exp.Current());
|
|
try {
|
|
|
|
BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
|
|
}
|
|
catch (Standard_Failure) {
|
|
#ifdef OCCT_DEBUG
|
|
cout << "Fail: BRepBuilderAPI_Sewing::SameParameterShape exception in BRepLib::SameParameter" << endl;
|
|
#endif
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Inspect
|
|
//purpose : Used for selection and storage of coinciding points
|
|
//=======================================================================
|
|
|
|
NCollection_CellFilter_Action BRepBuilderAPI_VertexInspector::Inspect (const Standard_Integer theTarget)
|
|
{
|
|
/*gp_Pnt aPnt = gp_Pnt (myPoints.Value (theTarget - 1));
|
|
if (aPnt.SquareDistance (gp_Pnt (myCurrent)) <= myTol)
|
|
myResInd.Append (theTarget);*/
|
|
|
|
const gp_XYZ& aPnt = myPoints.Value (theTarget - 1);
|
|
Standard_Real aDx, aDy, aDz;
|
|
aDx = myCurrent.X() - aPnt.X();
|
|
aDy = myCurrent.Y() - aPnt.Y();
|
|
aDz = myCurrent.Z() - aPnt.Z();
|
|
|
|
if ((aDx*aDx <= myTol) && (aDy*aDy <= myTol) && (aDz*aDz <= myTol))
|
|
myResInd.Append (theTarget);
|
|
return CellFilter_Keep;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Context
|
|
//purpose :
|
|
//=======================================================================
|
|
const Handle(BRepTools_ReShape)& BRepBuilderAPI_Sewing::GetContext() const
|
|
{
|
|
return myReShape;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SetContext
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepBuilderAPI_Sewing::SetContext(const Handle(BRepTools_ReShape)& theContext)
|
|
{
|
|
myReShape = theContext;
|
|
}
|
|
|