A tool to remove tails from the wires of a shape was created.
The tool is based on mechanism 'ShapeFix',
is located in types 'ShapeFix_Wire' and 'ShapeAnalysis_Wire',
is enabled through method 'ShapeFix_Wire::FixTailMode' and
is initialized by methods 'ShapeFix_Wire::SetMaxTailAngle' and 'ShapeFix_Wire::SetMaxTailWidth' and
is called through method 'ShapeFix_Wire::FixTails'.
The status of any performing of the last method is accessible through method 'ShapeFix_Wire::StatusFixTails'.
The tail angle is checked only at the tail start.
Mechanism 'ShapeFix' was modified:
- the tool is disabled by default;
- algorithm 'Fix notched edges' is disabled then the tool is enabled;
- the tool and the last algorithm work in turns then the tool works on the request.
'Draw' command 'fixshape' was extended by options '-maxtaila' and '-maxtailw' to test the tool.
'Draw' tests to test the tool were created.
Algorithm 'fixshape' was changed in type 'ShapeProcess_OperLibrary' to
- use new parameters named 'FixTailMode', 'MaxTailAngle' (in degrees) and 'MaxTailWidth' from the algorithm context;
- apply the tool after the shape will be fully fixed if the tool was enabled.
Place holders for the new parameters were created in the resource file of mechsnism 'STEPControl_Reader'.
Test cases for issue CR26261
Standard_CString res = 0;
Standard_Integer par = 0, mess=0;
- for ( Standard_Integer i=1; i < argc; i++ ) {
- if ( argv[i][0] == '-' || argv[i][0] == '+' || argv[i][0] == '*' ) {
+ for ( Standard_Integer i=1; i < argc; i++ )
+ {
+ if (strlen(argv[i]) == 2 &&
+ (argv[i][0] == '-' || argv[i][0] == '+' || argv[i][0] == '*'))
+ {
Standard_Integer val = ( argv[i][0] == '-' ? 0 : argv[i][0] == '+' ? 1 : -1 );
switch ( argv[i][1] ) {
case 'l': sfs->FixWireTool()->FixLackingMode() = val; break;
}
continue;
}
- else {
+ else if (!strcmp(argv[i], "-maxtaila"))
+ {
+ if (++i >= argc)
+ {
+ break;
+ }
+
+ sfs->FixWireTool()->SetMaxTailAngle(Draw::Atof(argv[i]) * (M_PI / 180));
+ }
+ else if (!strcmp(argv[i], "-maxtailw"))
+ {
+ if (++i >= argc)
+ {
+ break;
+ }
+
+ sfs->FixWireTool()->SetMaxTailWidth(Draw::Atof(argv[i]));
+ sfs->FixWireTool()->FixTailMode() = 1;
+ }
+ else
+ {
switch ( par ) {
case 0: res = argv[i]; break;
case 1: {
}
if ( par <2 ) {
- di << "Use: " << argv[0] << " result shape [tolerance [max_tolerance]] [switches]" << "\n";
+ di << "Use: " << argv[0] << " result shape [tolerance [max_tolerance]] [switches]\n"
+ "[-maxtaila <degrees>] [-maxtailw <width>]" << "\n";
di << "Switches allow to tune parameters of ShapeFix" << "\n";
di << "The following syntax is used: <symbol><parameter>" << "\n";
di << "- symbol may be - to set parameter off, + to set on or * to set default" << "\n";
__FILE__,stwire,g);
theCommands.Add ("reface","shape result : controle sens wire",
__FILE__,reface,g);
- theCommands.Add ("fixshape","res shape [preci [maxpreci]] [{switches}]",
+ theCommands.Add ("fixshape",
+"res shape [preci [maxpreci]] [{switches}]\n"
+" [-maxtaila <degrees>] [-maxtailw <width>]",
__FILE__,fixshape,g);
// theCommands.Add ("testfill","result edge1 edge2",
// __FILE__,XSHAPE_testfill,g);
Shape from TopoDS,
Wire from TopoDS,
Face from TopoDS,
+ Edge from TopoDS,
SequenceOfIntersectionPoint from IntRes2d,
SequenceOfPnt from TColgp,
SequenceOfReal from TColStd,
aMapSeemEdges : out MapOfShape from TopTools) returns Boolean;
---Purpose: Checks existance of loop on wire and return vertices wich are loop vertices
-- (vertices belonging to a few pairs of edges)
+
+ CheckTail(me : mutable;
+ theEdge1: in Edge from TopoDS;
+ theEdge2: in Edge from TopoDS;
+ theMaxSine: in Real;
+ theMaxWidth: in Real;
+ theMaxTolerance: in Real;
+ theEdge11: out Edge from TopoDS;
+ theEdge12: out Edge from TopoDS;
+ theEdge21: out Edge from TopoDS;
+ theEdge22: out Edge from TopoDS) returns Boolean;
---Status after checking :
#include <Bnd_Box2d.hxx>
//szvsh addition
+#include <BRepGProp.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <GProp_GProps.hxx>
#include <Adaptor3d_CurveOnSurface.hxx>
#include <TColgp_SequenceOfPnt.hxx>
#include <ShapeAnalysis_Surface.hxx>
#include <TopoDS_Wire.hxx>
#include <ShapeAnalysis.hxx>
+#include <ShapeAnalysis_TransferParametersProj.hxx>
+#include <ShapeBuild_Edge.hxx>
#include <Geom_Plane.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopoDS_Iterator.hxx>
}
return Standard_False;
}
+
+//=======================================================================
+//function : Project
+//purpose :
+//=======================================================================
+static Standard_Real Project(
+ const Handle(Geom_Curve)& theCurve,
+ const Standard_Real theFirstParameter,
+ const Standard_Real theLastParameter,
+ const gp_Pnt& thePoint,
+ const Standard_Real thePrecision,
+ Standard_Real& theParameter,
+ gp_Pnt& theProjection)
+{
+ const Standard_Real aDist = ShapeAnalysis_Curve().Project(theCurve, thePoint,
+ thePrecision, theProjection, theParameter, theFirstParameter,
+ theLastParameter);
+ if (theParameter >= theFirstParameter && theParameter <= theLastParameter)
+ {
+ return aDist;
+ }
+
+ const Standard_Real aParams[] = {theFirstParameter, theLastParameter};
+ const gp_Pnt aPrjs[] =
+ {theCurve->Value(aParams[0]), theCurve->Value(aParams[1])};
+ const Standard_Real aDists[] =
+ {thePoint.Distance(aPrjs[0]), thePoint.Distance(aPrjs[1])};
+ const Standard_Integer aPI = (aDists[0] <= aDists[1]) ? 0 : 1;
+ theParameter = aParams[aPI];
+ theProjection = aPrjs[aPI];
+ return aDists[aPI];
+}
+
+//=======================================================================
+//function : CheckTail
+//purpose :
+//=======================================================================
+Standard_Boolean ShapeAnalysis_Wire::CheckTail(
+ const TopoDS_Edge& theEdge1,
+ const TopoDS_Edge& theEdge2,
+ const Standard_Real theMaxSine,
+ const Standard_Real theMaxWidth,
+ const Standard_Real theMaxTolerance,
+ TopoDS_Edge& theEdge11,
+ TopoDS_Edge& theEdge12,
+ TopoDS_Edge& theEdge21,
+ TopoDS_Edge& theEdge22)
+{
+ const TopoDS_Edge aEs[] = {theEdge1, theEdge2};
+ if (!IsReady() || BRep_Tool::Degenerated(aEs[0]) ||
+ BRep_Tool::Degenerated(aEs[1]))
+ {
+ return Standard_False;
+ }
+
+ // Check the distance between the edge common ends.
+ const Standard_Real aTol2 = theMaxWidth + 0.5 * Precision::Confusion();
+ const Standard_Real aTol3 = theMaxWidth + Precision::Confusion();
+ const Standard_Real aTol4 = theMaxWidth + 1.5 * Precision::Confusion();
+ const Standard_Real aSqTol2 = aTol2 * aTol2;
+ const Standard_Real aSqTol3 = aTol3 * aTol3;
+ Handle(Geom_Curve) aCs[2];
+ Standard_Real aLs[2][2];
+ Standard_Integer aVIs[2];
+ gp_Pnt aVPs[2];
+ {
+ for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
+ {
+ if (!ShapeAnalysis_Edge().Curve3d(
+ aEs[aEI], aCs[aEI], aLs[aEI][0], aLs[aEI][1], Standard_False))
+ {
+ return Standard_False;
+ }
+
+ aVIs[aEI] = (aEs[aEI].Orientation() == TopAbs_REVERSED) ? aEI : 1 - aEI;
+ aVPs[aEI] = aCs[aEI]->Value(aLs[aEI][aVIs[aEI]]);
+ }
+ if (aVPs[0].SquareDistance(aVPs[1]) > aSqTol2)
+ {
+ return Standard_False;
+ }
+ }
+
+ // Check the angle between the edges.
+ if (theMaxSine >= 0)
+ {
+ const Standard_Real aSqMaxSine = theMaxSine * theMaxSine;
+ gp_XYZ aDs[2];
+ Standard_Integer aReverse = 0;
+ for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
+ {
+ GeomAdaptor_Curve aCA(aCs[aEI]);
+ if (GCPnts_AbscissaPoint::Length(aCA, aLs[aEI][0], aLs[aEI][1],
+ 0.25 * Precision::Confusion()) < 0.5 * Precision::Confusion())
+ {
+ return Standard_False;
+ }
+
+ GCPnts_AbscissaPoint aAP(0.25 * Precision::Confusion(), aCA,
+ 0.5 * Precision::Confusion() * (1 - 2 * aVIs[aEI]),
+ aLs[aEI][aVIs[aEI]]);
+ if (!aAP.IsDone())
+ {
+ return Standard_False;
+ }
+
+ gp_XYZ aPs[2];
+ aPs[aVIs[aEI]] = aVPs[aEI].XYZ();
+ aPs[1 - aVIs[aEI]] = aCs[aEI]->Value(aAP.Parameter()).XYZ();
+ aDs[aEI] = aPs[1] - aPs[0];
+ const Standard_Real aDN = aDs[aEI].Modulus();
+ if (aDN < 0.1 * Precision::Confusion())
+ {
+ return Standard_False;
+ }
+
+ aDs[aEI] *= 1 / aDN;
+ aReverse ^= aVIs[aEI];
+ }
+ if (aReverse)
+ {
+ aDs[0].Reverse();
+ }
+ if (aDs[0] * aDs[1] < 0 || aDs[0].CrossSquareMagnitude(aDs[1]) > aSqMaxSine)
+ {
+ return Standard_False;
+ }
+ }
+
+ // Calculate the tail bounds.
+ gp_Pnt aPs[2], aPrjs[2];
+ Standard_Real aParams1[2], aParams2[2];
+ Standard_Real aDists[2];
+ Standard_Boolean isWholes[] = {Standard_True, Standard_True};
+ for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
+ {
+ Standard_Real aParam1 = aLs[aEI][aVIs[aEI]];
+ aParams1[aEI] = aLs[aEI][1 - aVIs[aEI]];
+ aCs[aEI]->D0(aParams1[aEI], aPs[aEI]);
+ aDists[aEI] = Project(aCs[1 - aEI], aLs[1 - aEI][0], aLs[1 - aEI][1],
+ aPs[aEI], 0.25 * Precision::Confusion(), aParams2[aEI], aPrjs[aEI]);
+ if (aDists[aEI] <= aTol2)
+ {
+ continue;
+ }
+
+ isWholes[aEI] = Standard_False;
+ for (;;)
+ {
+ const Standard_Real aParam = (aParam1 + aParams1[aEI]) * 0.5;
+ aCs[aEI]->D0(aParam, aPs[aEI]);
+ const Standard_Real aDist = Project(aCs[1 - aEI], aLs[1 - aEI][0],
+ aLs[1 - aEI][1], aPs[aEI], 0.25 * Precision::Confusion(), aParams2[aEI],
+ aPrjs[aEI]);
+ if (aDist <= aTol2)
+ {
+ aParam1 = aParam;
+ }
+ else
+ {
+ aParams1[aEI] = aParam;
+ if (aDist <= aTol3)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ // Check the tail bounds.
+ for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
+ {
+ const Standard_Real aParam1 = aLs[aEI][aVIs[aEI]];
+ const Standard_Real aParam2 = aParams1[aEI];
+ const Standard_Real aStepL = (aParam2 - aParam1) / 23;
+ for (Standard_Integer aStepN = 1; aStepN < 23; ++aStepN)
+ {
+ Standard_Real aParam = aParam1 + aStepN * aStepL;
+ gp_Pnt aP = aCs[aEI]->Value(aParam), aPrj;
+ if (Project(aCs[1 - aEI], aLs[1 - aEI][0], aLs[1 - aEI][1], aP,
+ 0.25 * Precision::Confusion(), aParam, aPrj) > aTol4)
+ {
+ return Standard_False;
+ }
+ }
+ }
+
+ // Check whether both edges must be removed.
+ if (isWholes[0] && isWholes[1] && aPs[0].SquareDistance(aPs[1]) <= aSqTol3)
+ {
+ theEdge11 = theEdge1;
+ theEdge21 = theEdge2;
+ return Standard_True;
+ }
+
+ // Cut and remove the edges.
+ Standard_Integer aFI = 0;
+ if (isWholes[0] || isWholes[1])
+ {
+ // Determine an edge to remove and the other one to cut.
+ aFI = isWholes[0] ? 0 : 1;
+ if (aDists[1 - aFI] < aDists[aFI] && isWholes[1 - aFI])
+ {
+ aFI = 1 - aFI;
+ }
+ }
+ Standard_Real aParams[2];
+ aParams[aFI] = aParams1[aFI];
+ aParams[1 - aFI] = aParams2[aFI];
+
+ // Correct the cut for the parametrization tolerance.
+ TopoDS_Edge* aEParts[][2] =
+ {{&theEdge11, &theEdge12}, {&theEdge21, &theEdge22}};
+ Standard_Integer aResults[] = {1, 1};
+ for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
+ {
+ if (Abs(aParams[aEI] - aLs[aEI][1 - aVIs[aEI]]) <= Precision::PConfusion())
+ {
+ aResults[aEI] = 2;
+ *aEParts[aEI][0] = aEs[aEI];
+ }
+ else if (Abs(aParams[aEI] - aLs[aEI][aVIs[aEI]]) <= Precision::PConfusion())
+ {
+ aResults[aEI] = 0;
+ }
+ }
+
+ // Correct the cut for the distance tolerance.
+ for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
+ {
+ if (aResults[aEI] != 1)
+ {
+ continue;
+ }
+
+ // Create the parts of the edge.
+ TopoDS_Edge aFE = TopoDS::Edge(aEs[aEI].Oriented(TopAbs_FORWARD));
+ ShapeAnalysis_TransferParametersProj aSATPP(aFE, TopoDS_Face());
+ aSATPP.SetMaxTolerance(theMaxTolerance);
+ TopoDS_Vertex aSplitV;
+ BRep_Builder().MakeVertex(
+ aSplitV, aCs[aEI]->Value(aParams[aEI]), Precision::Confusion());
+ TopoDS_Edge aEParts2[] = {
+ ShapeBuild_Edge().CopyReplaceVertices(aFE, TopoDS_Vertex(),
+ TopoDS::Vertex(aSplitV.Oriented(TopAbs_REVERSED))),
+ ShapeBuild_Edge().CopyReplaceVertices(aFE, aSplitV, TopoDS_Vertex())};
+ ShapeBuild_Edge().CopyPCurves(aEParts2[0], aFE);
+ ShapeBuild_Edge().CopyPCurves(aEParts2[1], aFE);
+ BRep_Builder().SameRange(aEParts2[0], Standard_False);
+ BRep_Builder().SameRange(aEParts2[1], Standard_False);
+ BRep_Builder().SameParameter(aEParts2[0], Standard_False);
+ BRep_Builder().SameParameter(aEParts2[1], Standard_False);
+ aSATPP.TransferRange(
+ aEParts2[0], aLs[aEI][0], aParams[aEI], Standard_False);
+ aSATPP.TransferRange(
+ aEParts2[1], aParams[aEI], aLs[aEI][1], Standard_False);
+ GProp_GProps aLinProps;
+ BRepGProp::LinearProperties(aEParts2[1 - aVIs[aEI]], aLinProps);
+ if (aLinProps.Mass() <= Precision::Confusion())
+ {
+ aResults[aEI] = 2;
+ *aEParts[aEI][0] = aEs[aEI];
+ }
+ else
+ {
+ BRepGProp::LinearProperties(aEParts2[aVIs[aEI]], aLinProps);
+ if (aLinProps.Mass() <= Precision::Confusion())
+ {
+ aResults[aEI] = 0;
+ }
+ else
+ {
+ *aEParts[aEI][0] = aEParts2[0];
+ *aEParts[aEI][1] = aEParts2[1];
+ }
+ }
+ }
+
+ return aResults[0] + aResults[1] != 0;
+}
theAdvFixWire->StatusConnected(ShapeExtend_DONE) ||
theAdvFixWire->StatusEdgeCurves(ShapeExtend_DONE) ||
theAdvFixWire->StatusNotches(ShapeExtend_DONE) || // CR0024983
+ theAdvFixWire->StatusFixTails(ShapeExtend_DONE) ||
theAdvFixWire->StatusDegenerated(ShapeExtend_DONE) ||
theAdvFixWire->StatusClosed(ShapeExtend_DONE));
TopoDS_Wire w = theAdvFixWire->Wire();
}
if ( theAdvFixWire->Perform() ) {
isfixReorder = theAdvFixWire->StatusReorder(ShapeExtend_DONE);
- fixed = (theAdvFixWire->StatusLacking(ShapeExtend_DONE) ||
- theAdvFixWire->StatusSelfIntersection(ShapeExtend_DONE) ||
- theAdvFixWire->StatusNotches(ShapeExtend_DONE)); //Standard_True;
+ fixed = (theAdvFixWire->StatusLacking(ShapeExtend_DONE) ||
+ theAdvFixWire->StatusSelfIntersection(ShapeExtend_DONE) ||
+ theAdvFixWire->StatusNotches(ShapeExtend_DONE) ||
+ theAdvFixWire->StatusFixTails(ShapeExtend_DONE));
TopoDS_Wire w = theAdvFixWire->Wire();
if(fixed) {
if ( ! Context().IsNull() ) Context()->Replace ( wire, w );
-- a) Wire (ether TopoDS_Wire or ShapeExtend_Wire)
-- b) Face or surface
-- c) Precision
+ -- d) Maximal tail angle and width
-- This can be done either by calling corresponding methods
- -- (LoadWire, SetFace or SetSurface, and SetPrecision), or
+ -- (LoadWire, SetFace or SetSurface, SetPrecision, SetMaxTailAngle
+ -- and SetMaxTailWidth), or
-- by loading already filled ShapeAnalisis_Wire with method Load
uses
SetPrecision (me: mutable; prec: Real) is redefined;
---Purpose: Set working precision (to root and to analyzer)
+ SetMaxTailAngle (me: mutable; theMaxTailAngle: Real);
+ ---Purpose: Sets the maximal allowed angle of the tails in radians.
+
+ SetMaxTailWidth (me: mutable; theMaxTailWidth: Real);
+ ---Purpose: Sets the maximal allowed width of the tails.
+
IsLoaded (me) returns Boolean;
---C++: inline
---Purpose: Tells if the wire is loaded
-- -1 default
-- 1 method will be called
-- 0 method will not be called
+ FixTailMode(me: mutable) returns Integer;
+ ---C++: inline
+ ---C++: return &
--- Fixing methods:
-- FAIL1 - There was no pcurve found on some edge
-- FAIL2 - Method failed to fix the gap
+ FixTails(me: mutable) returns Boolean;
+
--- Result of fixes:
StatusReorder (me; status: Status from ShapeExtend) returns Boolean;
-- DONE: some problem(s) was(were) detected and successfully fixed
-- FAIL: some problem(s) cannot be fixed
---Level : Public (API)
+ StatusFixTails(me; status: Status from ShapeExtend) returns Boolean;
+ ---C++: inline
+
LastFixStatus (me; status: Status from ShapeExtend) returns Boolean;
---C++: inline
---Purpose: Queries the status of last call to methods Fix... of
myFixSelfIntersectingEdgeMode: Integer is protected;
myFixIntersectingEdgesMode: Integer is protected;
myFixNonAdjacentIntersectingEdgesMode: Integer is protected;
+ myFixTailMode: Integer is protected;
myRemoveLoopMode: Integer is protected;
-- -1 - old variant (default)
myStatusGaps2d: Integer is protected;
myStatusRemovedSegment: Boolean is protected;
myStatusNotches: Integer is protected;
+ myStatusFixTails: Integer is protected;
+ myMaxTailAngleSine: Real is protected;
+ myMaxTailWidth: Real is protected;
end Wire;
//purpose :
//=======================================================================
-ShapeFix_Wire::ShapeFix_Wire()
+ShapeFix_Wire::ShapeFix_Wire() : myMaxTailAngleSine(0), myMaxTailWidth(-1)
{
myFixEdge = new ShapeFix_Edge;
myAnalyzer = new ShapeAnalysis_Wire;
//purpose :
//=======================================================================
-ShapeFix_Wire::ShapeFix_Wire (const TopoDS_Wire& wire,
- const TopoDS_Face &face, const Standard_Real prec)
+ShapeFix_Wire::ShapeFix_Wire (
+ const TopoDS_Wire& wire,
+ const TopoDS_Face &face,
+ const Standard_Real prec) : myMaxTailAngleSine(0), myMaxTailWidth(-1)
{
myFixEdge = new ShapeFix_Edge;
myAnalyzer = new ShapeAnalysis_Wire;
myAnalyzer->SetPrecision ( prec );
}
+//=======================================================================
+//function : SetMaxTailAngle
+//purpose :
+//=======================================================================
+void ShapeFix_Wire::SetMaxTailAngle(const Standard_Real theMaxTailAngle)
+{
+ myMaxTailAngleSine = Sin(theMaxTailAngle);
+ myMaxTailAngleSine = (myMaxTailAngleSine >= 0) ? myMaxTailAngleSine : 0;
+}
+
+//=======================================================================
+//function : SetMaxTailWidth
+//purpose :
+//=======================================================================
+void ShapeFix_Wire::SetMaxTailWidth(const Standard_Real theMaxTailWidth)
+{
+ myMaxTailWidth = theMaxTailWidth;
+}
+
//=======================================================================
//function : ClearModes
//purpose :
myFixSelfIntersectingEdgeMode = -1;
myFixIntersectingEdgesMode = -1;
myFixNonAdjacentIntersectingEdgesMode = -1;
+ myFixTailMode = 0;
myFixReorderMode = -1;
myFixSmallMode = -1;
myStatusGaps3d = emptyStatus; //szv#9:S4244:19Aug99 new method introduced
myStatusGaps2d = emptyStatus; //szv#9:S4244:19Aug99 new method introduced
myStatusClosed = emptyStatus;
+ myStatusNotches = emptyStatus;
+ myStatusFixTails = emptyStatus;
}
//=======================================================================
}
//pdn - temporary to test
- if ( NeedFix ( myFixNotchedEdgesMode, ReorderOK ) ) {
+ if (myFixTailMode <= 0 && NeedFix(myFixNotchedEdgesMode, ReorderOK))
+ {
Fixed |= FixNotchedEdges();
if(Fixed) FixShifted(); //skl 07.03.2002 for OCC180
}
+ if (myFixTailMode != 0)
+ {
+ Fixed |= FixTails();
+ if (Fixed)
+ {
+ FixShifted();
+ }
+ }
+
if ( NeedFix ( myFixSelfIntersectionMode, myClosedMode ) ) {
Standard_Integer savFixIntersectingEdgesMode = myFixIntersectingEdgesMode;
// switch off FixIntEdges if reorder not done
sbwd->Remove ( i-- );
}
}
+
+//=======================================================================
+//function : FixTails
+//purpose :
+//=======================================================================
+Standard_Boolean ShapeFix_Wire::FixTails()
+{
+ if (myMaxTailWidth < 0 || !IsReady())
+ {
+ return Standard_False;
+ }
+
+ myLastFixStatus = ShapeExtend::EncodeStatus(ShapeExtend_OK);
+ if (!Context().IsNull())
+ {
+ UpdateWire();
+ }
+ Handle(ShapeExtend_WireData) aSEWD = WireData();
+ Standard_Integer aECount = NbEdges(), aENs[] = {aECount, 1};
+ Standard_Boolean aCheckAngle = Standard_True;
+ while (aECount >= 2 && aENs[1] <= aECount)
+ {
+ const TopoDS_Edge aEs[] = {aSEWD->Edge(aENs[0]), aSEWD->Edge(aENs[1])};
+ TopoDS_Edge aEParts[2][2];
+ if (!myAnalyzer->CheckTail(aEs[0], aEs[1],
+ aCheckAngle ? myMaxTailAngleSine : -1, myMaxTailWidth, MaxTolerance(),
+ aEParts[0][0], aEParts[0][1], aEParts[1][0], aEParts[1][1]))
+ {
+ aENs[0] = aENs[1]++;
+ aCheckAngle = Standard_True;
+ continue;
+ }
+
+ // Provide not less than 1 edge in the result wire.
+ Standard_Integer aSplitCounts[] =
+ {aEParts[0][1].IsNull() ? 0 : 1, aEParts[1][1].IsNull() ? 0 : 1};
+ const Standard_Integer aRemoveCount =
+ (aEParts[0][0].IsNull() ? 0 : 1) + (aEParts[1][0].IsNull() ? 0 : 1);
+ if (aECount + aSplitCounts[0] + aSplitCounts[1] < 1 + aRemoveCount)
+ {
+ aENs[0] = aENs[1]++;
+ aCheckAngle = Standard_True;
+ continue;
+ }
+
+ // Split the edges.
+ for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
+ {
+ if (aSplitCounts[aEI] == 0)
+ {
+ continue;
+ }
+
+ // Replace the edge by the wire of its parts in the shape.
+ const TopoDS_Edge aE = aEs[aEI];
+ if (!Context().IsNull())
+ {
+ TopoDS_Wire aEWire;
+ BRep_Builder().MakeWire(aEWire);
+ BRep_Builder().Add(aEWire, aEParts[aEI][0]);
+ BRep_Builder().Add(aEWire, aEParts[aEI][1]);
+ TopoDS_Edge aFE = TopoDS::Edge(aE.Oriented(TopAbs_FORWARD));
+ Context()->Replace(aFE, aEWire);
+ }
+
+ // Replace the edge by its parts in the edge wire.
+ const TopAbs_Orientation aOrient = aE.Orientation();
+ aEParts[aEI][0].Orientation(aOrient);
+ aEParts[aEI][1].Orientation(aOrient);
+ const Standard_Integer aFirstPI = (aOrient != TopAbs_REVERSED) ? 0 : 1;
+ const Standard_Integer aAdd =
+ (aEI == 0 || aENs[1] < aENs[0]) ? 0 : aSplitCounts[0];
+ aSEWD->Set(aEParts[aEI][aFirstPI], aENs[aEI] + aAdd);
+ aSEWD->Add(aEParts[aEI][1 - aFirstPI], aENs[aEI] + 1 + aAdd);
+ }
+
+ // Remove the tail.
+ if (aRemoveCount == 2)
+ {
+ aCheckAngle = Standard_True;
+ FixDummySeam(aENs[0] + aSplitCounts[0] +
+ ((aENs[0] < aENs[1]) ? 0 : aSplitCounts[1]));
+ if (!Context().IsNull())
+ {
+ UpdateWire();
+ }
+ myLastFixStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE);
+
+ if (aSplitCounts[0] + aSplitCounts[1] == 2)
+ {
+ aENs[0] = aENs[1]++;
+ continue;
+ }
+
+ if (aSplitCounts[0] == aSplitCounts[1])
+ {
+ aECount -= 2;
+ if (aENs[1] >= 3)
+ {
+ --aENs[0];
+ --aENs[1];
+ }
+ else
+ {
+ aENs[0] = aECount;
+ aENs[1] = 1;
+ }
+ aCheckAngle = Standard_False;
+ }
+ else
+ {
+ --aECount;
+ if (aSplitCounts[0] != 0)
+ {
+ aENs[0] = (aENs[0] <= aECount) ? aENs[0] : aECount;
+ }
+ else
+ {
+ if (aENs[1] >= 3)
+ {
+ --aENs[0];
+ --aENs[1];
+ }
+ else
+ {
+ aENs[0] = aECount;
+ aENs[1] = 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ aCheckAngle = Standard_False;
+ --aECount;
+ const Standard_Integer aRI = aEParts[0][0].IsNull() ? 1 : 0;
+ if (aSplitCounts[aRI] != 0)
+ {
+ if (aRI == 0)
+ {
+ if (aENs[1] >= 3)
+ {
+ --aENs[0];
+ --aENs[1];
+ }
+ else
+ {
+ aENs[0] = aECount;
+ aENs[1] = 1;
+ }
+ }
+ else
+ {
+ aENs[0] = (aENs[1] > 1) ? aENs[0] : aECount;
+ }
+ }
+ aSEWD->Remove(aENs[aRI] + ((aRI != 0 || aSplitCounts[0] == 0) ? 0 : 1));
+ if (!Context().IsNull())
+ {
+ Context()->Remove(aEs[aRI].Oriented(TopAbs_FORWARD));
+ UpdateWire();
+ }
+ myLastFixStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE);
+ }
+ }
+ myStatusNotches = myLastFixStatus;
+ return ShapeExtend::DecodeStatus(myLastFixStatus, ShapeExtend_DONE);
+}
return myFixNonAdjacentIntersectingEdgesMode;
}
+//=======================================================================
+//function : FixTailMode
+//purpose :
+//=======================================================================
+inline Standard_Integer& ShapeFix_Wire::FixTailMode()
+{
+ return myFixTailMode;
+}
+
//=======================================================================
//function : Status.. for high-level methods
{
return ShapeExtend::DecodeStatus ( myStatusNotches, status );
}
+
+//=======================================================================
+//function : StatusFixTails
+//purpose :
+//=======================================================================
+inline Standard_Boolean ShapeFix_Wire::StatusFixTails(const ShapeExtend_Status status) const
+{
+ return ShapeExtend::DecodeStatus(myStatusFixTails, status);
+}
+
//=======================================================================
//function : LastFixStatus - Status for low-level methods (common)
//purpose :
sfw->FixSeamMode() = ctx->IntegerVal ( "FixSeamMode", -1 );
sfw->FixSameParameterMode() = ctx->IntegerVal ( "FixEdgeSameParameterMode", -1 );
sfw->FixNotchedEdgesMode() = ctx->IntegerVal ( "FixNotchedEdgesMode", -1 );
+ sfw->FixTailMode() = ctx->IntegerVal("FixTailMode", 0);
+ sfw->SetMaxTailAngle(ctx->RealVal("MaxTailAngle", 0) * (M_PI / 180));
+ sfw->SetMaxTailWidth(ctx->RealVal("MaxTailWidth", -1));
sfw->FixSelfIntersectingEdgeMode() = ctx->IntegerVal ( "FixSelfIntersectingEdgeMode", -1 );
sfw->FixIntersectingEdgesMode() = ctx->IntegerVal ( "FixIntersectingEdgesMode", -1 );
sfw->FixNonAdjacentIntersectingEdgesMode() = ctx->IntegerVal ( "FixNonAdjacentIntersectingEdgesMode", -1 );
-
+ if (sfw->FixTailMode() == 1)
+ {
+ sfw->FixTailMode() = 0;
+ sfs->Init(ctx->Result());
+ sfs->Perform(ctx->Progress());
+ sfw->FixTailMode() = 1;
+ if (!ctx->Progress().IsNull() && ctx->Progress()->UserBreak())
+ {
+ return Standard_False;
+ }
+
+ TopoDS_Shape result = sfs->Shape();
+ if (result != ctx->Result() ||
+ (!msg.IsNull() && !msg->MapShape().IsEmpty()))
+ {
+ ctx->RecordModification(sfs->Context(), msg);
+ ctx->SetResult(result);
+ }
+ }
+
sfs->Init(ctx->Result());
sfs->Perform(ctx->Progress());
-
- if ( !ctx->Progress().IsNull() && ctx->Progress()->UserBreak() )
+ if (!ctx->Progress().IsNull() && ctx->Progress()->UserBreak())
+ {
return Standard_False;
+ }
TopoDS_Shape result = sfs->Shape();
if (( result != ctx->Result() ) ||
FromSTEP.FixShape.FixShiftedMode : -1
FromSTEP.FixShape.FixEdgeSameParameterMode : 0
FromSTEP.FixShape.FixNotchedEdgesMode : -1
+FromSTEP.FixShape.FixTailMode : 0
+FromSTEP.FixShape.MaxTailAngle : 0
+FromSTEP.FixShape.MaxTailWidth : -1
FromSTEP.FixShape.FixSelfIntersectingEdgeMode : -1
FromSTEP.FixShape.FixIntersectingEdgesMode : -1
FromSTEP.FixShape.FixNonAdjacentIntersectingEdgesMode : -1
set test_image photo
}
+proc checklength {theShape theLength} {
+ set aLengthDump [uplevel lprops $theShape -full]
+ regexp {Mass\s*:\s*([-0-9.+eE]+)} $aLengthDump dummy aLength
+ if {abs($aLength - $theLength) > $theLength * 1e-14} {
+ puts "Error: result length is too different."
+ }
+}
-clear
-smallview
-if { [isdraw result] } {
+ if { [isdraw result] } {
+ clear
+ smallview
donly result
+ fit
+ xwd $imagedir/${test_image}.png
+} elseif { [isdraw r] } {
+ pload VISUALIZATION
+ vinit
+ vdisplay r
+ vfit
+ vdump $imagedir/${test_image}.png
} else {
puts "Error : the resulting shape is not done."
}
-fit
-xwd $imagedir/${test_image}.png
puts "TEST COMPLETED"
017 surface_to_revolution_advanced
018 surface_to_revolution_standard
019 drop_small_solids
+020 wire_tails_composed
+021 wire_tails_real
--- /dev/null
+vertex v1 -1 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v1 v2 v3 v1
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 0.7
+
+checknbshapes r -vertex 3 -edge 3 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 9.054743851305652
--- /dev/null
+vertex v1 -2 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v3 v2 v1 v3
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1
+
+checknbshapes r -vertex 2 -edge 2 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 6.1622776601683791
--- /dev/null
+vertex v1 -2 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v2 v1 v3 v2
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1
+
+checknbshapes r -vertex 2 -edge 2 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 6.1622776601683791
--- /dev/null
+vertex v1 -2 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v1 v3 v2 v1
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1
+
+checknbshapes r -vertex 2 -edge 2 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 6.1622776601683791
--- /dev/null
+vertex v1 0 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v1 v2 v3 v1
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1.5
+
+checknbshapes r -vertex 1 -edge 1 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 1.4142135623730949
--- /dev/null
+vertex v1 0 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v2 v3 v1 v2
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1.5
+
+checknbshapes r -vertex 1 -edge 1 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 1.4142135623730949
--- /dev/null
+vertex v1 0 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v3 v1 v2 v3
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1.5
+
+checknbshapes r -vertex 1 -edge 1 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 1.4142135623730949
--- /dev/null
+vertex v1 0 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v3 v2 v1 v3
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1.5
+
+checknbshapes r -vertex 1 -edge 1 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 1.4142135623730949
--- /dev/null
+vertex v1 0 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v2 v1 v3 v2
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1.5
+
+checknbshapes r -vertex 1 -edge 1 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 1.4142135623730949
--- /dev/null
+vertex v1 0 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v1 v3 v2 v1
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1.5
+
+checknbshapes r -vertex 1 -edge 1 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 1.4142135623730949
--- /dev/null
+vertex v1 -1 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+vertex v4 1 1 5
+polyvertex w1 v1 v3 v2 v1
+mkplane s1 w1
+polyvertex w2 v1 v2 v4 v1
+mkplane s2 w2
+polyvertex w3 v2 v3 v4 v2
+mkplane s3 w3
+polyvertex w4 v1 v4 v3 v1
+mkplane s4 w4
+sewing s s1 s2 s3 s4
+fixshape r s -maxtaila 10 -maxtailw 0.7
+
+checknbshapes r -vertex 5 -edge 7 -wire 4 -face 4 -shell 1 -solid 0 -compsolid 0 -compound 0
+checklength r 69.237606465667483
--- /dev/null
+vertex v1 -1 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v2 v3 v1 v2
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 0.7
+
+checknbshapes r -vertex 3 -edge 3 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 9.054743851305652
--- /dev/null
+vertex v1 -1 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v3 v1 v2 v3
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 0.7
+
+checknbshapes r -vertex 3 -edge 3 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 9.054743851305652
--- /dev/null
+vertex v1 -1 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v3 v2 v1 v3
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 0.7
+
+checknbshapes r -vertex 3 -edge 3 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 9.0547440573886373
--- /dev/null
+vertex v1 -1 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v2 v1 v3 v2
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 0.7
+
+checknbshapes r -vertex 3 -edge 3 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 9.0547440573886373
--- /dev/null
+vertex v1 -1 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v1 v3 v2 v1
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 0.7
+
+checknbshapes r -vertex 3 -edge 3 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 9.0547440573886373
--- /dev/null
+vertex v1 -2 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v1 v2 v3 v1
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1
+
+checknbshapes r -vertex 2 -edge 2 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 6.1622776601683791
--- /dev/null
+vertex v1 -2 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v2 v3 v1 v2
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1
+
+checknbshapes r -vertex 2 -edge 2 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 6.1622776601683791
--- /dev/null
+vertex v1 -2 0 0
+vertex v2 9 0 0
+vertex v3 1 1 0
+polyvertex w v3 v1 v2 v3
+mkplane s w
+fixshape r s -maxtaila 10 -maxtailw 1
+
+checknbshapes r -vertex 2 -edge 2 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 6.1622776601683791
--- /dev/null
+restore [locate_data_file bug26261_a_2574.brep] s
+fixshape r s -maxtaila 1 -maxtailw 6e-3
+
+checknbshapes r -vertex 16 -edge 16 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 17.514170299083325
--- /dev/null
+restore [locate_data_file bug26261_a_3380.brep] s
+fixshape r s -maxtaila 1 -maxtailw 3e-3
+
+checknbshapes r -vertex 5 -edge 5 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 1.9646975436380054
--- /dev/null
+restore [locate_data_file bug26261_notched_1.brep] s
+fixshape r s -maxtaila 1 -maxtailw 1e-4
+
+checknbshapes r -vertex 7 -edge 7 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 5.4302952062350922
--- /dev/null
+restore [locate_data_file bug26261_notched_2.brep] s
+fixshape r s -maxtaila 1 -maxtailw 1e-2
+
+checknbshapes r -vertex 3 -edge 3 -wire 1 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 0
+checklength r 21.767418596938622
--- /dev/null
+pload XDE
+
+stepread [locate_data_file bug26261_ca07771-040x.stp] s *
+renamevar s_1 s
+fixshape r s -maxtaila 1 -maxtailw 1e-3
+
+checknbshapes r -vertex 25950 -edge 41999 -wire 16519 -face 16205 -shell 51 -solid 1 -compsolid 0 -compound 2
+checklength r 127197.57657573155
--- /dev/null
+pload XDE
+
+stepread [locate_data_file bug26261_lower_2.stp] s *
+renamevar s_1 s
+fixshape r s 1e-3 1 -maxtaila 6 -maxtailw 1e-3
+
+checknbshapes r -vertex 257 -edge 395 -wire 146 -face 137 -shell 1 -solid 1 -compsolid 0 -compound 0
+checklength r 4611.0742231217555
--- /dev/null
+pload XDE
+
+stepread [locate_data_file bug26261_mmg-m-cv-qubit.stp] s *
+renamevar s_1 s
+fixshape r s 1e-3 1 -maxtaila 6 -maxtailw 1e-3
+
+checknbshapes r -vertex 8494 -edge 13832 -wire 5955 -face 5466 -shell 1 -solid 1 -compsolid 0 -compound 0
+checklength r 69141.057126027736