1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0026261: Create a tool to remove tails from any wire

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
This commit is contained in:
abk 2015-05-19 20:03:11 +03:00 committed by bugmaster
parent 70fd50ec90
commit fbf3becf65
38 changed files with 852 additions and 21 deletions

View File

@ -413,8 +413,11 @@ static Standard_Integer fixshape (Draw_Interpretor& di, Standard_Integer argc, c
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;
@ -429,7 +432,27 @@ static Standard_Integer fixshape (Draw_Interpretor& di, Standard_Integer argc, c
}
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: {
@ -445,7 +468,8 @@ static Standard_Integer fixshape (Draw_Interpretor& di, Standard_Integer argc, c
}
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";
@ -787,7 +811,9 @@ static Standard_Integer connectedges(Draw_Interpretor& di, Standard_Integer n, c
__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);

View File

@ -64,6 +64,7 @@ uses
Shape from TopoDS,
Wire from TopoDS,
Face from TopoDS,
Edge from TopoDS,
SequenceOfIntersectionPoint from IntRes2d,
SequenceOfPnt from TColgp,
SequenceOfReal from TColStd,
@ -545,6 +546,17 @@ is
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 :

View File

@ -69,12 +69,18 @@
#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>
@ -1964,3 +1970,283 @@ Standard_Boolean isMultiVertex(const TopTools_ListOfShape& alshape,
}
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;
}

View File

@ -462,6 +462,7 @@ Standard_Boolean ShapeFix_Face::Perform()
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();
@ -561,9 +562,10 @@ Standard_Boolean ShapeFix_Face::Perform()
}
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 );

View File

@ -59,8 +59,10 @@ class Wire from ShapeFix inherits Root from ShapeFix
-- 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
@ -131,6 +133,12 @@ is
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
@ -313,6 +321,9 @@ is
-- -1 default
-- 1 method will be called
-- 0 method will not be called
FixTailMode(me: mutable) returns Integer;
---C++: inline
---C++: return &
--- Fixing methods:
@ -767,6 +778,8 @@ is
-- 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;
@ -800,6 +813,9 @@ is
-- 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
@ -843,6 +859,7 @@ fields
myFixSelfIntersectingEdgeMode: Integer is protected;
myFixIntersectingEdgesMode: Integer is protected;
myFixNonAdjacentIntersectingEdgesMode: Integer is protected;
myFixTailMode: Integer is protected;
myRemoveLoopMode: Integer is protected;
-- -1 - old variant (default)
@ -874,4 +891,7 @@ fields
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;

View File

@ -129,7 +129,7 @@
//purpose :
//=======================================================================
ShapeFix_Wire::ShapeFix_Wire()
ShapeFix_Wire::ShapeFix_Wire() : myMaxTailAngleSine(0), myMaxTailWidth(-1)
{
myFixEdge = new ShapeFix_Edge;
myAnalyzer = new ShapeAnalysis_Wire;
@ -143,8 +143,10 @@ ShapeFix_Wire::ShapeFix_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;
@ -165,6 +167,25 @@ void ShapeFix_Wire::SetPrecision (const Standard_Real prec)
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 :
@ -194,6 +215,7 @@ void ShapeFix_Wire::ClearModes()
myFixSelfIntersectingEdgeMode = -1;
myFixIntersectingEdgesMode = -1;
myFixNonAdjacentIntersectingEdgesMode = -1;
myFixTailMode = 0;
myFixReorderMode = -1;
myFixSmallMode = -1;
@ -227,6 +249,8 @@ void ShapeFix_Wire::ClearStatuses()
myStatusGaps3d = emptyStatus; //szv#9:S4244:19Aug99 new method introduced
myStatusGaps2d = emptyStatus; //szv#9:S4244:19Aug99 new method introduced
myStatusClosed = emptyStatus;
myStatusNotches = emptyStatus;
myStatusFixTails = emptyStatus;
}
//=======================================================================
@ -361,11 +385,21 @@ Standard_Boolean ShapeFix_Wire::Perform()
}
//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
@ -3322,3 +3356,171 @@ void ShapeFix_Wire::UpdateWire ()
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);
}

View File

@ -405,6 +405,15 @@ inline Standard_Integer& ShapeFix_Wire::FixNonAdjacentIntersectingEdgesMode()
return myFixNonAdjacentIntersectingEdgesMode;
}
//=======================================================================
//function : FixTailMode
//purpose :
//=======================================================================
inline Standard_Integer& ShapeFix_Wire::FixTailMode()
{
return myFixTailMode;
}
//=======================================================================
//function : Status.. for high-level methods
@ -516,6 +525,16 @@ inline Standard_Boolean ShapeFix_Wire::StatusNotches(const ShapeExtend_Status s
{
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 :

View File

@ -752,15 +752,38 @@ static Standard_Boolean fixshape (const Handle(ShapeProcess_Context)& context)
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() ) ||

View File

@ -51,6 +51,9 @@ FromSTEP.FixShape.FixSeamMode : -1
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

View File

@ -11,3 +11,10 @@ if { [info exists test_image ] == 0 } {
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."
}
}

View File

@ -1,10 +1,16 @@
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"

View File

@ -17,3 +17,5 @@
017 surface_to_revolution_advanced
018 surface_to_revolution_standard
019 drop_small_solids
020 wire_tails_composed
021 wire_tails_real

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,17 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,9 @@
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

View File

@ -0,0 +1,5 @@
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

View File

@ -0,0 +1,5 @@
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

View File

@ -0,0 +1,5 @@
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

View File

@ -0,0 +1,5 @@
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

View File

@ -0,0 +1,8 @@
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

View File

@ -0,0 +1,8 @@
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

View File

@ -0,0 +1,8 @@
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