diff --git a/src/ShapeFix/ShapeFix_ComposeShell.cxx b/src/ShapeFix/ShapeFix_ComposeShell.cxx index 348736c99b..cac53faca1 100644 --- a/src/ShapeFix/ShapeFix_ComposeShell.cxx +++ b/src/ShapeFix/ShapeFix_ComposeShell.cxx @@ -425,6 +425,7 @@ static inline Standard_Integer IsCoincided (const gp_Pnt2d &p1, const gp_Pnt2d & //function : GetPatchIndex //purpose : auxilary //======================================================================= + // computes index for the patch by given parameter Param static Standard_Integer GetPatchIndex (const Standard_Real Param, const Handle(TColStd_HArray1OfReal) &Params, @@ -450,7 +451,6 @@ static Standard_Integer GetPatchIndex (const Standard_Real Param, return i - ishift * ( NP - 1 ); } - //======================================================================= //function : LoadWires //purpose : @@ -781,19 +781,6 @@ static void DefinePatch (ShapeFix_WireSegment &wire, const Standard_Integer code } } - -//======================================================================= -//function : DefinePatchForWire -//purpose : auxilary -//======================================================================= -static void DefinePatchForWire(ShapeFix_WireSegment &wire, const Standard_Integer code, - const Standard_Boolean isCutByU, const Standard_Integer cutIndex) -{ - for(Standard_Integer i = 1; i <= wire.NbEdges(); i++) - DefinePatch(wire,code,isCutByU,cutIndex,i); -} - - //======================================================================= //function : GetGridResolution //purpose : auxilary @@ -1427,7 +1414,7 @@ Standard_Boolean ShapeFix_ComposeShell::SplitByLine (ShapeFix_WireSegment &wire, if ( IntEdgePar.Length() <1 ) { //pdn Defining position of wire. There is no intersection, so by any point. - DefinePatchForWire ( wire, firstCode, isCutByU, cutIndex ); + //DefinePatchForWire ( wire, firstCode, isCutByU, cutIndex ); return Standard_False; //pdn ?? } @@ -1467,19 +1454,23 @@ Standard_Boolean ShapeFix_ComposeShell::SplitByLine (ShapeFix_WireSegment &wire, j=i++; } } - + //sequence of real codes for each segment + TColStd_SequenceOfInteger aNewSegCodes; // Compute segment codes (left side of line, right or tangential) for ( i=1; i <= IntEdgePar.Length(); i++ ) { j = ( i < IntEdgePar.Length() ? i + 1 : 1 ); Standard_Integer code = ComputeCode ( sewd, line, IntEdgeInd(i), IntEdgeInd(j), - IntEdgePar(i), IntEdgePar(j),isnonmanifold ); + IntEdgePar(i), IntEdgePar(j),isnonmanifold ); SegmentCodes.Append ( code ); } - + // for EXTERNAL wire, i.e. another joint line, every point is double intersection if ( wire.Orientation() == TopAbs_EXTERNAL ) { for ( i=1; i <= IntEdgePar.Length(); i++ ) + { IntCode.Append ( ITP_TANG | IOR_BOTH ); + aNewSegCodes.Append(SegmentCodes(i)); + } } // For real (closed) wire, analyze tangencies else { @@ -1508,7 +1499,6 @@ Standard_Boolean ShapeFix_ComposeShell::SplitByLine (ShapeFix_WireSegment &wire, } //pdn exit if all split points removed if ( IntEdgePar.Length() <1 ) { - //DefinePatchForWire ( wire, firstCode, isCutByU, cutIndex ); return Standard_False; //pdn ?? } @@ -1517,15 +1507,22 @@ Standard_Boolean ShapeFix_ComposeShell::SplitByLine (ShapeFix_WireSegment &wire, // beginning and end of tangential segment. // Orientation (IOR) tells on which side of line edge crosses it j = IntEdgePar.Length(); + for ( i=1; i <= IntEdgePar.Length(); j = i++ ) { Standard_Integer codej = SegmentCodes(j); Standard_Integer codei = SegmentCodes(i); if ( myClosedMode ) { - if ( ( codej & IOR_BOTH ) == IOR_BOTH ) //IOR_LEFT : IOR_RIGHT - codej = ( codej & IOR_POS ? IOR_RIGHT : IOR_LEFT ); - if ( ( codei & IOR_BOTH ) == IOR_BOTH ) //IOR_RIGHT : IOR_LEFT - codei = ( codei & IOR_POS ? IOR_LEFT : IOR_RIGHT ); + if ( ( codej & IOR_BOTH ) == IOR_BOTH ) //IOR_LEFT : IOR_RIGHT + codej = ( codej & IOR_POS ? IOR_RIGHT : IOR_LEFT ); + if ( ( codei & IOR_BOTH ) == IOR_BOTH ) //IOR_RIGHT : IOR_LEFT + codei = ( codei & IOR_POS ? IOR_LEFT : IOR_RIGHT ); + aNewSegCodes.Append ( codei ); + if(IntEdgeInd(i) == IntEdgeInd(j)) + aNewSegCodes.Append ( codej ); + } + else + aNewSegCodes.Append ( codei ); Standard_Integer ipcode = ( codej | codei ); if ( codej == IOR_UNDEF ) { // previous segment was tangency if ( IntLinePar(i) > IntLinePar (j) ) @@ -1546,10 +1543,12 @@ Standard_Boolean ShapeFix_ComposeShell::SplitByLine (ShapeFix_WireSegment &wire, } //======================================= + + // Split edges in the wire by intersection points and fill vertices array TopTools_SequenceOfShape IntVertices; wire = SplitWire ( wire, IntEdgeInd, IntEdgePar, IntVertices, - SegmentCodes, isCutByU, cutIndex ); + aNewSegCodes, isCutByU, cutIndex ); // add all data to input arrays for ( i=1; i <= IntLinePar.Length(); i++ ) { @@ -1683,15 +1682,20 @@ void ShapeFix_ComposeShell::SplitByLine (ShapeFix_SequenceOfWireSegment &wires, // set patch indices DefinePatch ( seg, IOR_UNDEF, isCutByU, cutIndex ); if ( ! isCutByU ) { - seg.DefineIUMin ( 1, GetPatchIndex ( SplitLinePar(i-1)+::Precision::PConfusion(), - myGrid->UJointValues(), myUClosed ) ); - seg.DefineIUMax ( 1, GetPatchIndex ( SplitLinePar(i)-::Precision::PConfusion(), + Standard_Real shiftU = + (myClosedMode && myUClosed ? ShapeAnalysis::AdjustToPeriod(SplitLinePar(i-1) -TOLINT, myGrid->UJointValue(1), myGrid->UJointValue(2)) : 0.); + Standard_Real aPar = SplitLinePar(i-1) + shiftU; + + seg.DefineIUMin ( 1, GetPatchIndex ( aPar+::Precision::PConfusion(), myGrid->UJointValues(), myUClosed ) ); + seg.DefineIUMax ( 1, GetPatchIndex ( aPar-::Precision::PConfusion(), myGrid->UJointValues(), myUClosed ) + 1 ); } else { - seg.DefineIVMin ( 1, GetPatchIndex ( SplitLinePar(i-1)+::Precision::PConfusion(), + Standard_Real shiftV = (myClosedMode && myVClosed ? ShapeAnalysis::AdjustToPeriod(SplitLinePar(i-1) -TOLINT, myGrid->VJointValue(1), myGrid->VJointValue(2)) : 0.); + Standard_Real aPar = SplitLinePar(i-1) + shiftV; + seg.DefineIVMin ( 1, GetPatchIndex ( aPar+::Precision::PConfusion(), myGrid->VJointValues(), myVClosed ) ); - seg.DefineIVMax ( 1, GetPatchIndex ( SplitLinePar(i)-::Precision::PConfusion(), + seg.DefineIVMax ( 1, GetPatchIndex ( aPar-::Precision::PConfusion(), myGrid->VJointValues(), myVClosed ) + 1 ); } @@ -1725,10 +1729,79 @@ void ShapeFix_ComposeShell::SplitByGrid (ShapeFix_SequenceOfWireSegment &seqw) BRepTools::UVBounds(myFace,Uf,Ul,Vf,Vl); Standard_Real Umin,Umax,Vmin,Vmax; myGrid->Bounds(Umin,Umax,Vmin,Vmax); - Standard_Real pprec = ::Precision::PConfusion(); - + + //value of precision to define number of patch should be the same as used in the definitin position of point realtively to seam edge (TOLINT) + Standard_Real pprec = TOLINT;//::Precision::PConfusion(); + Standard_Integer i = 1; + if(myClosedMode) + { + //for closed mode when only one patch exist and location of the splitting line is coinsident with first joint value + //Therefore in this case it is necessary to move all wire segments in the range of the patch between first and last joint + //values. Then all wire segments are lie between -period and period in order to have valid split ranges after splitting. + //Because for closed mode cut index always equal to 1 and parts of segments after splitting always should have index either (0,1) or (1,2). + + for ( i=1; i <= seqw.Length(); i++ ) + { + ShapeFix_WireSegment &wire = seqw(i); + + TopoDS_Shape atmpF = myFace.EmptyCopied(); + BRep_Builder aB; + atmpF.Orientation(TopAbs_FORWARD); + aB.Add(atmpF, wire.WireData()->Wire()); + Standard_Real Uf1,Ul1,Vf1,Vl1; + ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(atmpF),Uf1,Ul1,Vf1,Vl1); + + //for closed mode it is necessary to move wire segment in the interval defined by first and last grid UV values + Standard_Real shiftU = (myClosedMode && myUClosed ? ShapeAnalysis::AdjustToPeriod(Ul1 -pprec, myGrid->UJointValue(1), myGrid->UJointValue(2)) : 0.); + Standard_Real shiftV = (myClosedMode && myVClosed ? ShapeAnalysis::AdjustToPeriod(Vl1 -pprec, myGrid->VJointValue(1), myGrid->VJointValue(2)) : 0.); + Uf1 += shiftU; + Ul1 += shiftU; + Vf1 += shiftV; + Vl1 += shiftV; + // limit patch indices to be in range of grid (extended for periodic) (0, 2) + //in same cases for example trj4_pm2-ug-203.stp (entity #8024) wire in 2D space has length greater then period + Standard_Integer iumin = Max(0,GetPatchIndex ( Uf1+pprec, myGrid->UJointValues(), myUClosed )); + Standard_Integer iumax = GetPatchIndex ( Ul1-pprec, myGrid->UJointValues(), myUClosed ) + 1; + + + for ( Standard_Integer j=1; j <= wire.NbEdges(); j++ ) { + wire.DefineIUMin ( j, iumin ); + wire.DefineIUMax ( j, iumax ); + } + + Standard_Integer ivmin = Max(0,GetPatchIndex ( Vf1+pprec, myGrid->VJointValues(), myVClosed )); + Standard_Integer ivmax = GetPatchIndex ( Vl1-pprec, myGrid->VJointValues(), myVClosed ) + 1; + + for ( Standard_Integer j=1; j <= wire.NbEdges(); j++ ) { + wire.DefineIVMin ( j, ivmin ); + wire.DefineIVMax ( j, ivmax ); + } + } + } + else + { + // limit patch indices to be in range of grid (extended for periodic) + Standard_Integer iumin = GetPatchIndex ( Uf+pprec, myGrid->UJointValues(), myUClosed ); + Standard_Integer iumax = GetPatchIndex ( Ul-pprec, myGrid->UJointValues(), myUClosed ) + 1; + for ( i=1; i <= seqw.Length(); i++ ) { + ShapeFix_WireSegment &wire = seqw(i); + for ( Standard_Integer j=1; j <= wire.NbEdges(); j++ ) { + wire.DefineIUMin ( j, iumin ); + wire.DefineIUMax ( j, iumax ); + } + } + Standard_Integer ivmin = GetPatchIndex ( Vf+pprec, myGrid->VJointValues(), myVClosed ); + Standard_Integer ivmax = GetPatchIndex ( Vl-pprec, myGrid->VJointValues(), myVClosed ) + 1; + for ( i=1; i <= seqw.Length(); i++ ) { + ShapeFix_WireSegment &wire = seqw(i); + for ( Standard_Integer j=1; j <= wire.NbEdges(); j++ ) { + wire.DefineIVMin ( j, ivmin ); + wire.DefineIVMax ( j, ivmax ); + } + } + } // split by u lines - Standard_Integer i; // svv #1 + for ( i = ( myUClosed ? 1 : 2 ); i <= myGrid->NbUPatches(); i++ ) { gp_Pnt2d pos ( myGrid->UJointValue(i), 0. ); // 0. - for infinite ranges: myGrid->VJointValue(1) ; gp_Lin2d line ( pos, gp_Dir2d ( 0., 1. ) ); @@ -1737,15 +1810,15 @@ void ShapeFix_ComposeShell::SplitByGrid (ShapeFix_SequenceOfWireSegment &seqw) Standard_Real X = pos.X(); Standard_Real sh = ShapeAnalysis::AdjustToPeriod(X,Uf, Uf+period); for( ; X+sh <= Ul+pprec; sh += period ) { - gp_Lin2d ln = line.Translated(gp_Vec2d(sh,0)); - Standard_Integer cutIndex = GetPatchIndex ( X+sh+pprec, myGrid->UJointValues(), myUClosed ); - SplitByLine ( seqw, ln, Standard_True, cutIndex ); + gp_Lin2d ln = line.Translated(gp_Vec2d(sh,0)); + Standard_Integer cutIndex = GetPatchIndex ( X+sh+pprec, myGrid->UJointValues(), myUClosed ); + SplitByLine ( seqw, ln, Standard_True, cutIndex ); } } else SplitByLine ( seqw, line, Standard_True, i ); } - + // split by v lines for ( i = ( myVClosed ? 1 : 2 ); i <= myGrid->NbVPatches(); i++ ) { gp_Pnt2d pos ( 0., myGrid->VJointValue(i) ); @@ -1755,34 +1828,15 @@ void ShapeFix_ComposeShell::SplitByGrid (ShapeFix_SequenceOfWireSegment &seqw) Standard_Real Y = pos.Y(); Standard_Real sh = ShapeAnalysis::AdjustToPeriod(Y,Vf, Vf+period); for( ; Y+sh <= Vl+pprec; sh += period) { - gp_Lin2d ln = line.Translated(gp_Vec2d(0,sh)); - Standard_Integer cutIndex = GetPatchIndex ( Y+sh+pprec, myGrid->VJointValues(), myVClosed ); - SplitByLine ( seqw, ln, Standard_False, cutIndex ); + gp_Lin2d ln = line.Translated(gp_Vec2d(0,sh)); + Standard_Integer cutIndex = GetPatchIndex ( Y+sh+pprec, myGrid->VJointValues(), myVClosed ); + SplitByLine ( seqw, ln, Standard_False, cutIndex ); } } else SplitByLine ( seqw, line, Standard_False, i ); } - // limit patch indices to be in range of grid (extended for periodic) - Standard_Integer iumin = GetPatchIndex ( Uf+pprec, myGrid->UJointValues(), myUClosed ); - Standard_Integer iumax = GetPatchIndex ( Ul-pprec, myGrid->UJointValues(), myUClosed ) + 1; - for ( i=1; i <= seqw.Length(); i++ ) { - ShapeFix_WireSegment &wire = seqw(i); - for ( Standard_Integer j=1; j <= wire.NbEdges(); j++ ) { - wire.DefineIUMin ( j, iumin ); - wire.DefineIUMax ( j, iumax ); - } - } - Standard_Integer ivmin = GetPatchIndex ( Vf+pprec, myGrid->VJointValues(), myVClosed ); - Standard_Integer ivmax = GetPatchIndex ( Vl-pprec, myGrid->VJointValues(), myVClosed ) + 1; - for ( i=1; i <= seqw.Length(); i++ ) { - ShapeFix_WireSegment &wire = seqw(i); - for ( Standard_Integer j=1; j <= wire.NbEdges(); j++ ) { - wire.DefineIVMin ( j, ivmin ); - wire.DefineIVMax ( j, ivmax ); - } - } } @@ -2037,15 +2091,15 @@ void ShapeFix_ComposeShell::CollectWires (ShapeFix_SequenceOfWireSegment &wires, if ( anOr == TopAbs_FORWARD ) reverse = Standard_True; index = i; seg.GetPatchIndex ( 1, iumin, iumax, ivmin, ivmax ); + misoriented = Standard_False; dsu = dsv = 0.; break; } // check whether current segment is on the same patch with previous - Standard_Integer sp = ( myClosedMode || // no indexation in closed mode - IsSamePatch ( seg, myGrid->NbUPatches(), myGrid->NbVPatches(), - iumin, iumax, ivmin, ivmax ) ); + Standard_Integer sp = IsSamePatch ( seg, myGrid->NbUPatches(), myGrid->NbVPatches(), + iumin, iumax, ivmin, ivmax ); // not same patch has lowest priority if ( ! sp && ( canBeClosed || ( index && samepatch ) ) ) continue; @@ -2151,7 +2205,13 @@ void ShapeFix_ComposeShell::CollectWires (ShapeFix_SequenceOfWireSegment &wires, else if ( samepatch ) { // extend patch indices IsSamePatch ( seg, myGrid->NbUPatches(), myGrid->NbVPatches(), iumin, iumax, ivmin, ivmax, Standard_True ); - } + } + + //for closed mode in case if current segment is seam segment it is necessary to detect crossing seam edge + //in order to have possibility to take candidate from other patch + if(myClosedMode ) + seg.GetPatchIndex ( 1, iumin, iumax, ivmin, ivmax ); + // TopAbs_Orientation or = seg.Orientation(); if ( ! reverse ) sbwd->Add ( seg.WireData() ); else { diff --git a/tests/bugs/heal/bug26708 b/tests/bugs/heal/bug26708 new file mode 100644 index 0000000000..647bb201f6 --- /dev/null +++ b/tests/bugs/heal/bug26708 @@ -0,0 +1,11 @@ +puts "========================" +puts "Bug #26708" +puts "========================" + +brestore [locate_data_file bug26708_a_205.brep] face + +fixshape result face 1e-7 1 +checkshape result +checknbshapes result -face 1 + +set 2dviewer 1 diff --git a/tests/de/step_3/D8 b/tests/de/step_3/D8 index ae83511d29..9c85e72e41 100755 --- a/tests/de/step_3/D8 +++ b/tests/de/step_3/D8 @@ -1,5 +1,5 @@ # !!!! This file is generated automatically, do not edit manually! See end script -puts "TODO CR25013 Linux: Error : 1 differences with reference data found" +puts "TODO OCC26973 Windows: Error : 1 differences with reference data found" set filename trj6_pm4-hc-214.stp @@ -7,9 +7,9 @@ set ref_data { DATA : Faulties = 0 ( 20 ) Warnings = 0 ( 60 ) Summary = 0 ( 80 ) TPSTAT : Faulties = 0 ( 0 ) Warnings = 21 ( 557 ) Summary = 21 ( 557 ) CHECKSHAPE : Wires = 0 ( 0 ) Faces = 0 ( 0 ) Shells = 0 ( 0 ) Solids = 0 ( 0 ) -NBSHAPES : Solid = 98 ( 98 ) Shell = 98 ( 98 ) Face = 1506 ( 1506 ) Summary = 9262 ( 9257 ) +NBSHAPES : Solid = 98 ( 98 ) Shell = 98 ( 98 ) Face = 1506 ( 1506 ) Summary = 9261 ( 9257 ) STATSHAPE : Solid = 272 ( 272 ) Shell = 272 ( 272 ) Face = 3216 ( 3216 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 3315 ( 3311 ) -TOLERANCE : MaxTol = 0.9562231856 ( 3.3196868 ) AvgTol = 0.0007127405962 ( 0.003722159881 ) +TOLERANCE : MaxTol = 0.9562231856 ( 3.3196868 ) AvgTol = 0.0007127401639 ( 0.003722159846 ) LABELS : N0Labels = 230 ( 230 ) N1Labels = 1909 ( 1909 ) N2Labels = 0 ( 0 ) TotalLabels = 2139 ( 2139 ) NameLabels = 633 ( 633 ) ColorLabels = 1506 ( 1506 ) LayerLabels = 0 ( 0 ) PROPS : Centroid = 98 ( 98 ) Volume = 98 ( 98 ) Area = 98 ( 98 ) NCOLORS : NColors = 6 ( 6 ) diff --git a/tests/de/step_4/H1 b/tests/de/step_4/H1 index cf5bc49f62..4820f80dc9 100644 --- a/tests/de/step_4/H1 +++ b/tests/de/step_4/H1 @@ -1,16 +1,13 @@ # !!!! This file is generated automatically, do not edit manually! See end script -puts "TODO CR23096 ALL: CHECKSHAPE : Faulty" - - set filename Inventor_Engine.stp set ref_data { DATA : Faulties = 0 ( 0 ) Warnings = 0 ( 0 ) Summary = 0 ( 0 ) -TPSTAT : Faulties = 0 ( 0 ) Warnings = 448 ( 560 ) Summary = 448 ( 560 ) -CHECKSHAPE : Wires = 9 ( 6 ) Faces = 9 ( 6 ) Shells = 0 ( 0 ) Solids = 0 ( 0 ) -NBSHAPES : Solid = 47 ( 47 ) Shell = 47 ( 47 ) Face = 4455 ( 4455 ) Summary = 27804 ( 27803 ) -STATSHAPE : Solid = 80 ( 80 ) Shell = 80 ( 80 ) Face = 5359 ( 5359 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 11467 ( 11467 ) -TOLERANCE : MaxTol = 2.429208989 ( 2.450580634 ) AvgTol = 0.003235414897 ( 0.002917423634 ) +TPSTAT : Faulties = 0 ( 0 ) Warnings = 456 ( 560 ) Summary = 456 ( 560 ) +CHECKSHAPE : Wires = 6 ( 6 ) Faces = 6 ( 6 ) Shells = 0 ( 0 ) Solids = 0 ( 0 ) +NBSHAPES : Solid = 47 ( 47 ) Shell = 47 ( 47 ) Face = 4454 ( 4454 ) Summary = 27812 ( 27811 ) +STATSHAPE : Solid = 80 ( 80 ) Shell = 80 ( 80 ) Face = 5356 ( 5356 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 11472 ( 11473 ) +TOLERANCE : MaxTol = 2.37122237 ( 2.449305641 ) AvgTol = 0.002570900495 ( 0.002589625201 ) LABELS : N0Labels = 52 ( 52 ) N1Labels = 86 ( 86 ) N2Labels = 0 ( 0 ) TotalLabels = 138 ( 138 ) NameLabels = 136 ( 136 ) ColorLabels = 47 ( 47 ) LayerLabels = 0 ( 0 ) PROPS : Centroid = 0 ( 0 ) Volume = 0 ( 0 ) Area = 0 ( 0 ) NCOLORS : NColors = 11 ( 11 ) diff --git a/tests/de/step_5/A1 b/tests/de/step_5/A1 index ede0d5f80f..0baab19806 100755 --- a/tests/de/step_5/A1 +++ b/tests/de/step_5/A1 @@ -1,15 +1,13 @@ # !!!! This file is generated automatically, do not edit manually! See end script - - set filename Z8INV5.stp set ref_data { DATA : Faulties = 0 ( 0 ) Warnings = 0 ( 0 ) Summary = 0 ( 0 ) -TPSTAT : Faulties = 0 ( 0 ) Warnings = 114 ( 619 ) Summary = 114 ( 619 ) -CHECKSHAPE : Wires = 17 ( 17 ) Faces = 18 ( 20 ) Shells = 1 ( 1 ) Solids = 0 ( 0 ) -NBSHAPES : Solid = 22 ( 22 ) Shell = 24 ( 24 ) Face = 1520 ( 1520 ) Summary = 11210 ( 11195 ) -STATSHAPE : Solid = 22 ( 22 ) Shell = 24 ( 24 ) Face = 1520 ( 1520 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 4784 ( 4774 ) -TOLERANCE : MaxTol = 7.33063502 ( 7.159520237 ) AvgTol = 0.03499829069 ( 0.03222638333 ) +TPSTAT : Faulties = 0 ( 0 ) Warnings = 122 ( 622 ) Summary = 122 ( 622 ) +CHECKSHAPE : Wires = 19 ( 19 ) Faces = 19 ( 21 ) Shells = 1 ( 1 ) Solids = 0 ( 0 ) +NBSHAPES : Solid = 22 ( 22 ) Shell = 24 ( 24 ) Face = 1520 ( 1520 ) Summary = 11231 ( 11206 ) +STATSHAPE : Solid = 22 ( 22 ) Shell = 24 ( 24 ) Face = 1520 ( 1520 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 4797 ( 4781 ) +TOLERANCE : MaxTol = 7.159520237 ( 15.55113015 ) AvgTol = 0.03830637421 ( 0.03863233285 ) LABELS : N0Labels = 25 ( 25 ) N1Labels = 23 ( 23 ) N2Labels = 0 ( 0 ) TotalLabels = 48 ( 48 ) NameLabels = 48 ( 48 ) ColorLabels = 0 ( 0 ) LayerLabels = 0 ( 0 ) PROPS : Centroid = 0 ( 0 ) Volume = 0 ( 0 ) Area = 0 ( 0 ) NCOLORS : NColors = 0 ( 0 )