1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-05 18:16:23 +03:00
occt/src/ShapeFix/ShapeFix_Wire_1.cxx
abv d5f74e42d6 0024624: Lost word in license statement in source files
License statement text corrected; compiler warnings caused by Bison 2.41 disabled for MSVC; a few other compiler warnings on 54-bit Windows eliminated by appropriate type cast
Wrong license statements corrected in several files.
Copyright and license statements added in XSD and GLSL files.
Copyright year updated in some files.
Obsolete documentation files removed from DrawResources.
2014-02-20 16:15:17 +04:00

1626 lines
49 KiB
C++

// 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.
// szv 19.08.99: new methods for fixing gaps between edges (3d curves and pcurves)
#include <ShapeFix_Wire.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <Precision.hxx>
#include <Bnd_Box2d.hxx>
#include <Geom_Curve.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>
#include <IntRes2d_SequenceOfIntersectionPoint.hxx>
#include <IntRes2d_IntersectionPoint.hxx>
#include <TColgp_SequenceOfPnt.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
#include <TopTools_HSequenceOfShape.hxx>
#include <BRep_Tool.hxx>
#include <BRep_Builder.hxx>
#include <ShapeExtend.hxx>
#include <ShapeBuild_Edge.hxx>
#include <ShapeBuild_Vertex.hxx>
#include <ShapeAnalysis_Curve.hxx>
#include <ShapeAnalysis_Edge.hxx>
#include <ShapeAnalysis_Surface.hxx>
#include <ShapeAnalysis.hxx>
#include <GeomConvert_CompCurveToBSplineCurve.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <gp_Pln.hxx>
#include <GeomAPI.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_SphericalSurface.hxx> //S4135
#include <Geom2d_BSplineCurve.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_HSurface.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <TopTools_Array1OfShape.hxx>
#include <BRepTools.hxx>
#include <Bnd_Array1OfBox2d.hxx>
#include <BndLib_Add2dCurve.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2dConvert.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <ShapeBuild_ReShape.hxx>
//szv
#include <TColgp_Array1OfPnt2d.hxx>
#include <Geom2d_Circle.hxx>
#include <Geom2d_Ellipse.hxx>
#include <Geom2d_Parabola.hxx>
#include <Geom2d_Hyperbola.hxx>
#include <Geom2d_OffsetCurve.hxx>
#include <Geom2dInt_GInter.hxx>
#include <IntRes2d_Domain.hxx>
#include <IntRes2d_IntersectionSegment.hxx>
#include <Geom2dAPI_ExtremaCurveCurve.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
#include <Approx_Curve2d.hxx>
#include <Geom2dConvert.hxx>
#include <Geom_Line.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_Parabola.hxx>
#include <Geom_Hyperbola.hxx>
#include <Geom_OffsetCurve.hxx>
#include <GeomAPI_ExtremaCurveCurve.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAdaptor_HCurve.hxx>
#include <Approx_Curve3d.hxx>
#include <GeomConvert.hxx>
#include <TopoDS_Iterator.hxx>
#include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeAnalysis_TransferParametersProj.hxx>
//=======================================================================
//function : FixGaps3d
//purpose :
//=======================================================================
Standard_Boolean ShapeFix_Wire::FixGaps3d ()
{
myStatusGaps3d = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
// if ( !IsReady() ) return Standard_False;
Standard_Integer i, start = ( myClosedMode ? 1 : 2 );
if (myFixGapsByRanges)
{
for ( i = start; i <= NbEdges(); i++ )
{
FixGap3d ( i );
myStatusGaps3d |= myLastFixStatus;
}
}
for ( i = start; i <= NbEdges(); i++ )
{
FixGap3d ( i, Standard_True );
myStatusGaps3d |= myLastFixStatus;
}
return StatusGaps3d ( ShapeExtend_DONE );
}
//=======================================================================
//function : FixGaps2d
//purpose :
//=======================================================================
Standard_Boolean ShapeFix_Wire::FixGaps2d ()
{
myStatusGaps2d = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
// if ( !IsReady() ) return Standard_False;
Standard_Integer i, start = ( myClosedMode ? 1 : 2 );
if (myFixGapsByRanges)
{
for ( i = start; i <= NbEdges(); i++ )
{
FixGap2d ( i );
myStatusGaps2d |= myLastFixStatus;
}
}
for ( i = start; i <= NbEdges(); i++ )
{
FixGap2d ( i, Standard_True );
myStatusGaps2d |= myLastFixStatus;
}
return StatusGaps2d ( ShapeExtend_DONE );
}
//=======================================================================
//function : FixGap3d
//purpose :
//=======================================================================
static Standard_Real AdjustOnPeriodic3d (const Handle(Geom_Curve)& c,
const Standard_Boolean takefirst,
const Standard_Real first,
const Standard_Real last,
const Standard_Real param)
{
// 15.11.2002 PTV OCC966
if (ShapeAnalysis_Curve::IsPeriodic(c))
{
Standard_Real T = c->Period();
Standard_Real shift = -IntegerPart(first/T)*T; if (first<0.) shift += T;
Standard_Real sfirst = first+shift, slast = last+shift;
if ( takefirst && (param>slast) && (param>sfirst)) return param-T-shift;
if (!takefirst && (param<slast) && (param<sfirst)) return param+T-shift;
}
return param;
}
Standard_Boolean ShapeFix_Wire::FixGap3d (const Standard_Integer num,
const Standard_Boolean convert)
{
myLastFixStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
// if ( !IsReady() ) return Standard_False;
//=============
// First phase: analysis whether the problem (gap) exists
//=============
if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
Standard_Real preci = Precision();
Handle(ShapeExtend_WireData) sbwd = WireData();
Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
//smh#8
TopoDS_Shape tmp1 = Context()->Apply(sbwd->Edge(n1)),
tmp2 = Context()->Apply(sbwd->Edge(n2));
TopoDS_Edge E1 = TopoDS::Edge(tmp1),
E2 = TopoDS::Edge(tmp2);
// TopoDS_Face face = myAnalyzer->Face(); // comment by enk
// Retrieve curves on edges
Standard_Real cfirst1, clast1, cfirst2, clast2;
Handle(Geom_Curve) C1, C2;
ShapeAnalysis_Edge SAE;
if (!SAE.Curve3d(E1,C1,cfirst1,clast1) ||
!SAE.Curve3d(E2,C2,cfirst2,clast2))
{
myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
return Standard_False;
}
// Check gap in 3d space
gp_Pnt cpnt1 = C1->Value(clast1), cpnt2 = C2->Value(cfirst2);
Standard_Real gap = cpnt1.Distance(cpnt2);
if (!convert && gap<=preci) return Standard_False;
//=============
// Second phase: collecting data necessary for further analysis
//=============
Standard_Boolean reversed1 = (E1.Orientation()==TopAbs_REVERSED),
reversed2 = (E2.Orientation()==TopAbs_REVERSED);
TopoDS_Vertex V1 = SAE.LastVertex(E1), V2 = SAE.FirstVertex(E2);
gp_Pnt vpnt = (V1.IsSame(V2))? BRep_Tool::Pnt(V1) :
gp_Pnt((BRep_Tool::Pnt(V1).XYZ()+BRep_Tool::Pnt(V2).XYZ())*0.5);
Standard_Real first1, last1, first2, last2;
if (reversed1)
{
first1 = clast1; last1 = cfirst1;
}
else
{
first1 = cfirst1; last1 = clast1;
}
if (reversed2)
{
first2 = clast2; last2 = cfirst2;
}
else
{
first2 = cfirst2; last2 = clast2;
}
Handle(Geom_Curve) c1 = C1, c2 = C2;
// Extract basic curves from trimmed and offset
Standard_Boolean basic = Standard_False;
Standard_Boolean trimmed1 = Standard_False, offset1 = Standard_False;
gp_XYZ offval1(0.,0.,0.);
while (!basic)
{
if (c1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
{
c1 = Handle(Geom_TrimmedCurve)::DownCast(c1)->BasisCurve();
trimmed1 = Standard_True;
}
else if (c1->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
{
Handle(Geom_OffsetCurve) oc = Handle(Geom_OffsetCurve)::DownCast(c1);
c1 = oc->BasisCurve();
offval1 += oc->Offset()*oc->Direction().XYZ();
offset1 = Standard_True;
}
else basic = Standard_True;
}
basic = Standard_False;
Standard_Boolean trimmed2 = Standard_False, offset2 = Standard_False;
gp_XYZ offval2(0.,0.,0.);
while (!basic)
{
if (c2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
{
c2 = Handle(Geom_TrimmedCurve)::DownCast(c2)->BasisCurve();
trimmed2 = Standard_True;
}
else if (c2->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
{
Handle(Geom_OffsetCurve) oc = Handle(Geom_OffsetCurve)::DownCast(c2);
c2 = oc->BasisCurve();
offval2 += oc->Offset()*oc->Direction().XYZ();
offset2 = Standard_True;
}
else basic = Standard_True;
}
// Restore offset curves
if (offset1) c1 = new Geom_OffsetCurve(c1,offval1.Modulus(),gp_Dir(offval1));
if (offset2) c2 = new Geom_OffsetCurve(c2,offval2.Modulus(),gp_Dir(offval2));
Standard_Boolean done1 = Standard_False, done2 = Standard_False;
if (convert)
{
Handle(Geom_BSplineCurve) bsp1, bsp2;
Handle(Geom_Curve) c;
Standard_Real first, last;
// iterate on curves
Standard_Integer nbcurv = (n1==n2? 1 : 2);
for (Standard_Integer j=1; j<=nbcurv; j++)
{
//Standard_Boolean trim = Standard_False; // skl
if (j==1)
{
if (cpnt1.Distance(vpnt)<preci)
{
if (n1==n2)
{
if (cpnt2.Distance(vpnt)<preci) continue;
}
else continue;
}
c = c1; first = first1; last = last1; /*trim = trimmed1;*/ // skl
}
else
{
if (cpnt2.Distance(vpnt)<preci) continue;
c = c2; first = first2; last = last2; /*trim = trimmed2;*/ // skl
}
Handle(Geom_BSplineCurve) bsp;
// Convert curve to bspline
if (c->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
{
bsp = Handle(Geom_BSplineCurve)::DownCast(c->Copy());
// take segment if trim and range differ
Standard_Real fbsp = bsp->FirstParameter(), lbsp = bsp->LastParameter();
Standard_Boolean segment = Standard_False;
if (first>fbsp)
{
fbsp = first; segment = Standard_True;
}
if (last<lbsp)
{
lbsp = last; segment = Standard_True;
}
if (segment)
bsp = GeomConvert::SplitBSplineCurve(bsp,fbsp,lbsp,
::Precision::Confusion());
}
else if (c->IsKind(STANDARD_TYPE(Geom_Conic)))
{
Approx_Curve3d Conv(new GeomAdaptor_HCurve(c,first,last),
myAnalyzer->Precision(),GeomAbs_C1,9,1000);
if (Conv.IsDone() || Conv.HasResult()) bsp = Conv.Curve();
}
else
{
// Restore trim for pcurve
Handle(Geom_Curve) tc ;
try
{
OCC_CATCH_SIGNALS
// 15.11.2002 PTV OCC966
if(!ShapeAnalysis_Curve::IsPeriodic(c))
tc = new Geom_TrimmedCurve(c,Max(first,c->FirstParameter()),Min(last,c->LastParameter()));
else tc = new Geom_TrimmedCurve(c,first,last);
bsp = GeomConvert::CurveToBSplineCurve(tc);
}
catch (Standard_Failure)
{
#ifdef DEB
cout << "Warning: ShapeFix_Wire_1::FixGap3d: Exception in TrimmedCurve" <<first<<" " <<last<<endl;
Standard_Failure::Caught()->Print(cout); cout << endl;
#endif
}
}
if (j==1) bsp1 = bsp; else bsp2 = bsp;
}
// Take curves ends if could not convert
if (bsp1.IsNull()) vpnt = cpnt1;
else if (bsp2.IsNull()) vpnt = cpnt2;
if (!bsp1.IsNull())
{
if(bsp1->Degree() == 1) bsp1->IncreaseDegree(2); //gka
if (n1==n2)
{
bsp1->SetPole(1,vpnt); bsp1->SetPole(bsp1->NbPoles(),vpnt);
}
else
{
if (reversed1) bsp1->SetPole(1,vpnt);
else bsp1->SetPole(bsp1->NbPoles(),vpnt);
}
first1 = bsp1->FirstParameter(); last1 = bsp1->LastParameter();
c1 = bsp1;
done1 = Standard_True;
}
if (!bsp2.IsNull())
{
if(bsp2->Degree() == 1) bsp2->IncreaseDegree(2); //gka
if (reversed2) bsp2->SetPole(bsp2->NbPoles(),vpnt);
else bsp2->SetPole(1,vpnt);
first2 = bsp2->FirstParameter(); last2 = bsp2->LastParameter();
c2 = bsp2;
done2 = Standard_True;
}
}
else
{
if (n1==n2)
{
if (c1->IsKind(STANDARD_TYPE(Geom_Circle)) ||
c1->IsKind(STANDARD_TYPE(Geom_Ellipse)))
{
Standard_Real diff = M_PI - Abs(clast1-cfirst2)*0.5;
first1 -= diff; last1 += diff;
done1 = Standard_True;
}
}
else
{
// Determine domains for extremal points locating
Standard_Real domfirst1 = first1, domlast1 = last1;
if (c1->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
c1->IsKind(STANDARD_TYPE(Geom_BezierCurve)))
{
domfirst1 = c1->FirstParameter();
domlast1 = c1->LastParameter();
}
else if (c1->IsKind(STANDARD_TYPE(Geom_Line)) ||
c1->IsKind(STANDARD_TYPE(Geom_Parabola)) ||
c1->IsKind(STANDARD_TYPE(Geom_Hyperbola)))
{
Standard_Real diff = domlast1 - domfirst1;
if (reversed1) domfirst1 -= 10.*diff;
else domlast1 += 10.*diff;
}
else if (c1->IsKind(STANDARD_TYPE(Geom_Circle)) ||
c1->IsKind(STANDARD_TYPE(Geom_Ellipse)))
{
domfirst1 = 0.; domlast1 = 2*M_PI;
}
Standard_Real domfirst2 = first2, domlast2 = last2;
if (c2->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
c2->IsKind(STANDARD_TYPE(Geom_BezierCurve)))
{
domfirst2 = c2->FirstParameter();
domlast2 = c2->LastParameter();
}
else if (c2->IsKind(STANDARD_TYPE(Geom_Line)) ||
c2->IsKind(STANDARD_TYPE(Geom_Parabola)) ||
c2->IsKind(STANDARD_TYPE(Geom_Hyperbola)))
{
Standard_Real diff = domlast2 - domfirst2;
if (reversed2) domlast2 += 10.*diff;
else domfirst2 -= 10.*diff;
}
else if (c2->IsKind(STANDARD_TYPE(Geom_Circle)) ||
c2->IsKind(STANDARD_TYPE(Geom_Ellipse)))
{
domfirst2 = 0.; domlast2 = 2*M_PI;
}
Standard_Real ipar1 = clast1, ipar2 = cfirst2;
// Try to find projections of vertex point
GeomAPI_ProjectPointOnCurve Proj;
Standard_Real u1 = ipar1, u2 = ipar2;
Proj.Init(vpnt,c1,domfirst1,domlast1);
if (Proj.NbPoints())
{
Standard_Integer index = 1;
Standard_Real dist, mindist=-1.;
for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
{
dist = vpnt.Distance(Proj.Point(i));
if (mindist>dist || mindist<0.)
{
index = i; mindist = dist;
}
u1 = Proj.Parameter(index);
}
}
Proj.Init(vpnt,c2,domfirst2,domlast2);
if (Proj.NbPoints())
{
Standard_Integer index = 1;
Standard_Real dist, mindist=-1.;
for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
{
dist = vpnt.Distance(Proj.Point(i));
if (mindist>dist || mindist<0.)
{
index = i; mindist = dist;
}
u2 = Proj.Parameter(index);
}
}
// Ajust parameters on periodic curves
u1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,u1);
u2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,u2);
// Check points to satisfy distance criterium
gp_Pnt p1 = c1->Value(u1), p2 = c2->Value(u2);
if (p1.Distance(p2)<=gap &&
Abs(cfirst1-u1) > ::Precision::PConfusion() &&
Abs(clast2-u2) > ::Precision::PConfusion() &&
(((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
(cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
{
ipar1 = u1; ipar2 = u2;
done1 = done2 = Standard_True;
}
// Try to find closest points if nothing yet found
if (!done1)
{
// Recompute domains
if (reversed1)
{
domfirst1 = ipar1; domlast1 = last1;
}
else
{
domfirst1 = first1; domlast1 = ipar1;
}
if (reversed2)
{
domfirst2 = first2; domlast2 = ipar2;
}
else
{
domfirst2 = ipar2; domlast2 = last2;
}
GeomAPI_ExtremaCurveCurve Extr(c1,c2,domfirst1,domlast1,domfirst2,domlast2);
if (Extr.NbExtrema())
{
try
{
OCC_CATCH_SIGNALS
// First find all intersections
gp_Pnt pp1, pp2;
Standard_Integer index1=0, index2=0;
Standard_Real uu1, uu2, pardist, pardist1=-1., pardist2=-1.;
for (Standard_Integer i=1; i<=Extr.NbExtrema(); i++)
{
Extr.Parameters(i,uu1,uu2);
// Ajust parameters on periodic curves
uu1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,uu1);
uu2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,uu2);
pp1 = c1->Value(uu1); pp2 = c2->Value(uu2);
if (pp1.Distance(pp2) < ::Precision::Confusion())
{
// assume intersection
pardist = Abs(cfirst1-uu1);
if (pardist1>pardist || pardist1<0.)
{
index1 = i; pardist1 = pardist;
}
pardist = Abs(clast2-uu2);
if (pardist2>pardist || pardist2<0.)
{
index2 = i; pardist2 = pardist;
}
}
}
if (index1!=0 && index2!=0)
{
if (index1!=index2)
{
// take intersection closer to vertex point
Extr.Parameters(index1,uu1,uu2);
pp1 = gp_Pnt((c1->Value(uu1).XYZ()+c2->Value(uu2).XYZ())*0.5);
Extr.Parameters(index2,uu1,uu2);
pp2 = gp_Pnt((c1->Value(uu1).XYZ()+c2->Value(uu2).XYZ())*0.5);
if (pp2.Distance(vpnt) < pp1.Distance(vpnt)) index1 = index2;
}
Extr.Parameters(index1,uu1,uu2);
}
else Extr.LowerDistanceParameters(uu1,uu2);
// Ajust parameters on periodic curves
uu1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,uu1);
uu2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,uu2);
// Check points to satisfy distance criterium
pp1 = c1->Value(uu1), pp2 = c2->Value(uu2);
if (pp1.Distance(pp2)<=gap &&
Abs(cfirst1-uu1) > ::Precision::PConfusion() &&
Abs(clast2-uu2) > ::Precision::PConfusion() &&
(((uu1>first1) && (uu1<last1)) || ((uu2>first2) && (uu2<last2)) ||
(cpnt1.Distance(pp1)<=gap) || (cpnt2.Distance(pp2)<=gap)))
{
ipar1 = uu1; ipar2 = uu2;
done1 = done2 = Standard_True;
}
}
catch ( Standard_Failure )
{
}
}
}
try
{
OCC_CATCH_SIGNALS
if (done1)
{
if (ipar1==clast1) done1 = Standard_False;
else
{
// Set up new bounds for curve
if (reversed1) first1 = ipar1; else last1 = ipar1;
// Set new trim for old curve
if (trimmed1)
{
// Standard_Real ff1 = c1->FirstParameter();
// Standard_Real ll1 = c1->LastParameter();
c1 = new Geom_TrimmedCurve(c1,first1,last1);
}
}
}
if (done2)
{
if (ipar2==cfirst2) done2 = Standard_False;
else
{
// Set up new bounds for curve
if (reversed2) last2 = ipar2; else first2 = ipar2;
// Set new trim for old curve
if (trimmed2)
{
// Standard_Real ff2 = c2->FirstParameter();
// Standard_Real ll2 = c2->LastParameter();
c2 = new Geom_TrimmedCurve(c2,first2,last2);
}
}
}
}
catch (Standard_Failure)
{
#ifdef DEB
cout << "Warning: ShapeFix_Wire_1::FixGap3d: Exception in TrimmedCurve :"<<endl;
Standard_Failure::Caught()->Print(cout); cout << endl;
#endif
}
}
}
if (done1 || done2)
{
BRep_Builder B;
ShapeBuild_Edge SBE;
ShapeFix_ShapeTolerance SFST;
// Update vertices
TopoDS_Vertex nullV, newV1;
//smh#8
TopoDS_Shape emptyCopiedV2 = V2.EmptyCopied();
TopoDS_Vertex newV2 = TopoDS::Vertex(emptyCopiedV2);
SFST.SetTolerance(newV2,::Precision::Confusion());
Context()->Replace(V2,newV2);
if (V1.IsSame(V2))
//smh#8
{
TopoDS_Shape tmpV2 = newV2.Oriented(TopAbs_REVERSED);
newV1 = TopoDS::Vertex(tmpV2);
}
else
{
//smh#8
TopoDS_Shape emptyCopied = V1.EmptyCopied();
newV1 = TopoDS::Vertex(emptyCopied);
SFST.SetTolerance(newV1,::Precision::Confusion());
Context()->Replace(V1,newV1);
}
if (done1)
{
// Update first edge
TopoDS_Edge newE1 = SBE.CopyReplaceVertices(E1,nullV,newV1);
//smh#8
TopoDS_Shape tmpE1 = newE1.Oriented(TopAbs_FORWARD);
B.UpdateEdge(TopoDS::Edge(tmpE1),c1,0.);
SBE.SetRange3d(TopoDS::Edge(tmpE1),first1,last1);
SFST.SetTolerance(newE1,::Precision::Confusion(),TopAbs_EDGE);
B.SameRange(newE1,Standard_False);
// B.SameParameter(newE1,Standard_False);
//To keep NM vertices belonging initial edges
TopoDS_Iterator aItv(E1,Standard_False);
for( ; aItv.More(); aItv.Next()) {
if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
aItv.Value().Orientation() == TopAbs_EXTERNAL) {
TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE1,E1);
B.Add(newE1,anewV);
Context()->Replace(aOldV,anewV);
}
}
Context()->Replace(E1,newE1);
sbwd->Set(newE1,n1);
}
if (done2)
{
// Update second edge
TopoDS_Edge newE2 = SBE.CopyReplaceVertices(E2,newV2,nullV);
//smh#8
TopoDS_Shape tmpE2 = newE2.Oriented(TopAbs_FORWARD);
B.UpdateEdge(TopoDS::Edge(tmpE2),c2,0.);
SBE.SetRange3d(TopoDS::Edge(tmpE2),first2,last2);
SFST.SetTolerance(newE2,::Precision::Confusion(),TopAbs_EDGE);
B.SameRange(newE2,Standard_False);
// B.SameParameter(newE2,Standard_False);
//To keep NM vertices belonging initial edges
TopoDS_Iterator aItv(E2,Standard_False);
for( ; aItv.More(); aItv.Next()) {
if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
aItv.Value().Orientation() == TopAbs_EXTERNAL) {
TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE2,E2);
B.Add(newE2,anewV);
Context()->Replace(aOldV,anewV);
}
}
Context()->Replace(E2,newE2);
sbwd->Set(newE2,n2);
}
myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
}
else
if (convert)
myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );
return (done1 || done2);
}
//=======================================================================
//function : FixGap2d
//purpose :
//=======================================================================
static Standard_Real AdjustOnPeriodic2d (const Handle(Geom2d_Curve)& pc,
const Standard_Boolean takefirst,
const Standard_Real first,
const Standard_Real last,
const Standard_Real param)
{
// 15.11.2002 PTV OCC966
if (ShapeAnalysis_Curve::IsPeriodic(pc))
{
Standard_Real T = pc->Period();
Standard_Real shift = -IntegerPart(first/T)*T; if (first<0.) shift += T;
Standard_Real sfirst = first+shift, slast = last+shift;
if ( takefirst && (param>slast) && (param>sfirst)) return param-T-shift;
if (!takefirst && (param<slast) && (param<sfirst)) return param+T-shift;
}
return param;
}
Standard_Boolean ShapeFix_Wire::FixGap2d (const Standard_Integer num,
const Standard_Boolean convert)
{
myLastFixStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
if ( !IsReady() ) return Standard_False;
//=============
// First phase: analysis whether the problem (gap) exists
//=============
if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
Standard_Real preci = ::Precision::PConfusion();
//Standard_Real preci = Precision();
//GeomAdaptor_Surface& SA = Analyzer().Surface()->Adaptor()->ChangeSurface();
//preci = Max(SA.UResolution(preci), SA.VResolution(preci));
Handle(ShapeExtend_WireData) sbwd = WireData();
Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
//smh#8
TopoDS_Shape tmp1 = Context()->Apply(sbwd->Edge(n1)),
tmp2 = Context()->Apply(sbwd->Edge(n2));
TopoDS_Edge E1 = TopoDS::Edge(tmp1),
E2 = TopoDS::Edge(tmp2);
TopoDS_Face face = myAnalyzer->Face();
// Retrieve pcurves on edges
Standard_Real cfirst1, clast1, cfirst2, clast2;
Handle(Geom2d_Curve) PC1, PC2;
ShapeAnalysis_Edge SAE;
if (!SAE.PCurve(E1,face,PC1,cfirst1,clast1) ||
!SAE.PCurve(E2,face,PC2,cfirst2,clast2) ||
sbwd->IsSeam(n1) || sbwd->IsSeam(n2))
{
myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
return Standard_False;
}
// Check gap in 2d space
gp_Pnt2d cpnt1 = PC1->Value(clast1), cpnt2 = PC2->Value(cfirst2);
Standard_Real gap = cpnt1.Distance(cpnt2);
if (gap<=preci) return Standard_False;
//=============
// Second phase: collecting data necessary for further analysis
//=============
Standard_Boolean reversed1 = (E1.Orientation()==TopAbs_REVERSED),
reversed2 = (E2.Orientation()==TopAbs_REVERSED);
Standard_Real first1, last1, first2, last2;
if (reversed1)
{
first1 = clast1; last1 = cfirst1;
}
else
{
first1 = cfirst1; last1 = clast1;
}
if (reversed2)
{
first2 = clast2; last2 = cfirst2;
}
else
{
first2 = cfirst2; last2 = clast2;
}
Handle(Geom2d_Curve) pc1 = PC1, pc2 = PC2;
// Extract basic curves from trimmed and offset
Standard_Boolean basic = Standard_False;
Standard_Boolean trimmed1 = Standard_False, offset1 = Standard_False;
Standard_Real offval1 = 0.;
while (!basic)
{
if (pc1->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
{
pc1 = Handle(Geom2d_TrimmedCurve)::DownCast(pc1)->BasisCurve();
trimmed1 = Standard_True;
}
else if (pc1->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
{
Handle(Geom2d_OffsetCurve) oc = Handle(Geom2d_OffsetCurve)::DownCast(pc1);
pc1 = oc->BasisCurve();
offval1 += oc->Offset();
offset1 = Standard_True;
}
else basic = Standard_True;
}
basic = Standard_False;
Standard_Boolean trimmed2 = Standard_False, offset2 = Standard_False;
Standard_Real offval2 = 0.;
while (!basic)
{
if (pc2->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
{
pc2 = Handle(Geom2d_TrimmedCurve)::DownCast(pc2)->BasisCurve();
trimmed2 = Standard_True;
}
else if (pc2->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
{
Handle(Geom2d_OffsetCurve) oc = Handle(Geom2d_OffsetCurve)::DownCast(pc2);
pc2 = oc->BasisCurve();
offval2 += oc->Offset();
offset2 = Standard_True;
}
else basic = Standard_True;
}
// Restore offset curves
if (offset1) pc1 = new Geom2d_OffsetCurve(pc1,offval1);
if (offset2) pc2 = new Geom2d_OffsetCurve(pc2,offval2);
Standard_Boolean done1 = Standard_False, done2 = Standard_False;
// Determine same edge case
if (convert)
{
Handle(Geom2d_BSplineCurve) bsp1, bsp2;
Handle(Geom2d_Curve) pc;
Standard_Real first, last;
// iterate on pcurves
Standard_Integer nbcurv = (n1==n2? 1 : 2);
for (Standard_Integer j=1; j<=nbcurv; j++)
{
//Standard_Integer trim = Standard_False; // skl
Handle(Geom2d_BSplineCurve) bsp;
if (j==1)
{
pc = pc1; first = first1; last = last1; /*trim = trimmed1;*/
} // skl
else
{
pc = pc2; first = first2; last = last2; /*trim = trimmed2;*/
} // skl
// Convert pcurve to bspline
if (pc->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)))
{
bsp = Handle(Geom2d_BSplineCurve)::DownCast(pc->Copy());
// take segment if trim and range differ
Standard_Real fbsp = bsp->FirstParameter(), lbsp = bsp->LastParameter();
Standard_Boolean segment = Standard_False;
if (first>fbsp)
{
fbsp = first; segment = Standard_True;
}
if (last<lbsp)
{
lbsp = last; segment = Standard_True;
}
if (segment)
bsp = Geom2dConvert::SplitBSplineCurve(bsp,fbsp,lbsp,
::Precision::PConfusion());
}
else if (pc->IsKind(STANDARD_TYPE(Geom2d_Conic)))
{
GeomAdaptor_Surface& AS = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface();
Standard_Real tolu = AS.UResolution(myAnalyzer->Precision()),
tolv = AS.VResolution(myAnalyzer->Precision());
Approx_Curve2d Conv(new Geom2dAdaptor_HCurve(pc,first,last),
first,last,tolu,tolv,GeomAbs_C1,9,1000);
if (Conv.IsDone() || Conv.HasResult()) bsp = Conv.Curve();
}
else
{
// Restore trim for pcurve
try
{
OCC_CATCH_SIGNALS
Handle(Geom2d_Curve) c;
// 15.11.2002 PTV OCC966
if(!ShapeAnalysis_Curve::IsPeriodic(pc))
c = new Geom2d_TrimmedCurve(pc,Max(first,pc->FirstParameter()),Min(last,pc->LastParameter()));
else
c = new Geom2d_TrimmedCurve(pc,first,last);
bsp = Geom2dConvert::CurveToBSplineCurve(c);
}
catch (Standard_Failure)
{
#ifdef DEB
cout << "Warning: ShapeFix_Wire_1::FixGap2d: Exception in TrimmedCurve2d" <<first<<" " <<last<<endl;
Standard_Failure::Caught()->Print(cout); cout << endl;
#endif
}
}
if (j==1) bsp1 = bsp; else bsp2 = bsp;
}
// Take curves ends if could not convert
gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
if (bsp1.IsNull()) mpnt = cpnt1;
else if (bsp2.IsNull()) mpnt = cpnt2;
if (!bsp1.IsNull())
{
if(bsp1->Degree() == 1) bsp1->IncreaseDegree(2);
if (n1==n2)
{
bsp1->SetPole(1,mpnt); bsp1->SetPole(bsp1->NbPoles(),mpnt);
}
else
{
if (reversed1) bsp1->SetPole(1,mpnt);
else bsp1->SetPole(bsp1->NbPoles(),mpnt);
}
first1 = bsp1->FirstParameter(); last1 = bsp1->LastParameter();
pc1 = bsp1;
done1 = Standard_True;
}
if (!bsp2.IsNull())
{
if(bsp2->Degree() == 1) bsp2->IncreaseDegree(2);
if (reversed2) bsp2->SetPole(bsp2->NbPoles(),mpnt);
else bsp2->SetPole(1,mpnt);
first2 = bsp2->FirstParameter(); last2 = bsp2->LastParameter();
pc2 = bsp2;
done2 = Standard_True;
}
}
else
{
if (n1==n2)
{
if (pc1->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
pc1->IsKind(STANDARD_TYPE(Geom2d_Ellipse)))
{
Standard_Real diff = M_PI - Abs(clast1-cfirst2)*0.5;
first1 -= diff; last1 += diff;
done1 = Standard_True;
}
}
else
{
// Determine domains for extremal points locating
Standard_Real domfirst1 = first1, domlast1 = last1;
if (pc1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ||
pc1->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)))
{
domfirst1 = pc1->FirstParameter();
domlast1 = pc1->LastParameter();
}
else if (pc1->IsKind(STANDARD_TYPE(Geom2d_Line)) ||
pc1->IsKind(STANDARD_TYPE(Geom2d_Parabola)) ||
pc1->IsKind(STANDARD_TYPE(Geom2d_Hyperbola)))
{
Standard_Real diff = domlast1 - domfirst1;
if (reversed1) domfirst1 -= 10.*diff;
else domlast1 += 10.*diff;
}
else if (pc1->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
pc1->IsKind(STANDARD_TYPE(Geom2d_Ellipse)))
{
domfirst1 = 0.; domlast1 = 2*M_PI;
}
Standard_Real domfirst2 = first2, domlast2 = last2;
if (pc2->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) ||
pc2->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)))
{
domfirst2 = pc2->FirstParameter();
domlast2 = pc2->LastParameter();
}
else if (pc2->IsKind(STANDARD_TYPE(Geom2d_Line)) ||
pc2->IsKind(STANDARD_TYPE(Geom2d_Parabola)) ||
pc2->IsKind(STANDARD_TYPE(Geom2d_Hyperbola)))
{
Standard_Real diff = domlast2 - domfirst2;
if (reversed2) domlast2 += 10.*diff;
else domfirst2 -= 10.*diff;
}
else if (pc2->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
pc2->IsKind(STANDARD_TYPE(Geom2d_Ellipse)))
{
domfirst2 = 0.; domlast2 = 2*M_PI;
}
Standard_Real ipar1 = clast1, ipar2 = cfirst2;
Geom2dInt_GInter Inter;
Standard_Real tolint = ::Precision::PConfusion();
Geom2dAdaptor_Curve AC1(pc1), AC2(pc2);
// Try to find intersection points
IntRes2d_Domain dom1(pc1->Value(domfirst1),domfirst1,tolint,
pc1->Value(domlast1),domlast1,tolint);
IntRes2d_Domain dom2(pc2->Value(domfirst2),domfirst2,tolint,
pc2->Value(domlast2),domlast2,tolint);
Inter.Perform( AC1, dom1, AC2, dom2, tolint, tolint );
if (Inter.IsDone())
{
if (Inter.NbPoints() || Inter.NbSegments())
{
Standard_Integer i, index1 = 0, index2 = 0;
Standard_Real pardist, pardist1=-1., pardist2=-1.;
// iterate on intersection points
IntRes2d_IntersectionPoint IP;
for ( i=1; i<=Inter.NbPoints(); i++ )
{
IP = Inter.Point(i);
// Adjust parameters on periodic curves
Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
IP.ParamOnFirst());
Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
IP.ParamOnSecond());
pardist = Abs(cfirst1-u1);
if (pardist1>pardist || pardist1<0.)
{
index1 = i; pardist1 = pardist;
}
pardist = Abs(clast2-u2);
if (pardist2>pardist || pardist2<0.)
{
index2 = i; pardist2 = pardist;
}
}
Standard_Integer flag1 = 0, flag2 = 0;
// iterate on intersection segments
IntRes2d_IntersectionSegment IS;
for ( i=1; i<=Inter.NbSegments(); i++ )
{
IS = Inter.Segment(i);
for (Standard_Integer j=1; j<=2; j++)
{
if ((j==1 && IS.HasFirstPoint()) ||
(j==2 && IS.HasLastPoint()))
{
if (j==1) IP = IS.FirstPoint();
else IP = IS.LastPoint();
// Adjust parameters on periodic curves
Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
IP.ParamOnFirst());
Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
IP.ParamOnSecond());
pardist = Abs(cfirst1-u1);
if (pardist1>pardist || pardist1<0.)
{
flag1 = j; index1 = i; pardist1 = pardist;
}
pardist = Abs(clast2-u2);
if (pardist2>pardist || pardist2<0.)
{
flag2 = j; index2 = i; pardist2 = pardist;
}
}
}
}
if (index1!=index2 || flag1!=flag2)
{
// take intersection closer to mean point
gp_Pnt2d pt1, pt2;
if (flag1==0) pt1 = Inter.Point(index1).Value();
else
{
IS = Inter.Segment(index1);
if (flag1==1) pt1 = IS.FirstPoint().Value();
else pt1 = IS.LastPoint().Value();
}
if (flag2==0) pt2 = Inter.Point(index2).Value();
else
{
IS = Inter.Segment(index2);
if (flag2==1) pt2 = IS.FirstPoint().Value();
else pt2 = IS.LastPoint().Value();
}
gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
if (pt2.Distance(mpnt) < pt1.Distance(mpnt))
{
index1 = index2; flag1 = flag2;
}
}
if (flag1==0) IP = Inter.Point(index1);
else
{
IS = Inter.Segment(index1);
if (flag1==1) IP = IS.FirstPoint();
else IP = IS.LastPoint();
}
// Ajust parameters on periodic curves
Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,
IP.ParamOnFirst());
Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,
IP.ParamOnSecond());
// Check points to satisfy distance criterium
gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
if (p1.Distance(p2)<=gap &&
Abs(cfirst1-u1) > ::Precision::PConfusion() &&
Abs(clast2 -u2) > ::Precision::PConfusion() &&
(((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
(cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
{
ipar1 = u1; ipar2 = u2;
done1 = done2 = Standard_True;
}
}
}
// Try to find closest points if nothing yet found
if (!done1)
{
Geom2dAPI_ExtremaCurveCurve Extr(pc1,pc2,domfirst1,domlast1,domfirst2,domlast2);
if (Extr.NbExtrema())
{
Standard_Real u1, u2;
Extr.LowerDistanceParameters(u1,u2);
// Ajust parameters on periodic curves
u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
// Check points to satisfy distance criterium
gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
if (p1.Distance(p2)<=gap &&
Abs(cfirst1-u1) > ::Precision::PConfusion() &&
Abs(clast2 -u2) > ::Precision::PConfusion() &&
(((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
(cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
{
ipar1 = u1; ipar2 = u2;
done1 = done2 = Standard_True;
}
}
}
// Try to find projections if nothing yet found
if (!done1)
{
Geom2dAPI_ProjectPointOnCurve Proj;
gp_Pnt2d ipnt1 = cpnt1, ipnt2 = cpnt2;
Standard_Real u1 = ipar1, u2 = ipar2;
Proj.Init(cpnt2,pc1,domfirst1,domlast1);
if (Proj.NbPoints())
{
Standard_Integer index = 1;
Standard_Real dist, mindist=-1.;
for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
{
dist = cpnt2.Distance(Proj.Point(i));
if (mindist>dist || mindist<0.)
{
index = i; mindist = dist;
}
ipnt1 = Proj.Point(index);
u1 = Proj.Parameter(index);
}
}
Proj.Init(cpnt1,pc2,domfirst2,domlast2);
if (Proj.NbPoints())
{
Standard_Integer index = 1;
Standard_Real dist, mindist=-1.;
for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
{
dist = cpnt1.Distance(Proj.Point(i));
if (mindist>dist || mindist<0.)
{
index = i; mindist = dist;
}
ipnt2 = Proj.Point(index);
u2 = Proj.Parameter(index);
}
}
// Ajust parameters on periodic curves
u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
// Process special case of projection
if ((((reversed1 && u1>clast1) || (!reversed1 && u1<clast1)) &&
((reversed2 && u2<cfirst2) || (!reversed2 && u2>cfirst2))) ||
(((reversed1 && u1<clast1) || (!reversed1 && u1>clast1)) &&
((reversed2 && u2>cfirst2) || (!reversed2 && u2<cfirst2))))
{
// both projections lie inside/outside initial domains
// project mean point
gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5);
u1 = ipar1; u2 = ipar2;
Proj.Init(mpnt,pc1,domfirst1,domlast1);
if (Proj.NbPoints())
{
Standard_Integer index = 1;
Standard_Real dist, mindist=-1.;
for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
{
dist = mpnt.Distance(Proj.Point(i));
if (mindist>dist || mindist<0.)
{
index = i; mindist = dist;
}
ipnt1 = Proj.Point(index);
u1 = Proj.Parameter(index);
}
}
Proj.Init(mpnt,pc2,domfirst2,domlast2);
if (Proj.NbPoints())
{
Standard_Integer index = 1;
Standard_Real dist, mindist=-1.;
for (Standard_Integer i=1; i<=Proj.NbPoints(); i++)
{
dist = mpnt.Distance(Proj.Point(i));
if (mindist>dist || mindist<0.)
{
index = i; mindist = dist;
}
ipnt2 = Proj.Point(index);
u2 = Proj.Parameter(index);
}
}
}
else
{
if (cpnt1.Distance(ipnt2)<cpnt2.Distance(ipnt1)) u1 = ipar1;
else u2 = ipar2;
}
// Ajust parameters on periodic curves
u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1);
u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2);
// Check points to satisfy distance criterium
gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2);
if (p1.Distance(p2)<=gap &&
Abs(cfirst1-u1) > ::Precision::PConfusion() &&
Abs(clast2 -u2) > ::Precision::PConfusion() &&
(((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) ||
(cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap)))
{
ipar1 = u1; ipar2 = u2;
done1 = done2 = Standard_True;
}
}
if (done1)
{
if (ipar1<first1 || ipar1>last1 || ipar2<first2 || ipar2>last2)
{
// Check whether new points lie inside the surface bounds
Standard_Real umin, umax, vmin, vmax;
myAnalyzer->Surface()->Surface()->Bounds(umin,umax,vmin,vmax);
if (::Precision::IsInfinite(umin) || ::Precision::IsInfinite(umax) ||
::Precision::IsInfinite(vmin) || ::Precision::IsInfinite(vmax))
{
Standard_Real fumin, fumax, fvmin, fvmax;
BRepTools::UVBounds(face,fumin,fumax,fvmin,fvmax);
if (::Precision::IsInfinite(umin)) umin = fumin-preci;
if (::Precision::IsInfinite(umax)) umax = fumax+preci;
if (::Precision::IsInfinite(vmin)) vmin = fvmin-preci;
if (::Precision::IsInfinite(vmax)) vmax = fvmax+preci;
}
gp_Pnt2d ipnt, P1, P2;
Standard_Real u, v;
Standard_Boolean out;
// iterate on curves
for (Standard_Integer j=1; j<=2; j++)
{
if (j==1)
{
if (ipar1>=first1 && ipar1<=last1) continue;
ipnt = pc1->Value(ipar1);
}
else
{
if (ipar2>=first2 && ipar2<=last2) continue;
ipnt = pc2->Value(ipar2);
}
// iterate on bounding lines
for (Standard_Integer k=1; k<=2; k++)
{
u = ipnt.X(); v = ipnt.Y();
out = Standard_True;
if (k==1)
{
if (u<umin)
{
P1 = gp_Pnt2d(umin,vmin); P2 = gp_Pnt2d(umin,vmax);
}
else if (u>umax)
{
P1 = gp_Pnt2d(umax,vmin); P2 = gp_Pnt2d(umax,vmax);
}
else out = Standard_False;
}
else
{
if (v<vmin)
{
P1 = gp_Pnt2d(umin,vmin); P2 = gp_Pnt2d(umax,vmin);
}
else if (v>vmax)
{
P1 = gp_Pnt2d(umin,vmax); P2 = gp_Pnt2d(umax,vmax);
}
else out = Standard_False;
}
if (out)
{
// Intersect pcurve with bounding line
Handle(Geom2d_Line) lin = new Geom2d_Line(P1,gp_Dir2d(gp_Vec2d(P1,P2)));
Geom2dAdaptor_Curve ACL(lin);
IntRes2d_Domain dlin(P1,0.,tolint,P2,P1.Distance(P2),tolint);
Handle(Geom2d_Curve) pc;
Standard_Real fpar, lpar;
if (j==1)
{
if (cfirst1<ipar1)
{
fpar = cfirst1, lpar = ipar1;
}
else
{
fpar = ipar1, lpar = cfirst1;
}
pc = pc1;
}
else
{
if (clast2<ipar2)
{
fpar = clast2, lpar = ipar2;
}
else
{
fpar = ipar2, lpar = clast2;
}
pc = pc2;
}
Geom2dAdaptor_Curve ACC(pc);
IntRes2d_Domain domc(pc->Value(fpar),fpar,tolint,
pc->Value(lpar),lpar,tolint);
// Intersect line with the pcurve
Inter.Perform( ACL, dlin, ACC, domc, tolint, tolint );
if (Inter.IsDone())
{
if (Inter.NbPoints() || Inter.NbSegments())
{
Standard_Integer i, index = 1;
Standard_Real uu, dist, mindist=-1.;
// iterate on intersection points
for ( i=1; i<=Inter.NbPoints(); i++ )
{
// Adjust parameters on periodic curve
uu = AdjustOnPeriodic2d(pc,(j==1? reversed1 : !reversed2),
fpar,lpar,Inter.Point(i).ParamOnSecond());
dist = Abs((j==1? cfirst1 : clast2)-uu);
if (mindist>dist || mindist<0.)
{
index = i; mindist = dist;
}
}
// iterate on intersection segments
Standard_Integer flag = 0;
IntRes2d_IntersectionPoint IP;
IntRes2d_IntersectionSegment IS;
for ( i=1; i<=Inter.NbSegments(); i++ )
{
IS = Inter.Segment(i);
for (Standard_Integer jj=1; jj<=2; jj++)
{
if ((jj==1 && IS.HasFirstPoint()) ||
(jj==2 && IS.HasLastPoint()))
{
if (jj==1) IP = IS.FirstPoint();
else IP = IS.LastPoint();
// Adjust parameters on periodic curve
uu = AdjustOnPeriodic2d(pc,(jj==1? reversed1 : !reversed2),
fpar,lpar,IP.ParamOnSecond());
dist = Abs((jj==1? cfirst1 : clast2)-uu);
if (mindist>dist || mindist<0.)
{
flag = jj; index = i; mindist = dist;
}
}
}
}
if (flag==0) IP = Inter.Point(index);
else
{
IS = Inter.Segment(index);
if (flag==1) IP = IS.FirstPoint();
else IP = IS.LastPoint();
}
// Ajust parameters on periodic curve
uu = AdjustOnPeriodic2d(pc,(j==1? reversed1 : !reversed2),
fpar,lpar,IP.ParamOnSecond());
if (j==1 && Abs(cfirst1-uu) > ::Precision::PConfusion())
{
ipar1 = uu; ipnt = IP.Value();
}
if (j==2 && Abs(clast2-uu) > ::Precision::PConfusion())
{
ipar2 = uu; ipnt = IP.Value();
}
}
}
}
}
// Adjust if intersection lies inside old bounds
if (j==1)
{
if (reversed1)
{
if (ipar1>first1) ipar1 = first1;
}
else
{
if (ipar1<last1) ipar1 = last1;
}
}
else
{
if (reversed2)
{
if (ipar2<last2) ipar2 = last2;
}
else
{
if (ipar2>first2) ipar2 = first2;
}
}
}
}
}
try
{
OCC_CATCH_SIGNALS
if (done1)
{
if (ipar1==clast1) done1 = Standard_False;
else
{
// Set up new bounds for pcurve
if (reversed1) first1 = ipar1; else last1 = ipar1;
// Set new trim for old pcurve
if (trimmed1) pc1 = new Geom2d_TrimmedCurve(pc1,first1,last1);
}
}
if (done2)
{
if (ipar2==cfirst2) done2 = Standard_False;
else
{
// Set up new bounds for pcurve
if (reversed2) last2 = ipar2; else first2 = ipar2;
// Set new trim for old pcurve
if (trimmed2) pc2 = new Geom2d_TrimmedCurve(pc2,first2,last2);
}
}
}
catch (Standard_Failure)
{
#ifdef DEB
cout << "Warning: ShapeFix_Wire_1::FixGap2d: Exception in TrimmedCurve2d :"<<endl;
Standard_Failure::Caught()->Print(cout); cout << endl;
#endif
}
}
}
if (done1 || done2)
{
BRep_Builder B;
ShapeBuild_Edge SBE;
ShapeFix_ShapeTolerance SFST;
// Update vertices
TopoDS_Vertex V1 = SAE.LastVertex(E1), V2 = SAE.FirstVertex(E2);
TopoDS_Vertex nullV, newV1;
//smh#8
TopoDS_Shape emptyCopiedV2 = V2.EmptyCopied();
TopoDS_Vertex newV2 = TopoDS::Vertex(emptyCopiedV2);
SFST.SetTolerance(newV2,::Precision::Confusion());
Context()->Replace(V2,newV2);
if (V1.IsSame(V2))
//smh#8
{
TopoDS_Shape tmpVertexRev = newV2.Oriented(TopAbs_REVERSED);
newV1 = TopoDS::Vertex(tmpVertexRev);
}
else
{
//smh#8
TopoDS_Shape emptyCopiedV1 = V1.EmptyCopied();
newV1 = TopoDS::Vertex(emptyCopiedV1);
SFST.SetTolerance(newV1,::Precision::Confusion());
Context()->Replace(V1,newV1);
}
if (done1)
{
// Update first edge
TopoDS_Edge newE1 = SBE.CopyReplaceVertices(E1,nullV,newV1);
//smh#8
TopoDS_Shape tmpE1 = newE1.Oriented(TopAbs_FORWARD);
B.UpdateEdge(TopoDS::Edge(tmpE1),pc1,face,0.);
B.Range(TopoDS::Edge(tmpE1),face,first1,last1);
SFST.SetTolerance(newE1,::Precision::Confusion(),TopAbs_EDGE);
B.SameRange(newE1,Standard_False);
// B.SameParameter(newE1,Standard_False);
//To keep NM vertices belonging initial edges
TopoDS_Iterator aItv(E1,Standard_False);
for( ; aItv.More(); aItv.Next()) {
if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
aItv.Value().Orientation() == TopAbs_EXTERNAL) {
TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE1,E1);
B.Add(newE1,anewV);
Context()->Replace(aOldV,anewV);
}
}
Context()->Replace(E1,newE1);
sbwd->Set(newE1,n1);
}
if (done2)
{
// Update second edge
TopoDS_Edge newE2 = SBE.CopyReplaceVertices(E2,newV2,nullV);
//smh#8
TopoDS_Shape tmpE2 = newE2.Oriented(TopAbs_FORWARD);
B.UpdateEdge(TopoDS::Edge(tmpE2),pc2,face,0.);
B.Range(TopoDS::Edge(tmpE2),face,first2,last2);
SFST.SetTolerance(newE2,::Precision::Confusion(),TopAbs_EDGE);
B.SameRange(newE2,Standard_False);
// B.SameParameter(newE2,Standard_False);
//To keep NM vertices belonging initial edges
TopoDS_Iterator aItv(E2,Standard_False);
for( ; aItv.More(); aItv.Next()) {
if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
aItv.Value().Orientation() == TopAbs_EXTERNAL) {
TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE2,E2);
B.Add(newE2,anewV);
Context()->Replace(aOldV,anewV);
}
}
Context()->Replace(E2,newE2);
sbwd->Set(newE2,n2);
}
myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
}
else
if (convert)
myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );
return (done1 || done2);
}