mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-03 17:56:21 +03:00
0032922: Data Exchange, STEP - The torus is stored incorrectly in STEP format
Problem: the complete surface of the torus is not stored correctly in STEP format due to the fact that the edges are not properly ordered. Change: added a mode for reordering edges in the wire with simultaneous use of 2d and 3d information (ShapeAnalysis_WireOrder). The new mode is used for torus-like surfaces before saving to STEP format. Result: Torus correctly stored.
This commit is contained in:
parent
86d6c284c2
commit
9b9aac4a7b
@ -260,7 +260,7 @@ void ShapeAnalysis_Wire::SetSurface (const Handle(Geom_Surface)& surface,
|
||||
const Standard_Boolean mode3d)
|
||||
{
|
||||
ShapeAnalysis_WireOrder sawo;
|
||||
CheckOrder (sawo, isClosed, mode3d);
|
||||
CheckOrder (sawo, isClosed, mode3d, Standard_False);
|
||||
myStatusOrder = myStatus;
|
||||
return StatusOrder (ShapeExtend_DONE);
|
||||
}
|
||||
@ -552,20 +552,26 @@ void ShapeAnalysis_Wire::SetSurface (const Handle(Geom_Surface)& surface,
|
||||
|
||||
Standard_Boolean ShapeAnalysis_Wire::CheckOrder(ShapeAnalysis_WireOrder &sawo,
|
||||
const Standard_Boolean isClosed,
|
||||
const Standard_Boolean mode3d)
|
||||
const Standard_Boolean theMode3D,
|
||||
const Standard_Boolean theModeBoth)
|
||||
{
|
||||
if ((!theMode3D || theModeBoth) && myFace.IsNull())
|
||||
{
|
||||
if ( ! mode3d && myFace.IsNull() ) {
|
||||
myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
|
||||
sawo.SetMode ( mode3d, ( mode3d ? myPrecision : ::Precision::PConfusion() ) );
|
||||
Standard_Integer i, nb = myWire->NbEdges();
|
||||
sawo.SetMode(theMode3D, 0.0, theModeBoth);
|
||||
Standard_Integer nb = myWire->NbEdges();
|
||||
ShapeAnalysis_Edge EA;
|
||||
for (i = 1; i <= nb; i ++) {
|
||||
Standard_Boolean isAll2dEdgesOk = Standard_True;
|
||||
for (Standard_Integer i = 1; i <= nb; i++)
|
||||
{
|
||||
TopoDS_Edge E = myWire->Edge(i);
|
||||
if ( mode3d ) {
|
||||
gp_XYZ aP1XYZ, aP2XYZ;
|
||||
gp_XY aP1XY, aP2XY;
|
||||
if (theMode3D || theModeBoth)
|
||||
{
|
||||
TopoDS_Vertex V1 = EA.FirstVertex(E);
|
||||
TopoDS_Vertex V2 = EA.LastVertex(E);
|
||||
if (V1.IsNull() || V2.IsNull())
|
||||
@ -573,31 +579,65 @@ Standard_Boolean ShapeAnalysis_Wire::CheckOrder(ShapeAnalysis_WireOrder& sawo,
|
||||
myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
|
||||
return Standard_False;
|
||||
}
|
||||
gp_Pnt p1 = BRep_Tool::Pnt (V1);
|
||||
gp_Pnt p2 = BRep_Tool::Pnt (V2);
|
||||
sawo.Add (p1.XYZ(),p2.XYZ());
|
||||
else
|
||||
{
|
||||
aP1XYZ = BRep_Tool::Pnt(V1).XYZ();
|
||||
aP2XYZ = BRep_Tool::Pnt(V2).XYZ();
|
||||
}
|
||||
else {
|
||||
}
|
||||
if (!theMode3D || theModeBoth)
|
||||
{
|
||||
Standard_Real f, l;
|
||||
Handle(Geom2d_Curve) c2d;
|
||||
TopoDS_Shape tmpF = myFace.Oriented (TopAbs_FORWARD);
|
||||
if ( ! EA.PCurve(E,TopoDS::Face(tmpF),c2d,f,l) ) {
|
||||
if (!EA.PCurve(E, TopoDS::Face (tmpF), c2d, f, l))
|
||||
{
|
||||
// if mode is 2d, then we can nothing to do, else we can switch to 3d mode
|
||||
if (!theMode3D && !theModeBoth)
|
||||
{
|
||||
myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
|
||||
return Standard_False;
|
||||
}
|
||||
sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
|
||||
else
|
||||
{
|
||||
isAll2dEdgesOk = Standard_False;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aP1XY = c2d->Value(f).XY();
|
||||
aP2XY = c2d->Value(l).XY();
|
||||
}
|
||||
}
|
||||
if (theMode3D && !theModeBoth)
|
||||
{
|
||||
sawo.Add (aP1XYZ, aP2XYZ);
|
||||
}
|
||||
else if (!theMode3D && !theModeBoth)
|
||||
{
|
||||
sawo.Add (aP1XY, aP2XY);
|
||||
}
|
||||
else
|
||||
{
|
||||
sawo.Add (aP1XYZ, aP2XYZ, aP1XY, aP2XY);
|
||||
}
|
||||
}
|
||||
// need to switch to 3d mode
|
||||
if (theModeBoth && !isAll2dEdgesOk)
|
||||
{
|
||||
sawo.SetMode (Standard_True, 0.0, Standard_False);
|
||||
}
|
||||
sawo.Perform (isClosed);
|
||||
Standard_Integer stat = sawo.Status();
|
||||
switch (stat) {
|
||||
switch (stat)
|
||||
{
|
||||
case 0: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); break;
|
||||
case 1: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); break;
|
||||
case 2: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); break;
|
||||
case 2: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); break; // this value is not returned
|
||||
case -1: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE3); break;
|
||||
case -2: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE4); break;
|
||||
case -2: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE4); break; // this value is not returned
|
||||
case 3: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE5); break; // only shifted
|
||||
case -10: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); break;
|
||||
case -10: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); break; // this value is not returned
|
||||
}
|
||||
return LastCheckStatus (ShapeExtend_DONE);
|
||||
}
|
||||
|
@ -232,7 +232,8 @@ public:
|
||||
//! Analyzes the order of the edges in the wire,
|
||||
//! uses class WireOrder for that purpose.
|
||||
//! Flag <isClosed> defines if the wire is closed or not
|
||||
//! Flag <mode3d> defines which mode is used (3d or 2d)
|
||||
//! Flag <theMode3D> defines 3D or 2d mode.
|
||||
//! Flag <theModeBoth> defines miscible mode and the flag <theMode3D> is ignored.
|
||||
//! Returns False if wire is already ordered (tail-to-head),
|
||||
//! True otherwise.
|
||||
//! Use returned WireOrder object for deeper analysis.
|
||||
@ -243,7 +244,10 @@ public:
|
||||
//! DONE3: not the same edges orientation (some need to be reversed)
|
||||
//! DONE4: as DONE3 and gaps more than myPrecision
|
||||
//! FAIL : algorithm failed (could not detect order)
|
||||
Standard_EXPORT Standard_Boolean CheckOrder (ShapeAnalysis_WireOrder& sawo, const Standard_Boolean isClosed = Standard_True, const Standard_Boolean mode3d = Standard_True);
|
||||
Standard_EXPORT Standard_Boolean CheckOrder(ShapeAnalysis_WireOrder &sawo,
|
||||
Standard_Boolean isClosed = Standard_True,
|
||||
Standard_Boolean theMode3D = Standard_True,
|
||||
Standard_Boolean theModeBoth = Standard_False);
|
||||
|
||||
//! Checks connected edges (num-th and preceding).
|
||||
//! Tests with starting preci from <SBWD> or with <prec> if
|
||||
|
@ -21,10 +21,9 @@
|
||||
#include <gp_XYZ.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <ShapeAnalysis_WireOrder.hxx>
|
||||
#include <Standard_TypeMismatch.hxx>
|
||||
#include <TColgp_Array1OfXYZ.hxx>
|
||||
#include <TColgp_Array1OfXY.hxx>
|
||||
#include <TColStd_Array1OfBoolean.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
#include <TColStd_HSequenceOfInteger.hxx>
|
||||
#include <TColStd_SequenceOfInteger.hxx>
|
||||
#include <TColStd_SequenceOfTransient.hxx>
|
||||
@ -34,7 +33,7 @@
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
ShapeAnalysis_WireOrder::ShapeAnalysis_WireOrder()
|
||||
: myKeepLoops(Standard_False) , myGap (0.) , myStat (0) , myMode (Standard_True)
|
||||
: myGap (0.0), myStat (0), myKeepLoops (Standard_False), myMode (Mode3D)
|
||||
{
|
||||
myTol = Precision::Confusion();
|
||||
Clear();
|
||||
@ -45,10 +44,26 @@ ShapeAnalysis_WireOrder::ShapeAnalysis_WireOrder()
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
ShapeAnalysis_WireOrder::ShapeAnalysis_WireOrder(const Standard_Boolean mode3d,
|
||||
const Standard_Real tol)
|
||||
: myKeepLoops(Standard_False), myTol (tol), myGap (0.), myStat (0), myMode (mode3d)
|
||||
ShapeAnalysis_WireOrder::ShapeAnalysis_WireOrder (const Standard_Boolean theMode3D,
|
||||
const Standard_Real theTolerance,
|
||||
const Standard_Boolean theModeBoth)
|
||||
: myTol (theTolerance), myGap (0.0), myStat (0), myKeepLoops (Standard_False)
|
||||
{
|
||||
if (theModeBoth)
|
||||
{
|
||||
myMode = ModeBoth;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (theMode3D)
|
||||
{
|
||||
myMode = Mode3D;
|
||||
}
|
||||
else
|
||||
{
|
||||
myMode = Mode2D;
|
||||
}
|
||||
}
|
||||
Clear();
|
||||
}
|
||||
|
||||
@ -57,12 +72,36 @@ ShapeAnalysis_WireOrder::ShapeAnalysis_WireOrder(const Standard_Boolean mode3d,
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void ShapeAnalysis_WireOrder::SetMode(const Standard_Boolean mode3d,const Standard_Real tol)
|
||||
void ShapeAnalysis_WireOrder::SetMode (const Standard_Boolean theMode3D,
|
||||
const Standard_Real theTolerance,
|
||||
const Standard_Boolean theModeBoth)
|
||||
{
|
||||
if (mode3d != myMode) Clear();
|
||||
myOrd.Nullify(); myStat = 0; myGap = 0.;
|
||||
myMode = mode3d;
|
||||
myTol = (tol > 0.)? tol : 1.e-08; //szv#4:S4163:12Mar99 optimized
|
||||
ModeType aNewMode;
|
||||
|
||||
if (theModeBoth)
|
||||
{
|
||||
aNewMode = ModeBoth;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (theMode3D)
|
||||
{
|
||||
aNewMode = Mode3D;
|
||||
}
|
||||
else
|
||||
{
|
||||
aNewMode = Mode2D;
|
||||
}
|
||||
}
|
||||
if (myMode != aNewMode)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
myMode = aNewMode;
|
||||
myOrd.Nullify();
|
||||
myStat = 0;
|
||||
myGap = 0.0;
|
||||
myTol = (theTolerance > 0.0) ? theTolerance : 1.e-08;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -83,8 +122,9 @@ Standard_Real ShapeAnalysis_WireOrder::Tolerance() const
|
||||
void ShapeAnalysis_WireOrder::Clear()
|
||||
{
|
||||
myXYZ = new TColgp_HSequenceOfXYZ();
|
||||
myXY = new TColgp_HSequenceOfXY();
|
||||
myStat = 0;
|
||||
myGap = 0.;
|
||||
myGap = 0.0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -92,13 +132,12 @@ void ShapeAnalysis_WireOrder::Clear()
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void ShapeAnalysis_WireOrder::Add(const gp_XYZ& start3d,const gp_XYZ& end3d)
|
||||
void ShapeAnalysis_WireOrder::Add (const gp_XYZ& theStart3d, const gp_XYZ& theEnd3d)
|
||||
{
|
||||
//szv#4:S4163:12Mar99 waste raise
|
||||
//if (!myMode)
|
||||
//throw Standard_TypeMismatch("ShapeAnalysis_WireOrder : AddXYZ");
|
||||
if (myMode) {
|
||||
myXYZ->Append (start3d); myXYZ->Append (end3d);
|
||||
if (myMode == Mode3D)
|
||||
{
|
||||
myXYZ->Append (theStart3d);
|
||||
myXYZ->Append (theEnd3d);
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,20 +146,38 @@ void ShapeAnalysis_WireOrder::Add(const gp_XYZ& start3d,const gp_XYZ& end3d)
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void ShapeAnalysis_WireOrder::Add(const gp_XY& start2d,const gp_XY& end2d)
|
||||
void ShapeAnalysis_WireOrder::Add (const gp_XY& theStart2d, const gp_XY& theEnd2d)
|
||||
{
|
||||
if (myMode == Mode2D)
|
||||
{
|
||||
//szv#4:S4163:12Mar99 waste raise
|
||||
//if ( myMode)
|
||||
//throw Standard_TypeMismatch("ShapeAnalysis_WireOrder : AddXY");
|
||||
if (!myMode) {
|
||||
gp_XYZ val;
|
||||
val.SetCoord (start2d.X(),start2d.Y(),0.);
|
||||
val.SetCoord (theStart2d.X(), theStart2d.Y(), 0.0);
|
||||
myXYZ->Append (val);
|
||||
val.SetCoord (end2d.X(),end2d.Y(),0.);
|
||||
val.SetCoord (theEnd2d.X(), theEnd2d.Y(), 0.0);
|
||||
myXYZ->Append (val);
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Add
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void ShapeAnalysis_WireOrder::Add (const gp_XYZ& theStart3d,
|
||||
const gp_XYZ& theEnd3d,
|
||||
const gp_XY& theStart2d,
|
||||
const gp_XY& theEnd2d)
|
||||
{
|
||||
if (myMode == ModeBoth)
|
||||
{
|
||||
myXYZ->Append (theStart3d);
|
||||
myXYZ->Append (theEnd3d);
|
||||
|
||||
myXY->Append (theStart2d);
|
||||
myXY->Append (theEnd2d);
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : NbEdges
|
||||
//purpose :
|
||||
@ -166,234 +223,480 @@ Standard_Boolean& ShapeAnalysis_WireOrder::KeepLoopsMode()
|
||||
|
||||
//=======================================================================
|
||||
//function : Perform
|
||||
//purpose :
|
||||
//purpose : Make wire order analysis and propose the better order of the edges
|
||||
// taking into account the gaps between edges.
|
||||
//=======================================================================
|
||||
|
||||
static Standard_Boolean IsBetter(const Standard_Integer first,
|
||||
const Standard_Integer second)
|
||||
{
|
||||
//rln 23.03.99 bm4_al_eye.stp, entity 5281
|
||||
//Order in the file is better even if another order has the same distance
|
||||
//Lexicograhical order of preference: 0 > 2 > 1 > 3
|
||||
if (first == 0 && second > 0 ) return Standard_True;
|
||||
if (first == 2 && (second == 1 || second == 3)) return Standard_True;
|
||||
if (first == 1 && second == 3 ) return Standard_True;
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
void ShapeAnalysis_WireOrder::Perform (const Standard_Boolean /*closed*/)
|
||||
{
|
||||
myStat = 0;
|
||||
Standard_Integer i, nb = NbEdges();
|
||||
if(nb == 0)
|
||||
return; // no edges loaded, nothing to do -- return with status OK
|
||||
myOrd = new TColStd_HArray1OfInteger(1,nb);
|
||||
myOrd->Init(0);
|
||||
|
||||
Handle(TColStd_HSequenceOfInteger) seq = new TColStd_HSequenceOfInteger;
|
||||
TColStd_SequenceOfTransient loops;
|
||||
|
||||
TColgp_Array1OfXYZ debs(0,nb);
|
||||
TColgp_Array1OfXYZ fins(0,nb);
|
||||
|
||||
TColStd_Array1OfBoolean idone (1, nb);
|
||||
idone.Init (Standard_False);
|
||||
|
||||
// Calcul des precedents-suivants
|
||||
for (i = 1; i <= nb; i ++) {
|
||||
debs(i) = myXYZ->Value(2*i-1);
|
||||
fins(i) = myXYZ->Value(2*i);
|
||||
}
|
||||
|
||||
Standard_Real tol2 = Precision::SquareConfusion();
|
||||
idone(1) = Standard_True;
|
||||
gp_Pnt wireFirst = debs(1);
|
||||
gp_Pnt wireLast = fins(1);
|
||||
seq->Append(1);
|
||||
Standard_Boolean done = Standard_False;
|
||||
|
||||
//pdn 11.03.99 S4135 constructing closed loops of edges
|
||||
while(!done) {
|
||||
Standard_Integer resultType = 3;
|
||||
Standard_Real distmin = RealLast();
|
||||
Standard_Integer ledge = 0;
|
||||
Standard_Boolean found = Standard_False;
|
||||
Standard_Real closeDist = wireFirst.SquareDistance(wireLast);
|
||||
|
||||
for(Standard_Integer iedge = 1; (iedge <= nb) && (distmin||resultType||(resultType!=2)); iedge++)
|
||||
if(!idone(iedge)) {
|
||||
Standard_Real tailhead = wireLast.SquareDistance(debs(iedge));
|
||||
Standard_Real tailtail = wireLast.SquareDistance(fins(iedge));
|
||||
Standard_Real headtail = wireFirst.SquareDistance(fins(iedge));
|
||||
Standard_Real headhead = wireFirst.SquareDistance(debs(iedge));
|
||||
Standard_Real dm1 = tailhead, dm2 = headtail;
|
||||
Standard_Integer res1 = 0, res2 = 2;
|
||||
|
||||
if (tailhead > tailtail) {res1 = 1; dm1 = tailtail;}
|
||||
if (headtail > headhead) {res2 = 3; dm2 = headhead;}
|
||||
Standard_Integer result =0;
|
||||
Standard_Real myMin3d = Min (dm1, dm2);
|
||||
if(fabs(dm1 - dm2) < tol2 ) {
|
||||
Standard_Boolean isB = IsBetter(res1,res2);
|
||||
result = (isB ? res1 : res2);
|
||||
}
|
||||
else
|
||||
result = ((dm1 > dm2) ? res2 : res1); // 0 > 2 > 1 > 3
|
||||
|
||||
if (distmin > tol2 || IsBetter(result,resultType))
|
||||
if (myMin3d < distmin || ((myMin3d == distmin || myMin3d < tol2) && IsBetter(result,resultType))) {
|
||||
found = Standard_True;
|
||||
distmin = myMin3d;
|
||||
ledge = iedge;
|
||||
resultType = result;
|
||||
}
|
||||
}
|
||||
if(found) {
|
||||
if (distmin == 0 || distmin < closeDist) {
|
||||
switch(resultType){
|
||||
case 0: seq->Append(ledge); wireLast = fins(ledge); break;
|
||||
case 1: seq->Append(-ledge); wireLast = debs(ledge); break;
|
||||
case 2: seq->Prepend(ledge); wireFirst = debs(ledge); break;
|
||||
case 3: seq->Prepend(-ledge); wireFirst = fins(ledge); break;
|
||||
}
|
||||
} else {
|
||||
//pdn 11.03.99 S4135 closing loop and creating new one
|
||||
loops.Append(seq);
|
||||
seq = new TColStd_HSequenceOfInteger;
|
||||
wireFirst = debs(ledge);
|
||||
wireLast = fins(ledge);
|
||||
seq->Append(ledge);
|
||||
}
|
||||
idone(ledge) = Standard_True;
|
||||
} else {
|
||||
ledge = -1;
|
||||
for (i = 1 ; i <= nb && ledge == -1; i++)
|
||||
ledge = idone(i) ? ledge : i;
|
||||
if (ledge == -1)
|
||||
done = 1;
|
||||
else {
|
||||
wireFirst = debs(ledge);
|
||||
wireLast = fins(ledge);
|
||||
seq->Append(ledge);
|
||||
idone(ledge) = Standard_True;
|
||||
}
|
||||
}
|
||||
}
|
||||
loops.Append(seq);
|
||||
|
||||
Handle(TColStd_HSequenceOfInteger) mainSeq;
|
||||
if (myKeepLoops) {
|
||||
|
||||
//pdn Keeping the loops, adding one after another.
|
||||
mainSeq = new TColStd_HSequenceOfInteger;
|
||||
for (Standard_Integer ii = 1; ii <= loops.Length(); ii++) {
|
||||
Handle(TColStd_HSequenceOfInteger) subLoop =
|
||||
Handle(TColStd_HSequenceOfInteger)::DownCast(loops(ii));
|
||||
for (Standard_Integer j = 1; j<= subLoop->Length(); j++)
|
||||
mainSeq->Append(subLoop->Value(j));
|
||||
}
|
||||
}
|
||||
else {
|
||||
//pdn 11.03.99 S4135 connecting loops.
|
||||
mainSeq = Handle(TColStd_HSequenceOfInteger)::DownCast(loops.First());
|
||||
loops.Remove(1);
|
||||
while(loops.Length()) {
|
||||
Standard_Real minLoopDist = RealLast();
|
||||
Standard_Integer loopNum=0;
|
||||
Standard_Integer loopShift=0;
|
||||
Standard_Boolean loopDirect=0;
|
||||
Standard_Integer numInLoop=0;
|
||||
for(i = 1; i <= loops.Length(); i++) {
|
||||
Handle(TColStd_HSequenceOfInteger) loop = Handle(TColStd_HSequenceOfInteger)::DownCast(loops.Value(i));
|
||||
Standard_Integer num = loop->Length();
|
||||
Standard_Integer LocShift=0;
|
||||
Standard_Integer LocNumInLoop=0;
|
||||
Standard_Boolean LocDirect = Standard_False;
|
||||
Standard_Real minLocDist = RealLast();
|
||||
for(Standard_Integer ibegin = 1; ibegin <= loop->Length(); ibegin++) {
|
||||
Standard_Integer iend = (ibegin==1 ? num : ibegin -1);
|
||||
gp_Pnt loopFirst = (loop->Value(ibegin) > 0 ? debs(loop->Value(ibegin)) : fins(-loop->Value(ibegin)));
|
||||
gp_Pnt loopLast = (loop->Value(iend) > 0 ? fins(loop->Value(iend)) : debs(-loop->Value(iend)));
|
||||
Standard_Real distmin = RealLast();
|
||||
Standard_Integer lloop=0;
|
||||
Standard_Boolean direct = Standard_False;
|
||||
for(Standard_Integer j = 1; (j <= mainSeq->Length())&& distmin; j++) {
|
||||
Standard_Integer k = (j == mainSeq->Length()? 1 : j+1);
|
||||
gp_Pnt first = (mainSeq->Value(j) > 0 ? fins(mainSeq->Value(j)) : debs(-mainSeq->Value(j)));
|
||||
gp_Pnt last = (mainSeq->Value(k) > 0 ? debs(mainSeq->Value(k)) : fins(-mainSeq->Value(k)));
|
||||
Standard_Real dirDist = loopFirst.SquareDistance(first)+loopLast.SquareDistance(last);
|
||||
Standard_Real revDist = loopFirst.SquareDistance(last)+loopLast.SquareDistance(first);
|
||||
Standard_Real minDist;
|
||||
if((dirDist<tol2)||(dirDist < 2.*revDist)) {
|
||||
minDist = dirDist;
|
||||
revDist = dirDist;
|
||||
}
|
||||
else
|
||||
minDist = revDist;
|
||||
if(minDist < distmin && Abs(distmin - minDist) > tol2) {
|
||||
distmin = minDist;
|
||||
direct = (dirDist <= revDist);
|
||||
lloop = j;
|
||||
}
|
||||
}
|
||||
if(distmin < minLocDist && Abs(minLocDist - distmin) > tol2) {
|
||||
minLocDist = distmin;
|
||||
LocDirect = direct;
|
||||
LocNumInLoop = lloop;
|
||||
LocShift = ibegin;
|
||||
}
|
||||
|
||||
}
|
||||
if(minLocDist < minLoopDist && Abs(minLoopDist - minLocDist) > tol2) {
|
||||
minLoopDist = minLocDist;
|
||||
loopNum = i;
|
||||
loopDirect = LocDirect;
|
||||
numInLoop = LocNumInLoop;
|
||||
loopShift = LocShift;
|
||||
}
|
||||
}
|
||||
|
||||
Handle(TColStd_HSequenceOfInteger) loop = Handle(TColStd_HSequenceOfInteger)::DownCast(loops.Value(loopNum));
|
||||
Standard_Integer factor = (loopDirect ? 1: -1);
|
||||
// skl : in the next block for{} I change "i" to "ii"
|
||||
for(Standard_Integer ii = 1; ii <= loop->Length(); ii++) {
|
||||
Standard_Integer num = (ii+loopShift-1>loop->Length() ? ii+loopShift-1-loop->Length() : ii+loopShift-1);
|
||||
mainSeq->InsertAfter(numInLoop+ii-1,loop->Value(num)*factor);
|
||||
}
|
||||
loops.Remove(loopNum);
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Integer stTmp=0;
|
||||
for(i = 1; i <= mainSeq->Length(); i++) {
|
||||
if(i!=mainSeq->Value(i))
|
||||
if(stTmp>=0) stTmp = (mainSeq->Value(i) > 0 ? 1 : -1);
|
||||
myOrd->SetValue(i,mainSeq->Value(i));
|
||||
}
|
||||
if (stTmp == 0) {
|
||||
myStat = stTmp;
|
||||
Standard_Integer aNbEdges = NbEdges();
|
||||
// no edges loaded, nothing to do -- return with status OK
|
||||
if (aNbEdges == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else {//check if edges were only shifted in reverse or forward, not reordered
|
||||
Standard_Boolean isShiftReverse = Standard_True, isShiftForward = Standard_True;
|
||||
Standard_Integer tmpFirst = 0, tmpSecond = 0, length = mainSeq->Length();
|
||||
for(i = 1; i <= length - 1; i++) {
|
||||
tmpFirst = mainSeq->Value(i);
|
||||
tmpSecond = mainSeq->Value(i+1);
|
||||
if (!(tmpSecond - tmpFirst == 1 || (tmpFirst == length && tmpSecond == 1)))
|
||||
myOrd = new TColStd_HArray1OfInteger (1, aNbEdges);
|
||||
myOrd->Init (0);
|
||||
|
||||
// sequence of the edge nums in the right order
|
||||
Handle(TColStd_HSequenceOfInteger) anEdgeSeq = new TColStd_HSequenceOfInteger;
|
||||
NCollection_Sequence<Handle(TColStd_HSequenceOfInteger) > aLoops;
|
||||
|
||||
// the beginnings and ends of the edges
|
||||
TColgp_Array1OfXYZ aBegins3D (1, aNbEdges);
|
||||
TColgp_Array1OfXYZ anEnds3D (1, aNbEdges);
|
||||
TColgp_Array1OfXY aBegins2D (1, aNbEdges);
|
||||
TColgp_Array1OfXY anEnds2D (1, aNbEdges);
|
||||
for (Standard_Integer i = 1; i <= aNbEdges; i++)
|
||||
{
|
||||
aBegins3D (i) = myXYZ->Value (2 * i - 1);
|
||||
anEnds3D (i) = myXYZ->Value (2 * i);
|
||||
if (myMode == ModeBoth)
|
||||
{
|
||||
aBegins2D (i) = myXY->Value (2 * i - 1);
|
||||
anEnds2D (i) = myXY->Value (2 * i);
|
||||
}
|
||||
}
|
||||
// the flags that the edges was considered
|
||||
TColStd_Array1OfBoolean isEdgeUsed (1, aNbEdges);
|
||||
isEdgeUsed.Init (Standard_False);
|
||||
|
||||
Standard_Real aTol2 = Precision::SquareConfusion();
|
||||
Standard_Real aTolP2 = Precision::SquarePConfusion();
|
||||
|
||||
// take the first edge to the constructed chain
|
||||
isEdgeUsed (1) = Standard_True;
|
||||
gp_Pnt aFirstPnt3D = aBegins3D (1);
|
||||
gp_Pnt aLastPnt3D = anEnds3D (1);
|
||||
gp_Pnt2d aFirstPnt2D;
|
||||
gp_Pnt2d aLastPnt2D;
|
||||
if (myMode == ModeBoth)
|
||||
{
|
||||
aFirstPnt2D = aBegins2D (1);
|
||||
aLastPnt2D = anEnds2D (1);
|
||||
}
|
||||
anEdgeSeq->Append (1);
|
||||
|
||||
// cycle until all edges are considered
|
||||
for (;;)
|
||||
{
|
||||
// joint type
|
||||
// 0 - the start of the best edge to the end of constructed sequence (nothing to do)
|
||||
// 1 - the end of the best edge to the start of constructed sequence (need move the edge)
|
||||
// 2 - the end of the best edge to the end of constructed sequence (need to reverse)
|
||||
// 3 - the start of the best edge to the start of constructed sequence (need to reverse and move the edge)
|
||||
Standard_Integer aBestJointType = 3;
|
||||
// the best minimum distance between constructed sequence and the best edge
|
||||
Standard_Real aBestMin3D = RealLast();
|
||||
// number of the best edge
|
||||
Standard_Integer aBestEdgeNum = 0;
|
||||
// the best edge was found
|
||||
Standard_Boolean isFound = Standard_False;
|
||||
Standard_Boolean isConnected = Standard_False;
|
||||
// loop to find the best edge among all the remaining
|
||||
for (Standard_Integer i = 1; i <= aNbEdges; i++)
|
||||
{
|
||||
if (isEdgeUsed (i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// find minimum distance and joint type for 3D and 2D (if necessary) modes
|
||||
Standard_Integer aCurJointType;
|
||||
Standard_Real aCurMin;
|
||||
// distance for four possible cases
|
||||
Standard_Real aSeqTailEdgeHead = aLastPnt3D.SquareDistance (aBegins3D (i));
|
||||
Standard_Real aSeqTailEdgeTail = aLastPnt3D.SquareDistance (anEnds3D (i));
|
||||
Standard_Real aSeqHeadEdgeTail = aFirstPnt3D.SquareDistance (anEnds3D (i));
|
||||
Standard_Real aSeqHeadEdgeHead = aFirstPnt3D.SquareDistance (aBegins3D (i));
|
||||
// the best distances for joints with head and tail of sequence
|
||||
Standard_Real aMinDistToTail, aMinDistToHead;
|
||||
Standard_Integer aTailJoinType, aHeadJointType;
|
||||
if (aSeqTailEdgeHead <= aSeqTailEdgeTail)
|
||||
{
|
||||
aTailJoinType = 0;
|
||||
aMinDistToTail = aSeqTailEdgeHead;
|
||||
}
|
||||
else
|
||||
{
|
||||
aTailJoinType = 2;
|
||||
aMinDistToTail = aSeqTailEdgeTail;
|
||||
}
|
||||
if (aSeqHeadEdgeTail <= aSeqHeadEdgeHead)
|
||||
{
|
||||
aHeadJointType = 1;
|
||||
aMinDistToHead = aSeqHeadEdgeTail;
|
||||
}
|
||||
else
|
||||
{
|
||||
aHeadJointType = 3;
|
||||
aMinDistToHead = aSeqHeadEdgeHead;
|
||||
}
|
||||
// comparing the head and the tail cases
|
||||
// if distances are close enough then we use rule for joint type: 0 < 1 < 2 < 3
|
||||
if (fabs (aMinDistToTail - aMinDistToHead) < aTol2)
|
||||
{
|
||||
if (aTailJoinType < aHeadJointType)
|
||||
{
|
||||
aCurJointType = aTailJoinType;
|
||||
aCurMin = aMinDistToTail;
|
||||
}
|
||||
else
|
||||
{
|
||||
aCurJointType = aHeadJointType;
|
||||
aCurMin = aMinDistToHead;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aMinDistToTail <= aMinDistToHead)
|
||||
{
|
||||
aCurJointType = aTailJoinType;
|
||||
aCurMin = aMinDistToTail;
|
||||
}
|
||||
else
|
||||
{
|
||||
aCurJointType = aHeadJointType;
|
||||
aCurMin = aMinDistToHead;
|
||||
}
|
||||
}
|
||||
// update for the best values
|
||||
if (myMode == ModeBoth)
|
||||
{
|
||||
// distances in 2D
|
||||
Standard_Integer aJointMask3D = 0, aJointMask2D = 0;
|
||||
if (aSeqTailEdgeHead < aTol2)
|
||||
{
|
||||
aJointMask3D |= (1 << 0);
|
||||
}
|
||||
if (aSeqTailEdgeTail < aTol2)
|
||||
{
|
||||
aJointMask3D |= (1 << 2);
|
||||
}
|
||||
if (aSeqHeadEdgeTail < aTol2)
|
||||
{
|
||||
aJointMask3D |= (1 << 1);
|
||||
}
|
||||
if (aSeqHeadEdgeHead < aTol2)
|
||||
{
|
||||
aJointMask3D |= (1 << 3);
|
||||
}
|
||||
Standard_Real aSeqTailEdgeHead2D = aLastPnt2D.SquareDistance (aBegins2D (i));
|
||||
Standard_Real aSeqTailEdgeTail2D = aLastPnt2D.SquareDistance (anEnds2D (i));
|
||||
Standard_Real aSeqHeadEdgeTail2D = aFirstPnt2D.SquareDistance (anEnds2D (i));
|
||||
Standard_Real aSeqHeadEdgeHead2D = aFirstPnt2D.SquareDistance (aBegins2D (i));
|
||||
if (aSeqTailEdgeHead2D < aTolP2)
|
||||
{
|
||||
aJointMask2D |= (1 << 0);
|
||||
}
|
||||
if (aSeqTailEdgeTail2D < aTolP2)
|
||||
{
|
||||
aJointMask2D |= (1 << 2);
|
||||
}
|
||||
if (aSeqHeadEdgeTail2D < aTolP2)
|
||||
{
|
||||
aJointMask2D |= (1 << 1);
|
||||
}
|
||||
if (aSeqHeadEdgeHead2D < aTolP2)
|
||||
{
|
||||
aJointMask2D |= (1 << 3);
|
||||
}
|
||||
// new approche for detecting best edge connection, for all other cases used old 3D algorithm
|
||||
Standard_Integer aFullMask = aJointMask3D & aJointMask2D;
|
||||
if (aFullMask != 0)
|
||||
{
|
||||
// find the best current joint type
|
||||
aCurJointType = 3;
|
||||
for (Standard_Integer j = 0; j < 4; j++)
|
||||
{
|
||||
if (aFullMask & (1 << j))
|
||||
{
|
||||
aCurJointType = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isConnected || aCurJointType < aBestJointType)
|
||||
{
|
||||
isFound = Standard_True;
|
||||
isConnected = Standard_True;
|
||||
switch (aCurJointType)
|
||||
{
|
||||
case 0:
|
||||
aBestMin3D = aSeqTailEdgeHead;
|
||||
break;
|
||||
case 1:
|
||||
aBestMin3D = aSeqHeadEdgeTail;
|
||||
break;
|
||||
case 2:
|
||||
aBestMin3D = aSeqTailEdgeTail;
|
||||
break;
|
||||
case 3:
|
||||
aBestMin3D = aSeqHeadEdgeHead;
|
||||
break;
|
||||
}
|
||||
aBestJointType = aCurJointType;
|
||||
aBestEdgeNum = i;
|
||||
}
|
||||
}
|
||||
// if there is still no connection, continue to use ald 3D algorithm
|
||||
if (isConnected)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// if the best distance is still not reached (aBestMin3D > aTol2) or we found a better joint type
|
||||
if (aBestMin3D > aTol2 || aCurJointType < aBestJointType)
|
||||
{
|
||||
// make a decision that this edge is good enough:
|
||||
// - it gets the best distance but there is fabs(aCurMin3d - aBestMin3d) < aTol2 && (aCurJointType < aBestJointType) ?
|
||||
// - it gets the best joint in some cases
|
||||
if (aCurMin < aBestMin3D || ((aCurMin == aBestMin3D || aCurMin < aTol2) && (aCurJointType < aBestJointType)))
|
||||
{
|
||||
isFound = Standard_True;
|
||||
aBestMin3D = aCurMin;
|
||||
aBestJointType = aCurJointType;
|
||||
aBestEdgeNum = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check that we found edge for connecting
|
||||
if (isFound)
|
||||
{
|
||||
// distance between first and last point in sequence
|
||||
Standard_Real aCloseDist = aFirstPnt3D.SquareDistance (aLastPnt3D);
|
||||
// if it's better to insert the edge than to close the loop, just insert the edge according to joint type
|
||||
if (aBestMin3D <= RealSmall() || aBestMin3D < aCloseDist)
|
||||
{
|
||||
switch (aBestJointType)
|
||||
{
|
||||
case 0:
|
||||
anEdgeSeq->Append (aBestEdgeNum);
|
||||
aLastPnt3D = anEnds3D (aBestEdgeNum);
|
||||
break;
|
||||
case 1:
|
||||
anEdgeSeq->Prepend (aBestEdgeNum);
|
||||
aFirstPnt3D = aBegins3D (aBestEdgeNum);
|
||||
break;
|
||||
case 2:
|
||||
anEdgeSeq->Append (-aBestEdgeNum);
|
||||
aLastPnt3D = aBegins3D (aBestEdgeNum);
|
||||
break;
|
||||
case 3:
|
||||
anEdgeSeq->Prepend (-aBestEdgeNum);
|
||||
aFirstPnt3D = anEnds3D (aBestEdgeNum);
|
||||
break;
|
||||
}
|
||||
if (myMode == ModeBoth)
|
||||
{
|
||||
switch (aBestJointType)
|
||||
{
|
||||
case 0:
|
||||
aLastPnt2D = anEnds2D (aBestEdgeNum);
|
||||
break;
|
||||
case 1:
|
||||
aFirstPnt2D = aBegins2D (aBestEdgeNum);
|
||||
break;
|
||||
case 2:
|
||||
aLastPnt2D = aBegins2D (aBestEdgeNum);
|
||||
break;
|
||||
case 3:
|
||||
aFirstPnt2D = anEnds2D (aBestEdgeNum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// closing loop and creating new one
|
||||
else
|
||||
{
|
||||
aLoops.Append (anEdgeSeq);
|
||||
anEdgeSeq = new TColStd_HSequenceOfInteger;
|
||||
aFirstPnt3D = aBegins3D (aBestEdgeNum);
|
||||
aLastPnt3D = anEnds3D (aBestEdgeNum);
|
||||
if (myMode == ModeBoth)
|
||||
{
|
||||
aFirstPnt2D = aBegins2D (aBestEdgeNum);
|
||||
aLastPnt2D = anEnds2D (aBestEdgeNum);
|
||||
}
|
||||
anEdgeSeq->Append (aBestEdgeNum);
|
||||
}
|
||||
// mark the edge as used
|
||||
isEdgeUsed (aBestEdgeNum) = Standard_True;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the only condition under which we can't find an edge is when all edges are done
|
||||
break;
|
||||
}
|
||||
}
|
||||
// append the last loop
|
||||
aLoops.Append (anEdgeSeq);
|
||||
|
||||
// handling with constructed loops
|
||||
Handle(TColStd_HSequenceOfInteger) aMainLoop;
|
||||
if (myKeepLoops)
|
||||
{
|
||||
// keeping the loops, adding one after another.
|
||||
aMainLoop = new TColStd_HSequenceOfInteger;
|
||||
for (Standard_Integer i = 1; i <= aLoops.Length(); i++)
|
||||
{
|
||||
const Handle(TColStd_HSequenceOfInteger)& aCurLoop = aLoops (i);
|
||||
aMainLoop->Append (aCurLoop);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// connecting loops
|
||||
aMainLoop = aLoops.First();
|
||||
aLoops.Remove (1);
|
||||
while (aLoops.Length())
|
||||
{
|
||||
// iterate over all loops to find the closest one
|
||||
Standard_Real aMinDist1 = RealLast();
|
||||
Standard_Integer aLoopNum1 = 0;
|
||||
Standard_Integer aCurLoopIt1 = 0;
|
||||
Standard_Boolean aDirect1 = Standard_False;
|
||||
Standard_Integer aMainLoopIt1 = 0;
|
||||
for (Standard_Integer aLoopIt = 1; aLoopIt <= aLoops.Length(); aLoopIt++)
|
||||
{
|
||||
const Handle(TColStd_HSequenceOfInteger)& aCurLoop = aLoops.Value (aLoopIt);
|
||||
// iterate over all gaps between edges in current loop
|
||||
Standard_Integer aCurLoopIt2 = 0;
|
||||
Standard_Integer aMainLoopIt2 = 0;
|
||||
Standard_Boolean aDirect2 = Standard_False;
|
||||
Standard_Real aMinDist2 = RealLast();
|
||||
Standard_Integer aCurLoopLength = aCurLoop->Length();
|
||||
for (Standard_Integer aCurEdgeIt = 1; aCurEdgeIt <= aCurLoopLength; aCurEdgeIt++)
|
||||
{
|
||||
// get the distance between the current edge and the previous edge taking into account the edge's orientation
|
||||
Standard_Integer aPrevEdgeIt = aCurEdgeIt == 1 ? aCurLoopLength : aCurEdgeIt - 1;
|
||||
Standard_Integer aCurEdgeIdx = aCurLoop->Value (aCurEdgeIt);
|
||||
Standard_Integer aPrevEdgeIdx = aCurLoop->Value (aPrevEdgeIt);
|
||||
gp_Pnt aCurLoopFirst = aCurEdgeIdx > 0 ? aBegins3D (aCurEdgeIdx) : anEnds3D (-aCurEdgeIdx);
|
||||
gp_Pnt aCurLoopLast = aPrevEdgeIdx > 0 ? anEnds3D (aPrevEdgeIdx) : aBegins3D (-aPrevEdgeIdx);
|
||||
// iterate over all gaps between edges in main loop
|
||||
Standard_Real aMinDist3 = RealLast();
|
||||
Standard_Integer aMainLoopIt3 = 0;
|
||||
Standard_Boolean aDirect3 = Standard_False;
|
||||
Standard_Integer aMainLoopLength = aMainLoop->Length();
|
||||
for (Standard_Integer aCurEdgeIt2 = 1; (aCurEdgeIt2 <= aMainLoopLength) && aMinDist3 != 0.0; aCurEdgeIt2++)
|
||||
{
|
||||
// get the distance between the current edge and the next edge taking into account the edge's orientation
|
||||
Standard_Integer aNextEdgeIt2 = aCurEdgeIt2 == aMainLoopLength ? 1 : aCurEdgeIt2 + 1;
|
||||
Standard_Integer aCurEdgeIdx2 = aMainLoop->Value (aCurEdgeIt2);
|
||||
Standard_Integer aNextEdgeIdx2 = aMainLoop->Value (aNextEdgeIt2);
|
||||
gp_Pnt aMainLoopFirst = (aCurEdgeIdx2 > 0 ? anEnds3D (aCurEdgeIdx2) : aBegins3D (-aCurEdgeIdx2));
|
||||
gp_Pnt aMainLoopLast = (aNextEdgeIdx2 > 0 ? aBegins3D (aNextEdgeIdx2) : anEnds3D (-aNextEdgeIdx2));
|
||||
// getting the sum of square distances if we try to sew the current loop with the main loop in current positions
|
||||
Standard_Real aDirectDist =
|
||||
aCurLoopFirst.SquareDistance (aMainLoopFirst) + aCurLoopLast.SquareDistance (aMainLoopLast);
|
||||
Standard_Real aReverseDist =
|
||||
aCurLoopFirst.SquareDistance (aMainLoopLast) + aCurLoopLast.SquareDistance (aMainLoopFirst);
|
||||
// take the best result
|
||||
Standard_Real aJoinDist;
|
||||
if ((aDirectDist < aTol2) || (aDirectDist < 2.0 * aReverseDist))
|
||||
{
|
||||
aJoinDist = aDirectDist;
|
||||
aReverseDist = aDirectDist;
|
||||
}
|
||||
else
|
||||
{
|
||||
aJoinDist = aReverseDist;
|
||||
}
|
||||
// check if we found a better distance
|
||||
if (aJoinDist < aMinDist3 && Abs (aMinDist3 - aJoinDist) > aTol2)
|
||||
{
|
||||
aMinDist3 = aJoinDist;
|
||||
aDirect3 = (aDirectDist <= aReverseDist);
|
||||
aMainLoopIt3 = aCurEdgeIt2;
|
||||
}
|
||||
}
|
||||
// check if we found a better distance
|
||||
if (aMinDist3 < aMinDist2 && Abs (aMinDist2 - aMinDist3) > aTol2)
|
||||
{
|
||||
aMinDist2 = aMinDist3;
|
||||
aDirect2 = aDirect3;
|
||||
aMainLoopIt2 = aMainLoopIt3;
|
||||
aCurLoopIt2 = aCurEdgeIt;
|
||||
}
|
||||
}
|
||||
// check if we found a better distance
|
||||
if (aMinDist2 < aMinDist1 && Abs (aMinDist1 - aMinDist2) > aTol2)
|
||||
{
|
||||
aMinDist1 = aMinDist2;
|
||||
aLoopNum1 = aLoopIt;
|
||||
aDirect1 = aDirect2;
|
||||
aMainLoopIt1 = aMainLoopIt2;
|
||||
aCurLoopIt1 = aCurLoopIt2;
|
||||
}
|
||||
}
|
||||
// insert the found loop into main loop
|
||||
Handle(TColStd_HSequenceOfInteger) aLoop = aLoops.Value (aLoopNum1);
|
||||
Standard_Integer aFactor = (aDirect1 ? 1 : -1);
|
||||
for (Standard_Integer i = 0; i < aLoop->Length(); i++)
|
||||
{
|
||||
Standard_Integer anIdx = (aCurLoopIt1 + i > aLoop->Length() ? aCurLoopIt1 + i - aLoop->Length() :
|
||||
aCurLoopIt1 + i);
|
||||
aMainLoop->InsertAfter (aMainLoopIt1 + i, aLoop->Value (anIdx) * aFactor);
|
||||
}
|
||||
aLoops.Remove (aLoopNum1);
|
||||
}
|
||||
}
|
||||
|
||||
// checking the new order of the edges
|
||||
// 0 - order is the same
|
||||
// 1 - some edges were reordered
|
||||
// -1 - some edges were reversed
|
||||
Standard_Integer aTempStatus = 0;
|
||||
for (Standard_Integer i = 1; i <= aMainLoop->Length(); i++)
|
||||
{
|
||||
if (i != aMainLoop->Value (i) && aTempStatus >= 0)
|
||||
{
|
||||
aTempStatus = (aMainLoop->Value (i) > 0 ? 1 : -1);
|
||||
}
|
||||
myOrd->SetValue (i, aMainLoop->Value (i));
|
||||
}
|
||||
if (aTempStatus == 0)
|
||||
{
|
||||
myStat = aTempStatus;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if edges were only shifted in reverse or forward, not reordered
|
||||
Standard_Boolean isShiftReverse = Standard_True;
|
||||
Standard_Boolean isShiftForward = Standard_True;
|
||||
Standard_Integer aFirstIdx, aSecondIdx;
|
||||
Standard_Integer aLength = aMainLoop->Length();
|
||||
for (Standard_Integer i = 1; i <= aLength - 1; i++)
|
||||
{
|
||||
aFirstIdx = aMainLoop->Value (i);
|
||||
aSecondIdx = aMainLoop->Value (i + 1);
|
||||
if (!(aSecondIdx - aFirstIdx == 1 || (aFirstIdx == aLength && aSecondIdx == 1)))
|
||||
{
|
||||
isShiftForward = Standard_False;
|
||||
if (!(tmpFirst - tmpSecond == 1 || (tmpSecond == length && tmpFirst == 1)))
|
||||
}
|
||||
if (!(aFirstIdx - aSecondIdx == 1 || (aSecondIdx == aLength && aFirstIdx == 1)))
|
||||
{
|
||||
isShiftReverse = Standard_False;
|
||||
}
|
||||
tmpFirst = mainSeq->Value(length);
|
||||
tmpSecond = mainSeq->Value(1);
|
||||
if (!(tmpSecond - tmpFirst == 1 || (tmpFirst == length && tmpSecond == 1)))
|
||||
}
|
||||
aFirstIdx = aMainLoop->Value (aLength);
|
||||
aSecondIdx = aMainLoop->Value (1);
|
||||
if (!(aSecondIdx - aFirstIdx == 1 || (aFirstIdx == aLength && aSecondIdx == 1)))
|
||||
{
|
||||
isShiftForward = Standard_False;
|
||||
if (!(tmpFirst - tmpSecond == 1 || (tmpSecond == length && tmpFirst == 1)))
|
||||
}
|
||||
if (!(aFirstIdx - aSecondIdx == 1 || (aSecondIdx == aLength && aFirstIdx == 1)))
|
||||
{
|
||||
isShiftReverse = Standard_False;
|
||||
}
|
||||
if (isShiftForward || isShiftReverse)
|
||||
stTmp = 3;
|
||||
myStat = stTmp;
|
||||
{
|
||||
aTempStatus = 3;
|
||||
}
|
||||
myStat = aTempStatus;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -423,11 +726,11 @@ void ShapeAnalysis_WireOrder::Perform(const Standard_Boolean /*closed*/)
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
Standard_Integer ShapeAnalysis_WireOrder::Ordered(const Standard_Integer n) const
|
||||
Standard_Integer ShapeAnalysis_WireOrder::Ordered (const Standard_Integer theIdx) const
|
||||
{
|
||||
if (myOrd.IsNull() || myOrd->Upper() < n) return n;
|
||||
Standard_Integer ord = myOrd->Value(n);
|
||||
return (ord == 0 ? n : ord);
|
||||
if (myOrd.IsNull() || myOrd->Upper() < theIdx) return theIdx;
|
||||
Standard_Integer anOldIdx = myOrd->Value (theIdx);
|
||||
return (anOldIdx == 0 ? theIdx : anOldIdx);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -435,15 +738,10 @@ void ShapeAnalysis_WireOrder::Perform(const Standard_Boolean /*closed*/)
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void ShapeAnalysis_WireOrder::XYZ(const Standard_Integer num,gp_XYZ& start3d,gp_XYZ& end3d) const
|
||||
void ShapeAnalysis_WireOrder::XYZ (const Standard_Integer theIdx, gp_XYZ& theStart3D, gp_XYZ& theEnd3D) const
|
||||
{
|
||||
if (num > 0) {
|
||||
start3d = myXYZ->Value (2*num-1);
|
||||
end3d = myXYZ->Value (2*num);
|
||||
} else {
|
||||
start3d = myXYZ->Value (-2*num);
|
||||
end3d = myXYZ->Value (-2*num-1);
|
||||
}
|
||||
theStart3D = myXYZ->Value ((theIdx > 0 ? 2 * theIdx - 1 : -2 * theIdx));
|
||||
theEnd3D = myXYZ->Value ((theIdx > 0 ? 2 * theIdx : -2 * theIdx - 1));
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -451,12 +749,20 @@ void ShapeAnalysis_WireOrder::Perform(const Standard_Boolean /*closed*/)
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void ShapeAnalysis_WireOrder::XY(const Standard_Integer num,gp_XY& start2d,gp_XY& end2d) const
|
||||
void ShapeAnalysis_WireOrder::XY (const Standard_Integer theIdx, gp_XY& theStart2D, gp_XY& theEnd2D) const
|
||||
{
|
||||
const gp_XYZ& st2d = myXYZ->Value ( (num > 0 ? 2*num-1 : -2*num) );
|
||||
start2d.SetCoord (st2d.X(),st2d.Y());
|
||||
const gp_XYZ& en2d = myXYZ->Value ( (num > 0 ? 2*num : -2*num -1) );
|
||||
end2d.SetCoord (en2d.X(),en2d.Y());
|
||||
if (myMode == ModeBoth)
|
||||
{
|
||||
theStart2D = myXY->Value ((theIdx > 0 ? 2 * theIdx - 1 : -2 * theIdx));
|
||||
theEnd2D = myXY->Value ((theIdx > 0 ? 2 * theIdx : -2 * theIdx - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
const gp_XYZ& aStart3d = myXYZ->Value ((theIdx > 0 ? 2 * theIdx - 1 : -2 * theIdx));
|
||||
theStart2D.SetCoord (aStart3d.X(), aStart3d.Y());
|
||||
const gp_XYZ& anEnd3d = myXYZ->Value ((theIdx > 0 ? 2 * theIdx : -2 * theIdx - 1));
|
||||
theEnd2D.SetCoord (anEnd3d.X(), anEnd3d.Y());
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -482,14 +788,16 @@ void ShapeAnalysis_WireOrder::Perform(const Standard_Boolean /*closed*/)
|
||||
|
||||
void ShapeAnalysis_WireOrder::SetChains (const Standard_Real gap)
|
||||
{
|
||||
Standard_Integer n0 = 0, n1, n2, nb = NbEdges(); //szv#4:S4163:12Mar99 o0,o1,o2 not needed
|
||||
Standard_Integer n0, n1, n2, nb = NbEdges(); //szv#4:S4163:12Mar99 o0,o1,o2 not needed
|
||||
if (nb == 0) return;
|
||||
TColStd_SequenceOfInteger chain;
|
||||
n0 = 0;
|
||||
chain.Append (1); // On demarre la partie
|
||||
gp_XYZ f3d, l3d, f13d, l13d; //szv#4:S4163:12Mar99 f03d,l03d unused
|
||||
for (n1 = 1; n1 <= nb; n1 ++) {
|
||||
if (n0 == 0) { // nouvelle boucle
|
||||
for (n1 = 1; n1 <= nb; n1++)
|
||||
{
|
||||
if (n0 == 0)
|
||||
{ // nouvelle boucle
|
||||
n0 = n1;
|
||||
//szv#4:S4163:12Mar99 optimized
|
||||
XYZ (Ordered (n0), f13d, l13d);
|
||||
@ -497,8 +805,13 @@ void ShapeAnalysis_WireOrder::SetChains(const Standard_Real gap)
|
||||
//szv#4:S4163:12Mar99 optimized
|
||||
n2 = (n1 == nb) ? n0 : (n1 + 1);
|
||||
XYZ (Ordered (n2), f3d, l3d);
|
||||
if (!f3d.IsEqual (l13d,gap)) { chain.Append (n2); n0 = 0; }
|
||||
f13d = f3d; l13d = l3d;
|
||||
if (!f3d.IsEqual (l13d, gap))
|
||||
{
|
||||
chain.Append (n2);
|
||||
n0 = 0;
|
||||
}
|
||||
f13d = f3d;
|
||||
l13d = l3d;
|
||||
}
|
||||
nb = chain.Length();
|
||||
if (nb == 0) return;
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <Standard_Boolean.hxx>
|
||||
#include <TColStd_HArray1OfInteger.hxx>
|
||||
#include <TColgp_HSequenceOfXY.hxx>
|
||||
#include <TColgp_HSequenceOfXYZ.hxx>
|
||||
#include <Standard_Real.hxx>
|
||||
#include <Standard_Integer.hxx>
|
||||
@ -41,10 +42,8 @@ class gp_XY;
|
||||
//! This allows to use this tool, either on existing wire, or on
|
||||
//! data just taken from a file (coordinates are easy to get)
|
||||
//!
|
||||
//! It can work, either in 2D, or in 3D, but not miscible
|
||||
//! Warning about tolerance : according to the mode (2D/3D), it
|
||||
//! must be given as 2D or 3D (i.e. metric) tolerance, uniform
|
||||
//! on the whole list
|
||||
//! It can work, either in 2D, or in 3D, or miscible mode
|
||||
//! The tolerance for each mode is fixed
|
||||
//!
|
||||
//! Two phases : firstly add the couples (start, end)
|
||||
//! secondly perform then get the result
|
||||
@ -54,17 +53,24 @@ public:
|
||||
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
|
||||
//! Empty constructor
|
||||
Standard_EXPORT ShapeAnalysis_WireOrder();
|
||||
|
||||
//! Creates a WireOrder in 3D (if mode3d is True) or 2D (if False)
|
||||
//! with a tolerance
|
||||
Standard_EXPORT ShapeAnalysis_WireOrder(const Standard_Boolean mode3d, const Standard_Real tol);
|
||||
//! Creates a WireOrder.
|
||||
//! Flag <theMode3D> defines 3D or 2d mode.
|
||||
//! Flag <theModeBoth> defines miscible mode and the flag <theMode3D> is ignored.
|
||||
//! Warning: Parameter <theTolerance> is not used in algorithm.
|
||||
Standard_EXPORT ShapeAnalysis_WireOrder (const Standard_Boolean theMode3D,
|
||||
const Standard_Real theTolerance,
|
||||
const Standard_Boolean theModeBoth = Standard_False);
|
||||
|
||||
//! Sets new values. Clears the connexion list
|
||||
//! If <mode3d> changes, also clears the edge list (else, doesn't)
|
||||
Standard_EXPORT void SetMode (const Standard_Boolean mode3d, const Standard_Real tol);
|
||||
//! Sets new values.
|
||||
//! Clears the edge list if the mode (<theMode3D> or <theModeBoth> ) changes.
|
||||
//! Clears the connexion list.
|
||||
//! Warning: Parameter <theTolerance> is not used in algorithm.
|
||||
Standard_EXPORT void SetMode (const Standard_Boolean theMode3D,
|
||||
const Standard_Real theTolerance,
|
||||
const Standard_Boolean theModeBoth = Standard_False);
|
||||
|
||||
//! Returns the working tolerance
|
||||
Standard_EXPORT Standard_Real Tolerance() const;
|
||||
@ -73,10 +79,16 @@ public:
|
||||
Standard_EXPORT void Clear();
|
||||
|
||||
//! Adds a couple of points 3D (start, end)
|
||||
Standard_EXPORT void Add (const gp_XYZ& start3d, const gp_XYZ& end3d);
|
||||
Standard_EXPORT void Add (const gp_XYZ& theStart3d, const gp_XYZ& theEnd3d);
|
||||
|
||||
//! Adds a couple of points 2D (start, end)
|
||||
Standard_EXPORT void Add (const gp_XY& start2d, const gp_XY& end2d);
|
||||
Standard_EXPORT void Add (const gp_XY& theStart2d, const gp_XY& theEnd2d);
|
||||
|
||||
//! Adds a couple of points 3D and 2D (start, end)
|
||||
Standard_EXPORT void Add (const gp_XYZ& theStart3d,
|
||||
const gp_XYZ& theEnd3d,
|
||||
const gp_XY& theStart2d,
|
||||
const gp_XY& theEnd2d);
|
||||
|
||||
//! Returns the count of added couples of points (one per edges)
|
||||
Standard_EXPORT Standard_Integer NbEdges() const;
|
||||
@ -87,12 +99,11 @@ public:
|
||||
Standard_EXPORT Standard_Boolean& KeepLoopsMode();
|
||||
|
||||
//! Computes the better order
|
||||
//! If <closed> is True (D) considers also closure
|
||||
//! Optimised if the couples were already in order
|
||||
//! The criterium is : two couples in order if distance between
|
||||
//! end-prec and start-cur is less then starting tolerance <tol>
|
||||
//! Else, the smallest distance is reached
|
||||
//! Gap corresponds to a smallest distance greater than <tol>
|
||||
//! Warning: Parameter <closed> not used
|
||||
Standard_EXPORT void Perform (const Standard_Boolean closed = Standard_True);
|
||||
|
||||
//! Tells if Perform has been done
|
||||
@ -102,23 +113,20 @@ public:
|
||||
//! Returns the status of the order (0 if not done) :
|
||||
//! 0 : all edges are direct and in sequence
|
||||
//! 1 : all edges are direct but some are not in sequence
|
||||
//! 2 : in addition, unresolved gaps remain
|
||||
//! -1 : some edges are reversed, but no gap remain
|
||||
//! -2 : some edges are reversed and some gaps remain
|
||||
//! -10 : COULD NOT BE RESOLVED, Failure on Reorder
|
||||
//! gap : regarding starting <tol>
|
||||
//! 3 : edges in sequence are just shifted in forward or reverse manner
|
||||
Standard_EXPORT Standard_Integer Status() const;
|
||||
|
||||
//! Returns the number of original edge which correspond to the
|
||||
//! newly ordered number <n>
|
||||
//! Warning : the returned value is NEGATIVE if edge should be reversed
|
||||
Standard_EXPORT Standard_Integer Ordered (const Standard_Integer n) const;
|
||||
Standard_EXPORT Standard_Integer Ordered (const Standard_Integer theIdx) const;
|
||||
|
||||
//! Returns the values of the couple <num>, as 3D values
|
||||
Standard_EXPORT void XYZ (const Standard_Integer num, gp_XYZ& start3d, gp_XYZ& end3d) const;
|
||||
Standard_EXPORT void XYZ (const Standard_Integer theIdx, gp_XYZ& theStart3D, gp_XYZ& theEnd3D) const;
|
||||
|
||||
//! Returns the values of the couple <num>, as 2D values
|
||||
Standard_EXPORT void XY (const Standard_Integer num, gp_XY& start2d, gp_XY& end2d) const;
|
||||
Standard_EXPORT void XY (const Standard_Integer theIdx, gp_XY& theStart2D, gp_XY& theEnd2D) const;
|
||||
|
||||
//! Returns the gap between a couple and its preceding
|
||||
//! <num> is considered ordered
|
||||
@ -138,6 +146,7 @@ public:
|
||||
|
||||
//! Determines the couples of edges for which end and start fit
|
||||
//! inside a given gap. Queried by NbCouples and Couple
|
||||
//! Warning: function isn't implemented
|
||||
Standard_EXPORT void SetCouples (const Standard_Real gap);
|
||||
|
||||
//! Returns the count of computed couples
|
||||
@ -147,36 +156,27 @@ public:
|
||||
//! In the list of ordered edges
|
||||
Standard_EXPORT void Couple (const Standard_Integer num, Standard_Integer& n1, Standard_Integer& n2) const;
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
// the mode in which the algorithm works
|
||||
enum ModeType
|
||||
{
|
||||
Mode2D,
|
||||
Mode3D,
|
||||
ModeBoth
|
||||
};
|
||||
|
||||
|
||||
|
||||
Standard_Boolean myKeepLoops;
|
||||
Handle(TColStd_HArray1OfInteger) myOrd;
|
||||
Handle(TColStd_HArray1OfInteger) myChains;
|
||||
Handle(TColStd_HArray1OfInteger) myCouples;
|
||||
Handle(TColgp_HSequenceOfXYZ) myXYZ;
|
||||
Handle(TColgp_HSequenceOfXY) myXY;
|
||||
Standard_Real myTol;
|
||||
Standard_Real myGap;
|
||||
Standard_Integer myStat;
|
||||
Standard_Boolean myMode;
|
||||
|
||||
|
||||
Standard_Boolean myKeepLoops;
|
||||
ModeType myMode;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // _ShapeAnalysis_WireOrder_HeaderFile
|
||||
|
@ -433,51 +433,53 @@ Standard_Boolean ShapeFix_Wire::Perform()
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean ShapeFix_Wire::FixReorder()
|
||||
Standard_Boolean ShapeFix_Wire::FixReorder(Standard_Boolean theModeBoth)
|
||||
{
|
||||
myStatusReorder = ShapeExtend::EncodeStatus(ShapeExtend_OK);
|
||||
if ( ! IsLoaded() ) return Standard_False;
|
||||
|
||||
// fix in 3d
|
||||
ShapeAnalysis_WireOrder sawo;
|
||||
myAnalyzer->CheckOrder ( sawo, myClosedMode, Standard_True );
|
||||
|
||||
//:abv revolCuts.sat -23: in case of bi-periodic surface check case
|
||||
// of reversed wire specifically. This is necessary because degenerated
|
||||
// cases are possible when direct evaluation will give bad result.
|
||||
Standard_Boolean isReorder = Standard_False;
|
||||
if ( sawo.Status() != 0 &&
|
||||
! myAnalyzer->Surface().IsNull() &&
|
||||
myAnalyzer->Surface()->Surface()->IsUPeriodic() &&
|
||||
myAnalyzer->Surface()->Surface()->IsVPeriodic() ) {
|
||||
Handle(ShapeExtend_WireData) sbwd2 = new ShapeExtend_WireData;
|
||||
for ( Standard_Integer i=WireData()->NbEdges(); i >=1; i-- )
|
||||
sbwd2->Add ( WireData()->Edge(i) );
|
||||
ShapeAnalysis_WireOrder sawo2;
|
||||
ShapeAnalysis_Wire analyzer2 ( sbwd2, myAnalyzer->Face(), Precision() );
|
||||
analyzer2.CheckOrder ( sawo2, myClosedMode, Standard_True );
|
||||
if ( ( sawo2.Status() >=0 && sawo2.Status() < sawo.Status() ) ||
|
||||
( sawo.Status() <0 && sawo2.Status() > sawo.Status() ) ) {
|
||||
WireData()->Init ( sbwd2 );
|
||||
sawo = sawo2;
|
||||
isReorder = Standard_True;
|
||||
if (!IsLoaded())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// fix in Both mode for bi-periodic surface
|
||||
ShapeAnalysis_WireOrder sawo;
|
||||
if (!myAnalyzer->Surface().IsNull() &&
|
||||
myAnalyzer->Surface()->Surface()->IsUPeriodic() &&
|
||||
myAnalyzer->Surface()->Surface()->IsVPeriodic() &&
|
||||
theModeBoth)
|
||||
{
|
||||
myAnalyzer->CheckOrder(sawo, myClosedMode, Standard_True, Standard_True);
|
||||
}
|
||||
else
|
||||
{
|
||||
myAnalyzer->CheckOrder(sawo, myClosedMode, Standard_True, Standard_False);
|
||||
}
|
||||
|
||||
FixReorder(sawo);
|
||||
|
||||
if (LastFixStatus(ShapeExtend_FAIL))
|
||||
myStatusReorder |= ShapeExtend::EncodeStatus ( LastFixStatus ( ShapeExtend_FAIL1 ) ?
|
||||
ShapeExtend_FAIL1 : ShapeExtend_FAIL2 );
|
||||
if ( ! LastFixStatus ( ShapeExtend_DONE )&& !isReorder ) return Standard_False;
|
||||
{
|
||||
myStatusReorder |= ShapeExtend::EncodeStatus(LastFixStatus(ShapeExtend_FAIL1) ? ShapeExtend_FAIL1 : ShapeExtend_FAIL2);
|
||||
}
|
||||
if (!LastFixStatus(ShapeExtend_DONE))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
myStatusReorder |= ShapeExtend::EncodeStatus(ShapeExtend_DONE1);
|
||||
if (sawo.Status() == 2 || sawo.Status() == -2)
|
||||
{
|
||||
myStatusReorder |= ShapeExtend::EncodeStatus(ShapeExtend_DONE2);
|
||||
}
|
||||
if (sawo.Status() < 0)
|
||||
{
|
||||
myStatusReorder |= ShapeExtend::EncodeStatus(ShapeExtend_DONE3);
|
||||
}
|
||||
if (sawo.Status() == 3)
|
||||
myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );//only shifted
|
||||
{
|
||||
// only shifted
|
||||
myStatusReorder |= ShapeExtend::EncodeStatus(ShapeExtend_DONE5);
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
|
@ -267,9 +267,9 @@ public:
|
||||
//! FixLacking (if wire is ordered)
|
||||
Standard_EXPORT Standard_Boolean Perform();
|
||||
|
||||
//! Performs an analysis and reorders edges in the wire using
|
||||
//! class WireOrder
|
||||
Standard_EXPORT Standard_Boolean FixReorder();
|
||||
//! Performs an analysis and reorders edges in the wire using class WireOrder.
|
||||
//! Flag <theModeBoth> determines the use of miscible mode if necessary.
|
||||
Standard_EXPORT Standard_Boolean FixReorder(Standard_Boolean theModeBoth = Standard_False);
|
||||
|
||||
//! Applies FixSmall(num) to all edges in the wire
|
||||
Standard_EXPORT Standard_Integer FixSmall (const Standard_Boolean lockvtx, const Standard_Real precsmall = 0.0);
|
||||
|
@ -76,66 +76,64 @@ void TopoDSToStep_MakeStepWire::Init(const TopoDS_Wire& aWire,
|
||||
TopoDSToStep_Tool& aTool,
|
||||
const Handle(Transfer_FinderProcess)& FP)
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// The Wire is given in its relative orientation (i.e. in the face)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
aTool.SetCurrentWire (aWire);
|
||||
|
||||
if (aTool.IsBound(aWire)) {
|
||||
if (aTool.IsBound (aWire))
|
||||
{
|
||||
myError = TopoDSToStep_WireDone;
|
||||
done = Standard_True;
|
||||
myResult = aTool.Find (aWire);
|
||||
return;
|
||||
}
|
||||
|
||||
Standard_Integer i;
|
||||
|
||||
if (aWire.Orientation() == TopAbs_INTERNAL ||
|
||||
aWire.Orientation() == TopAbs_EXTERNAL ) {
|
||||
Handle(TransferBRep_ShapeMapper) errShape =
|
||||
new TransferBRep_ShapeMapper(aWire);
|
||||
if (aWire.Orientation() == TopAbs_INTERNAL || aWire.Orientation() == TopAbs_EXTERNAL)
|
||||
{
|
||||
Handle(TransferBRep_ShapeMapper) errShape = new TransferBRep_ShapeMapper (aWire);
|
||||
FP->AddWarning (errShape, " Wire(internal/external) from Non Manifold Topology");
|
||||
myError = TopoDSToStep_NonManifoldWire;
|
||||
done = Standard_False;
|
||||
return;
|
||||
}
|
||||
|
||||
BRepTools_WireExplorer ItW;
|
||||
TopoDS_Edge CurrentEdge;
|
||||
TColStd_SequenceOfTransient mySeq;
|
||||
|
||||
// --------
|
||||
// Polyloop
|
||||
// --------
|
||||
|
||||
if (aTool.Faceted()) {
|
||||
if (aTool.Faceted())
|
||||
{
|
||||
Handle(StepShape_VertexPoint) VertexPoint;
|
||||
Handle(StepGeom_Point) Point;
|
||||
Handle(StepShape_TopologicalRepresentationItem) Gpms;
|
||||
TopoDS_Vertex TopoDSVertex1, TopoDSVertex2;
|
||||
|
||||
TopoDSToStep_MakeStepVertex MkVertex;
|
||||
// TopoDS_Wire ForwardWire = TopoDS::Wire(aWire.Oriented(TopAbs_FORWARD));
|
||||
|
||||
for (ItW.Init(aWire, aTool.CurrentFace());
|
||||
ItW.More();ItW.Next()) {
|
||||
CurrentEdge = ItW.Current();
|
||||
for (BRepTools_WireExplorer ItW (aWire, aTool.CurrentFace()); ItW.More(); ItW.Next())
|
||||
{
|
||||
const TopoDS_Edge& CurrentEdge = ItW.Current();
|
||||
if (CurrentEdge.Orientation() == TopAbs_FORWARD)
|
||||
{
|
||||
TopExp::Vertices (CurrentEdge, TopoDSVertex1, TopoDSVertex2);
|
||||
}
|
||||
else
|
||||
{
|
||||
TopExp::Vertices (CurrentEdge, TopoDSVertex2, TopoDSVertex1);
|
||||
}
|
||||
|
||||
MkVertex.Init (TopoDSVertex1, aTool, FP);
|
||||
if (MkVertex.IsDone()) {
|
||||
if (MkVertex.IsDone())
|
||||
{
|
||||
VertexPoint = Handle(StepShape_VertexPoint)::DownCast (MkVertex.Value());
|
||||
Point = VertexPoint->VertexGeometry();
|
||||
mySeq.Append (Point);
|
||||
}
|
||||
else {
|
||||
Handle(TransferBRep_ShapeMapper) errShape =
|
||||
new TransferBRep_ShapeMapper(aWire);
|
||||
else
|
||||
{
|
||||
Handle(TransferBRep_ShapeMapper) errShape = new TransferBRep_ShapeMapper (aWire);
|
||||
FP->AddWarning (errShape, " a Vertex Point not mapped");
|
||||
myError = TopoDSToStep_WireOther;
|
||||
done = Standard_False;
|
||||
@ -143,16 +141,15 @@ void TopoDSToStep_MakeStepWire::Init(const TopoDS_Wire& aWire,
|
||||
}
|
||||
}
|
||||
Standard_Integer nbPoints = mySeq.Length();
|
||||
if (nbPoints>=3) {
|
||||
Handle(StepGeom_HArray1OfCartesianPoint) aPolygon =
|
||||
new StepGeom_HArray1OfCartesianPoint(1,nbPoints);
|
||||
for ( i=1; i<=nbPoints; i++) {
|
||||
aPolygon->SetValue(i, Handle(StepGeom_CartesianPoint)::
|
||||
DownCast(mySeq.Value(i)));
|
||||
if (nbPoints >= 3)
|
||||
{
|
||||
Handle(StepGeom_HArray1OfCartesianPoint) aPolygon = new StepGeom_HArray1OfCartesianPoint (1, nbPoints);
|
||||
for (Standard_Integer i = 1; i <= nbPoints; i++)
|
||||
{
|
||||
aPolygon->SetValue (i, Handle(StepGeom_CartesianPoint)::DownCast (mySeq.Value (i)));
|
||||
}
|
||||
Handle(StepShape_PolyLoop) PL = new StepShape_PolyLoop();
|
||||
Handle(TCollection_HAsciiString) aName =
|
||||
new TCollection_HAsciiString("");
|
||||
Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString ("");
|
||||
PL->Init (aName, aPolygon);
|
||||
|
||||
aTool.Bind (aWire, PL);
|
||||
@ -161,72 +158,75 @@ void TopoDSToStep_MakeStepWire::Init(const TopoDS_Wire& aWire,
|
||||
myResult = PL;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Handle(TransferBRep_ShapeMapper) errShape =
|
||||
new TransferBRep_ShapeMapper(aWire);
|
||||
else
|
||||
{
|
||||
Handle(TransferBRep_ShapeMapper) errShape = new TransferBRep_ShapeMapper (aWire);
|
||||
FP->AddWarning (errShape, " PolyLoop: Wire has less than 3 points");
|
||||
myError = TopoDSToStep_WireOther;
|
||||
done = Standard_False;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// --------
|
||||
// EdgeLoop
|
||||
// --------
|
||||
|
||||
else {
|
||||
|
||||
else
|
||||
{
|
||||
Handle(StepShape_TopologicalRepresentationItem) Gpms;
|
||||
Handle(StepShape_Edge) Epms;
|
||||
Handle(StepShape_OrientedEdge) OrientedEdge;
|
||||
|
||||
TopoDSToStep_MakeStepEdge MkEdge;
|
||||
|
||||
//szv#4:S4163:12Mar99 SGI warns
|
||||
TopoDS_Shape sh = aWire.Oriented(TopAbs_FORWARD);
|
||||
const TopoDS_Wire ForwardWire = TopoDS::Wire(sh);
|
||||
// test 25-01-96 FMA supprime CKY 2-JUN-1997, cf MakeStepFace->Face FWD]
|
||||
// remis CKY 9-DEC-1997 : chaque niveau se traite en FWD
|
||||
//#11 rln 16/03/98
|
||||
//TestRally8 file carter2.rle face#333 (wire is not sorted, not sorted edges are seam and iso-curve):
|
||||
//aWire is REVERSED but ForwardWire is FORWARD, when exploding not connected seams their pcurves are
|
||||
//returned in incorrect order (because of mismatched orientation)
|
||||
//As a result not sorted edges are lost (not returned by BRepTools_WireExplorer)
|
||||
//By the way, in the case of aTool.Faceted() aWire is used
|
||||
|
||||
//#11 ItW.Init(ForwardWire, aTool.CurrentFace());
|
||||
//#11 for (;ItW.More();ItW.Next()) {
|
||||
Handle(ShapeFix_Wire) STW =
|
||||
new ShapeFix_Wire(ForwardWire, aTool.CurrentFace(), Precision::Confusion());
|
||||
STW->FixReorder();
|
||||
Handle(ShapeExtend_WireData) sbwd = STW->WireData();
|
||||
Standard_Integer nb = sbwd->NbEdges();
|
||||
const TopoDS_Wire ForwardWire = TopoDS::Wire (aWire.Oriented (TopAbs_FORWARD));
|
||||
Handle(ShapeFix_Wire) STW = new ShapeFix_Wire (ForwardWire, aTool.CurrentFace(), Precision::Confusion());
|
||||
// for toroidal like surfaces we need to use both (3d and 2d) mode to correctly reorder the edges
|
||||
STW->FixReorder (Standard_True);
|
||||
Handle(ShapeExtend_WireData) anExtWire = STW->WireData();
|
||||
|
||||
//:abv 04.05.00: CAX-IF TRJ4: writing complete sphere with single vertex_loop
|
||||
// check that whole wire is one seam (perhaps made of several seam edges)
|
||||
//pdn remove degenerated pcurves
|
||||
Handle(ShapeExtend_WireData) cwd = new ShapeExtend_WireData;
|
||||
Standard_Integer ie;
|
||||
for (ie = 1; ie <=nb; ie++) {
|
||||
TopoDS_Edge edge = sbwd->Edge(ie);
|
||||
if (!BRep_Tool::Degenerated(edge))
|
||||
cwd->Add(edge);
|
||||
}
|
||||
|
||||
nb = cwd->NbEdges();
|
||||
if(nb%2 == 0 ) {
|
||||
for ( ie = 1; ie < nb; ie++) {
|
||||
if ( cwd->Edge(ie).IsSame(cwd->Edge(ie+1)) ) break;
|
||||
// collect not degenerated edges
|
||||
Handle(ShapeExtend_WireData) anExtWire2 = new ShapeExtend_WireData;
|
||||
for (Standard_Integer ie = 1; ie <= anExtWire->NbEdges(); ie++)
|
||||
{
|
||||
TopoDS_Edge anEdge = anExtWire->Edge (ie);
|
||||
if (!BRep_Tool::Degenerated (anEdge))
|
||||
{
|
||||
anExtWire2->Add (anEdge);
|
||||
}
|
||||
if ( ie < nb ) {
|
||||
cwd->SetLast(ie);
|
||||
for ( ie=nb/2+1; ie <= nb; ie++ ) {
|
||||
if ( ! cwd->Edge(ie).IsSame(cwd->Edge(nb-ie+1)) ) break;
|
||||
}
|
||||
if ( ie > nb ) { // make vertex_loop
|
||||
// check for seam edges
|
||||
Standard_Integer nb = anExtWire2->NbEdges();
|
||||
if (nb % 2 == 0)
|
||||
{
|
||||
Standard_Integer ie;
|
||||
// check if two adjacent edges are the same
|
||||
for (ie = 1; ie < nb; ie++)
|
||||
{
|
||||
if (anExtWire2->Edge (ie).IsSame (anExtWire2->Edge (ie + 1)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if found seam edges
|
||||
if (ie < nb)
|
||||
{
|
||||
// make the first edge from pair last
|
||||
anExtWire2->SetLast (ie);
|
||||
for (ie = nb / 2 + 1; ie <= nb; ie++)
|
||||
{
|
||||
if (!anExtWire2->Edge (ie).IsSame (anExtWire2->Edge (nb - ie + 1)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ie > nb)
|
||||
{
|
||||
// make vertex_loop
|
||||
ShapeAnalysis_Edge sae;
|
||||
TopoDS_Vertex V = sae.FirstVertex(cwd->Edge(1));
|
||||
TopoDS_Vertex V = sae.FirstVertex (anExtWire2->Edge (1));
|
||||
TopoDSToStep_MakeStepVertex mkV (V, aTool, FP);
|
||||
Handle(StepShape_VertexLoop) vloop = new StepShape_VertexLoop;
|
||||
Handle(TCollection_HAsciiString) name = new TCollection_HAsciiString ("");
|
||||
@ -239,55 +239,35 @@ void TopoDSToStep_MakeStepWire::Init(const TopoDS_Wire& aWire,
|
||||
}
|
||||
}
|
||||
}
|
||||
nb = sbwd->NbEdges();
|
||||
|
||||
for (Standard_Integer nEdge = 1; nEdge <= sbwd->NbEdges(); nEdge++) {
|
||||
|
||||
CurrentEdge = sbwd->Edge(nEdge);
|
||||
//#11 CurrentEdge = ItW.Current();
|
||||
|
||||
//if (ItW.Current().Orientation() != ItW.Orientation())
|
||||
//std::cout << "DEBUG : Attention WireExplorer Orientation" << std::endl;
|
||||
|
||||
for (Standard_Integer nEdge = 1; nEdge <= anExtWire->NbEdges(); nEdge++)
|
||||
{
|
||||
const TopoDS_Edge anEdge = anExtWire->Edge (nEdge);
|
||||
// ---------------------------------
|
||||
// --- Is the edge Degenerated ? ---
|
||||
// ---------------------------------
|
||||
|
||||
Standard_Real cf, cl;
|
||||
Handle(Geom2d_Curve) theC2d =
|
||||
BRep_Tool::CurveOnSurface(CurrentEdge, aTool.CurrentFace(), cf, cl);
|
||||
//BRepAdaptor_Curve CA;
|
||||
//CA = BRepAdaptor_Curve(CurrentEdge,
|
||||
//aTool.CurrentFace());
|
||||
//GeomAbs_CurveType typC = CA.CurveOnSurface().GetCurve().GetType();
|
||||
//if (typC == GeomAbs_Line && BRep_Tool::Degenerated(CurrentEdge)) {
|
||||
//Handle(TransferBRep_ShapeMapper) errShape =
|
||||
//new TransferBRep_ShapeMapper(aWire);
|
||||
//FP->AddWarning(errShape, " EdgeLoop: Degenerated Pcurve not mapped");
|
||||
//}
|
||||
if ( //:abv 26Jan00, CAX-IF TRJ3: ! theC2d.IsNull() && theC2d->IsKind(STANDARD_TYPE(Geom2d_Line)) &&
|
||||
BRep_Tool::Degenerated(CurrentEdge)) {
|
||||
Handle(TransferBRep_ShapeMapper) errShape =
|
||||
new TransferBRep_ShapeMapper(aWire);
|
||||
Handle(Geom2d_Curve) theC2d = BRep_Tool::CurveOnSurface (anEdge, aTool.CurrentFace(), cf, cl);
|
||||
if (BRep_Tool::Degenerated (anEdge))
|
||||
{
|
||||
Handle(TransferBRep_ShapeMapper) errShape = new TransferBRep_ShapeMapper (aWire);
|
||||
FP->AddWarning (errShape, " EdgeLoop: Degenerated Pcurve not mapped");
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
//szv#4:S4163:12Mar99 SGI warns
|
||||
//TopoDS_Shape ssh = CurrentEdge.Oriented(TopAbs_FORWARD);
|
||||
//const TopoDS_Edge ForwardEdge = TopoDS::Edge(ssh);
|
||||
|
||||
MkEdge.Init(CurrentEdge, aTool, FP);
|
||||
if (MkEdge.IsDone()) {
|
||||
else
|
||||
{
|
||||
MkEdge.Init (anEdge, aTool, FP);
|
||||
if (MkEdge.IsDone())
|
||||
{
|
||||
OrientedEdge = new StepShape_OrientedEdge();
|
||||
Epms = Handle(StepShape_Edge)::DownCast (MkEdge.Value());
|
||||
Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString ("");
|
||||
OrientedEdge->Init(aName, Epms, (CurrentEdge.Orientation() == TopAbs_FORWARD));
|
||||
OrientedEdge->Init (aName, Epms, (anEdge.Orientation() == TopAbs_FORWARD));
|
||||
mySeq.Append (OrientedEdge);
|
||||
}
|
||||
else {
|
||||
Handle(TransferBRep_ShapeMapper) errShape =
|
||||
new TransferBRep_ShapeMapper(aWire);
|
||||
else
|
||||
{
|
||||
Handle(TransferBRep_ShapeMapper) errShape = new TransferBRep_ShapeMapper (aWire);
|
||||
FP->AddWarning (errShape, " EdgeLoop: an Edge not mapped");
|
||||
myError = TopoDSToStep_WireOther;
|
||||
done = Standard_False;
|
||||
@ -296,25 +276,25 @@ void TopoDSToStep_MakeStepWire::Init(const TopoDS_Wire& aWire,
|
||||
}
|
||||
}
|
||||
Standard_Integer nbEdges = mySeq.Length();
|
||||
if ( nbEdges >0 ) {
|
||||
Handle(StepShape_HArray1OfOrientedEdge) aList =
|
||||
new StepShape_HArray1OfOrientedEdge(1,nbEdges);
|
||||
for ( i=1; i<=nbEdges; i++ ) {
|
||||
if (nbEdges > 0)
|
||||
{
|
||||
Handle(StepShape_HArray1OfOrientedEdge) aList = new StepShape_HArray1OfOrientedEdge (1, nbEdges);
|
||||
for (Standard_Integer i = 1; i <= nbEdges; i++)
|
||||
{
|
||||
aList->SetValue (i, Handle(StepShape_OrientedEdge)::
|
||||
DownCast (mySeq.Value (i)));
|
||||
}
|
||||
Handle(StepShape_EdgeLoop) Epmsl = new StepShape_EdgeLoop;
|
||||
Handle(TCollection_HAsciiString) aName =
|
||||
new TCollection_HAsciiString("");
|
||||
Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString ("");
|
||||
Epmsl->Init (aName, aList);
|
||||
aTool.Bind (aWire, Epmsl);
|
||||
done = Standard_True;
|
||||
myResult = Epmsl;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Handle(TransferBRep_ShapeMapper) errShape =
|
||||
new TransferBRep_ShapeMapper(aWire);
|
||||
else
|
||||
{
|
||||
Handle(TransferBRep_ShapeMapper) errShape = new TransferBRep_ShapeMapper (aWire);
|
||||
FP->AddWarning (errShape, " No Edges of this Wire were mapped");
|
||||
myError = TopoDSToStep_WireOther;
|
||||
done = Standard_False;
|
||||
|
@ -13,7 +13,7 @@ checkprops result -s 1.8e+101
|
||||
|
||||
set nbshapes_expected "
|
||||
Number of shapes in shape
|
||||
VERTEX : 56881
|
||||
VERTEX : 56883
|
||||
EDGE : 85310
|
||||
WIRE : 37795
|
||||
FACE : 32992
|
||||
@ -21,7 +21,7 @@ Number of shapes in shape
|
||||
SOLID : 1308
|
||||
COMPSOLID : 0
|
||||
COMPOUND : 1
|
||||
SHAPE : 215605
|
||||
SHAPE : 215607
|
||||
"
|
||||
checknbshapes result -ref ${nbshapes_expected} -t -m "importing file"
|
||||
checkview -display result -3d -path ${imagedir}/${test_image}.png
|
111
tests/bugs/step/bug32922
Normal file
111
tests/bugs/step/bug32922
Normal file
@ -0,0 +1,111 @@
|
||||
puts "============"
|
||||
puts "OCC32922 Data Exchange, STEP - The torus is stored incorrectly in STEP format"
|
||||
puts "============"
|
||||
puts ""
|
||||
#####################################################
|
||||
# STEP testing the case when a torus is saved in STEP
|
||||
# format with an incorrect edge order
|
||||
#####################################################
|
||||
|
||||
pload MODELING XDE
|
||||
|
||||
if { [info exists imagedir] == 0 } {
|
||||
set imagedir ../bug32922
|
||||
if {![file exists ${imagedir}]} {
|
||||
file mkdir ${imagedir}
|
||||
}
|
||||
}
|
||||
|
||||
# Generating resource file where all shape healing is off
|
||||
set fdata {
|
||||
ToSTEP.exec.op : SplitCommonVertex,DirectFaces
|
||||
|
||||
FromSTEP.exec.op : FixShape
|
||||
|
||||
FromSTEP.FixShape.Tolerance3d : &Runtime.Tolerance
|
||||
FromSTEP.FixShape.MaxTolerance3d : &Runtime.MaxTolerance
|
||||
FromSTEP.FixShape.MinTolerance3d : 1.e-7
|
||||
FromSTEP.FixShape.FixFreeShellMode : 0
|
||||
FromSTEP.FixShape.FixFreeFaceMode : 0
|
||||
FromSTEP.FixShape.FixFreeWireMode : 0
|
||||
FromSTEP.FixShape.FixSameParameterMode : 0
|
||||
|
||||
FromSTEP.FixShape.FixSolidMode : 0
|
||||
FromSTEP.FixShape.FixShellOrientationMode : 0
|
||||
FromSTEP.FixShape.CreateOpenSolidMode : 0
|
||||
|
||||
FromSTEP.FixShape.FixShellMode : 0
|
||||
FromSTEP.FixShape.FixFaceOrientationMode : 0
|
||||
|
||||
FromSTEP.FixShape.FixFaceMode : 0
|
||||
FromSTEP.FixShape.FixWireMode : 0
|
||||
FromSTEP.FixShape.FixOrientationMode : 0
|
||||
FromSTEP.FixShape.FixAddNaturalBoundMode : 0
|
||||
FromSTEP.FixShape.FixMissingSeamMode : 0
|
||||
FromSTEP.FixShape.FixSmallAreaWireMode : 0
|
||||
FromSTEP.FixShape.RemoveSmallAreaFaceMode : 0
|
||||
FromSTEP.FixShape.FixIntersectingWiresMode : 0
|
||||
FromSTEP.FixShape.FixLoopWiresMode : 0
|
||||
FromSTEP.FixShape.FixSplitFaceMode : 0
|
||||
FromSTEP.FixShape.AutoCorrectPrecisionMode : 0
|
||||
FromSTEP.FixShape.ModifyTopologyMode : 0
|
||||
FromSTEP.FixShape.ModifyGeometryMode : 0
|
||||
FromSTEP.FixShape.ClosedWireMode : 0
|
||||
FromSTEP.FixShape.PreferencePCurveMode : 0
|
||||
FromSTEP.FixShape.FixReorderMode : 0
|
||||
FromSTEP.FixShape.FixSmallMode : 0
|
||||
FromSTEP.FixShape.FixConnectedMode : 0
|
||||
FromSTEP.FixShape.FixEdgeCurvesMode : 0
|
||||
FromSTEP.FixShape.FixDegeneratedMode : 0
|
||||
FromSTEP.FixShape.FixLackingMode : 0
|
||||
FromSTEP.FixShape.FixSelfIntersectionMode : 0
|
||||
FromSTEP.FixShape.RemoveLoopMode : 0
|
||||
FromSTEP.FixShape.FixReversed2dMode : 0
|
||||
FromSTEP.FixShape.FixRemovePCurveMode : 0
|
||||
FromSTEP.FixShape.FixRemoveCurve3dMode : 0
|
||||
FromSTEP.FixShape.FixAddPCurveMode : 0
|
||||
FromSTEP.FixShape.FixAddCurve3dMode : 0
|
||||
FromSTEP.FixShape.FixSeamMode : 0
|
||||
FromSTEP.FixShape.FixShiftedMode : 0
|
||||
FromSTEP.FixShape.FixEdgeSameParameterMode : 0
|
||||
FromSTEP.FixShape.FixNotchedEdgesMode : 0
|
||||
FromSTEP.FixShape.FixTailMode : 0
|
||||
FromSTEP.FixShape.MaxTailAngle : 0
|
||||
FromSTEP.FixShape.MaxTailWidth : 0
|
||||
FromSTEP.FixShape.FixSelfIntersectingEdgeMode : 0
|
||||
FromSTEP.FixShape.FixIntersectingEdgesMode : 0
|
||||
FromSTEP.FixShape.FixNonAdjacentIntersectingEdgesMode : 0
|
||||
|
||||
FromSTEP.FixShape.FixVertexPositionMode : 0
|
||||
FromSTEP.FixShape.FixVertexToleranceMode : 0
|
||||
}
|
||||
|
||||
set new_resource_path ${imagedir}
|
||||
set resource_file STEP
|
||||
set fo [open "${new_resource_path}/${resource_file}" "wb"]
|
||||
puts -nonewline $fo $fdata
|
||||
close $fo
|
||||
|
||||
# Changing the path to the resource file
|
||||
set old_resource_path $::env(CSF_STEPDefaults)
|
||||
set env(CSF_STEPDefaults) ${new_resource_path}
|
||||
|
||||
# Generating, writing and reading the torus
|
||||
ptorus tor 20 5
|
||||
set step_file ${imagedir}/torus.stp
|
||||
testwritestep ${step_file} tor
|
||||
stepread ${step_file} a *
|
||||
|
||||
# Cheking the face of the torus
|
||||
explode a_1 f
|
||||
renamevar a_1_1 result
|
||||
checkshape result
|
||||
|
||||
# Making screenshort
|
||||
pcurve result
|
||||
view 1 -2D- 728 20 400 400
|
||||
2dfit
|
||||
checkview -screenshot -2d -path ${imagedir}/${test_image}.png
|
||||
|
||||
# Restoring the path to the old resource file
|
||||
set env(CSF_STEPDefaults) ${old_resource_path}
|
Loading…
x
Reference in New Issue
Block a user