1 // Created on: 2000-01-21
2 // Created by: data exchange team
3 // Copyright (c) 2000-2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
22 #include <ShapeFix.hxx>
23 //:k2 abv 16.12.98: eliminating code duplication
24 //pdn 18.12.98: checking deviation for SP edges
25 //: abv 22.02.99: method FillFace() removed since PRO13123 is fixed
27 //szv#9:S4244:19Aug99: Added method FixWireGaps
28 //szv#10:S4244:23Aug99: Added method FixFaceGaps
30 #include <BRep_Builder.hxx>
31 #include <BRep_Tool.hxx>
33 #include <Geom2d_Curve.hxx>
34 #include <Geom_Curve.hxx>
36 #include <Precision.hxx>
38 #include <Standard_ErrorHandler.hxx>
39 #include <Standard_Failure.hxx>
41 #include <TopExp_Explorer.hxx>
42 #include <TopLoc_Location.hxx>
44 #include <TopoDS_Edge.hxx>
45 #include <TopoDS_Face.hxx>
46 #include <Geom_Surface.hxx>
50 #include <Geom_Plane.hxx>
51 #include <ShapeFix_Edge.hxx>
52 #include <Geom2dAdaptor_HCurve.hxx>
53 #include <Adaptor3d_CurveOnSurface.hxx>
54 #include <Geom_RectangularTrimmedSurface.hxx>
55 #include <ShapeAnalysis_Surface.hxx>
57 #include <ShapeFix_Edge.hxx>
58 #include <ShapeFix_Shape.hxx>
59 #include <ShapeFix_Wire.hxx>
60 #include <ShapeFix_Face.hxx>
61 #include <TopoDS_Iterator.hxx>
62 #include <GeomAdaptor_HSurface.hxx>
63 #include <TopTools_MapOfShape.hxx>
64 #include <BRepLib.hxx>
66 #include <ShapeAnalysis_Edge.hxx>
67 #include <ShapeBuild_Edge.hxx>
68 #include <TopoDS_Vertex.hxx>
69 #include <ShapeBuild_ReShape.hxx>
70 #include <TColgp_SequenceOfPnt.hxx>
71 #include <TopTools_ListOfShape.hxx>
72 #include <TopTools_ListIteratorOfListOfShape.hxx>
73 #include <TopTools_SequenceOfShape.hxx>
74 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
77 #include <Message_ProgressSentry.hxx>
79 //=======================================================================
80 //function : SameParameter
82 //=======================================================================
84 Standard_Boolean ShapeFix::SameParameter(const TopoDS_Shape& shape,
85 const Standard_Boolean enforce,
86 const Standard_Real preci,
87 const Handle(Message_ProgressIndicator)& theProgress)
89 // Calculate number of edges
90 Standard_Integer aNbEdges = 0;
91 for ( TopExp_Explorer anEdgeExp(shape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next() )
94 // Calculate number of faces
95 Standard_Integer aNbFaces = 0;
96 for ( TopExp_Explorer anEdgeExp(shape, TopAbs_FACE); anEdgeExp.More(); anEdgeExp.Next() )
100 //Standard_Integer nbexcp = 0;
101 Standard_Integer nbfail = 0, numedge = 0;
102 Standard_Boolean status = Standard_True;
103 Standard_Real tol = preci;
104 Standard_Boolean iatol = (tol > 0);
105 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
106 TopExp_Explorer ex(shape,TopAbs_EDGE);
108 // Start progress scope (no need to check if progress exists -- it is safe)
109 Message_ProgressSentry aPSentry(theProgress, "Fixing same parameter problem", 0, 2, 1);
112 // Start progress scope (no need to check if progress exists -- it is safe)
113 Message_ProgressSentry aPSentry(theProgress, "Fixing edge", 0, aNbEdges, 1);
118 while ( ex.More() && aPSentry.More() )
123 E = TopoDS::Edge (ex.Current());
127 tol = BRep_Tool::Tolerance (E);
130 B.SameRange (E,Standard_False);
131 B.SameParameter (E,Standard_False);
134 sfe->FixSameParameter (E); // K2-SEP97
136 if (!BRep_Tool::SameParameter (E)) { ierr = 1; nbfail ++; }
140 status = Standard_False;
141 B.SameRange (E,Standard_False);
142 B.SameParameter (E,Standard_False);
145 // Complete step in current progress scope
149 // Halt algorithm in case of user's abort
150 if ( !aPSentry.More() )
151 return Standard_False;
155 // Switch to "Update tolerances" step
159 // Start progress scope (no need to check if progress exists -- it is safe)
160 Message_ProgressSentry aPSentry(theProgress, "Update tolerances", 0, aNbFaces, 1);
162 //:i2 abv 21 Aug 98: ProSTEP TR8 Motor.rle face 710:
163 // Update tolerance of edges on planes (no pcurves are stored)
164 for ( TopExp_Explorer exp ( shape, TopAbs_FACE ); exp.More() && aPSentry.More(); exp.Next(), aPSentry.Next() )
166 TopoDS_Face face = TopoDS::Face ( exp.Current() );
167 Handle(Geom_Surface) Surf = BRep_Tool::Surface ( face );
169 Handle(Geom_Plane) plane = Handle(Geom_Plane)::DownCast ( Surf );
170 if ( plane.IsNull() ) {
171 Handle(Geom_RectangularTrimmedSurface) GRTS =
172 Handle(Geom_RectangularTrimmedSurface)::DownCast ( Surf );
173 if ( ! GRTS.IsNull() )
174 plane = Handle(Geom_Plane)::DownCast ( GRTS->BasisSurface() );
175 if ( plane.IsNull() )
179 Handle(GeomAdaptor_HSurface) AS = new GeomAdaptor_HSurface ( plane );
180 for ( TopExp_Explorer ed ( face, TopAbs_EDGE ); ed.More(); ed.Next() ) {
181 TopoDS_Edge edge = TopoDS::Edge ( ed.Current() );
183 Handle(Geom_Curve) crv = BRep_Tool::Curve ( edge, f, l );
187 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface ( edge, face, f, l );;
188 if ( c2d.IsNull() ) continue;
189 Handle(Geom2dAdaptor_HCurve) GHPC = new Geom2dAdaptor_HCurve ( c2d, f, l );
190 Adaptor3d_CurveOnSurface ACS(GHPC,AS);
192 Standard_Real tol0 = BRep_Tool::Tolerance(edge);
194 Standard_Real tol2 = tol*tol;
195 const Standard_Integer NCONTROL = 23;
196 for ( Standard_Integer i = 0; i < NCONTROL; i++ )
198 Standard_Real par = ( f * ( NCONTROL - 1 - i ) + l * i ) / ( NCONTROL - 1 );
199 gp_Pnt pnt = crv->Value ( par );
200 gp_Pnt prj = ACS.Value( par );
201 Standard_Real dist = pnt.SquareDistance(prj);
205 tol = 1.00005 * sqrt(tol2); // coeff: see trj3_pm1-ct-203.stp #19681, edge 10
208 B.UpdateEdge ( edge, tol );
209 for ( TopoDS_Iterator itV(edge); itV.More(); itV.Next() )
211 TopoDS_Shape S = itV.Value();
212 B.UpdateVertex ( TopoDS::Vertex ( S ), tol );
217 // Halt algorithm in case of user's abort
218 if ( !aPSentry.More() )
219 return Standard_False;
225 cout<<"** SameParameter not complete. On "<<numedge<<" Edges:";
226 if (nbfail > 0) cout<<" "<<nbfail<<" Failed";
234 //=======================================================================
235 //function : EncodeRegularity
237 //=======================================================================
239 static void EncodeRegularity (const TopoDS_Shape& shape,
240 const Standard_Real tolang,
241 TopTools_MapOfShape &aMap)
243 TopoDS_Shape S = shape;
246 if ( ! aMap.Add ( S ) ) return;
248 if ( S.ShapeType() == TopAbs_COMPOUND ||
249 S.ShapeType() == TopAbs_COMPSOLID ) {
250 for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
251 EncodeRegularity ( it.Value(), tolang, aMap );
258 BRepLib::EncodeRegularity ( S, tolang );
260 catch(Standard_Failure) {
262 cout << "Warning: Exception in ShapeFix::EncodeRegularity(): ";
263 Standard_Failure::Caught()->Print ( cout );
269 void ShapeFix::EncodeRegularity (const TopoDS_Shape& shape,
270 const Standard_Real tolang)
272 TopTools_MapOfShape aMap;
273 ::EncodeRegularity ( shape, tolang, aMap );
277 //=======================================================================
278 //function : RemoveSmallEdges
280 //=======================================================================
282 TopoDS_Shape ShapeFix::RemoveSmallEdges (TopoDS_Shape& Shape,
283 const Standard_Real Tolerance,
284 Handle(ShapeBuild_ReShape)& context)
286 Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
288 sfs->SetPrecision(Tolerance);
289 Handle(ShapeFix_Face)::DownCast(sfs->FixFaceTool())->FixMissingSeamMode() = Standard_False;
290 Handle(ShapeFix_Face)::DownCast(sfs->FixFaceTool())->FixOrientationMode() = Standard_False;
291 Handle(ShapeFix_Face)::DownCast(sfs->FixFaceTool())->FixSmallAreaWireMode() = Standard_False;
292 sfs->FixWireTool()->ModifyTopologyMode() = Standard_True;
293 //sfs.FixWireTool().FixReorderMode() = Standard_False;
294 sfs->FixWireTool()->FixConnectedMode() = Standard_False;
295 sfs->FixWireTool()->FixEdgeCurvesMode() = Standard_False;
296 sfs->FixWireTool()->FixDegeneratedMode() = Standard_False;
297 Handle(ShapeFix_Wire)::DownCast(sfs->FixWireTool())->FixSelfIntersectionMode() = Standard_False;
298 Handle(ShapeFix_Wire)::DownCast(sfs->FixWireTool())->FixLackingMode() = Standard_False;
299 Handle(ShapeFix_Wire)::DownCast(sfs->FixWireTool())->FixSmallMode() = Standard_True;
301 TopoDS_Shape result = sfs->Shape();
302 context = sfs->Context();
307 //=======================================================================
308 //function : ReplaceVertex
309 //purpose : auxilary for FixVertexPosition
310 //=======================================================================
311 static TopoDS_Edge ReplaceVertex(const TopoDS_Edge& theEdge,
313 const Standard_Boolean theFwd)
315 TopoDS_Vertex aNewVertex;
317 aB.MakeVertex(aNewVertex,theP,Precision::Confusion());
318 TopoDS_Vertex aV1,aV2;
321 aV1.Orientation( TopAbs_FORWARD);
325 aV2.Orientation( TopAbs_REVERSED);
327 ShapeBuild_Edge aSbe;
328 TopoDS_Edge e1 = theEdge;
329 TopAbs_Orientation Ori = e1.Orientation();
330 e1.Orientation(TopAbs_FORWARD);
331 TopoDS_Edge aNewEdge = aSbe.CopyReplaceVertices(e1,aV1,aV2);
332 aNewEdge.Orientation(Ori);
337 //=======================================================================
338 //function : getNearPoint
339 //purpose : auxilary for FixVertexPosition
340 //=======================================================================
341 static Standard_Real getNearPoint(const TColgp_SequenceOfPnt& aSeq1,
342 const TColgp_SequenceOfPnt& aSeq2,
345 Standard_Integer i =1;
346 Standard_Integer ind1 =0,ind2 =0;
347 Standard_Real mindist =RealLast();
348 for( ; i <= aSeq1.Length(); i++) {
349 gp_Pnt p1 = aSeq1.Value(i);
350 Standard_Integer j=1;
351 for( ; j <= aSeq2.Length(); j++) {
352 gp_Pnt p2 = aSeq2.Value(j);
353 Standard_Real d = p1.Distance(p2);
354 if(fabs(d -mindist ) <= Precision::Confusion())
365 acent = (aSeq1.Value(ind1).XYZ() + aSeq2.Value(ind2).XYZ())/2.0;
370 //=======================================================================
371 //function : getNearestEdges
372 //purpose : auxilary for FixVertexPosition
373 //=======================================================================
374 static Standard_Boolean getNearestEdges(TopTools_ListOfShape& theLEdges,
375 const TopoDS_Vertex theVert,
376 TopTools_SequenceOfShape& theSuitEdges,
377 TopTools_SequenceOfShape& theRejectEdges,
378 const Standard_Real theTolerance,
379 gp_XYZ& thecentersuit,
380 gp_XYZ& thecenterreject)
382 if(theLEdges.IsEmpty())
383 return Standard_False;
384 TopTools_MapOfShape aMapEdges;
386 TopTools_ListOfShape atempList;
387 atempList= theLEdges;
388 TopTools_ListIteratorOfListOfShape alIter(atempList);
390 TopoDS_Edge aEdge1 = TopoDS::Edge(alIter.Value());
391 TopoDS_Vertex aVert11,aVert12;
392 TopExp::Vertices(aEdge1, aVert11,aVert12 );
393 aMapEdges.Add(aEdge1);
394 Standard_Real aFirst1,aLast1;
395 Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(aEdge1,aFirst1,aLast1);
398 Standard_Boolean isFirst1 = theVert.IsSame(aVert11);
399 Standard_Boolean isSame1 = aVert11.IsSame(aVert12);
400 if( !aCurve1.IsNull()) {
402 p11 = aCurve1->Value(aFirst1);
404 p11 = aCurve1->Value(aLast1);
406 p12 = aCurve1->Value(aLast1);
408 else return Standard_False;
410 TopTools_SequenceOfShape aseqreject;
411 TopTools_SequenceOfShape aseqsuit;
413 Standard_Integer anumLoop =0;
414 for( ; alIter.More(); ) {
415 TopoDS_Edge aEdge = TopoDS::Edge(alIter.Value());
416 if( aMapEdges.Contains(aEdge)) {
417 atempList.Remove(alIter);
421 TopoDS_Vertex aVert1,aVert2;
422 TopExp::Vertices(aEdge, aVert1,aVert2 );
423 Standard_Real isFirst = theVert.IsSame(aVert1);
424 Standard_Boolean isSame = aVert1.IsSame(aVert2);
426 Standard_Boolean isLoop = ((aVert1.IsSame(aVert11) && aVert2.IsSame(aVert12)) ||
427 (aVert1.IsSame(aVert12) && aVert2.IsSame(aVert11)));
428 if(isLoop /*&& !aseqsuit.Length()*/ && (atempList.Extent() >anumLoop)) {
429 atempList.Append(aEdge);
430 atempList.Remove(alIter);
434 aMapEdges.Add(aEdge);
435 Standard_Real aFirst,aLast;
436 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
437 if( !aCurve.IsNull()) {
441 p1 = aCurve->Value(aFirst);
443 p1 = aCurve->Value(aLast);
445 p2 = aCurve->Value(aLast);
446 Standard_Real aMinDist = RealLast();
448 if(!isSame && ! isSame1) {
449 aMinDist = p1.Distance(p11);
450 acent = (p1.XYZ() + p11.XYZ())/2.0;
453 TColgp_SequenceOfPnt aSeq1;
454 TColgp_SequenceOfPnt aSeq2;
461 aMinDist = getNearPoint(aSeq1,aSeq2,acent);
464 if(aMinDist > theTolerance) {
465 if(!aseqreject.Length())
466 thecenterreject = acent;
467 aseqreject.Append(aEdge);
470 if(!aseqsuit.Length()) {
471 thecentersuit = acent;
472 aseqsuit.Append(aEdge);
475 aseqsuit.Append(aEdge);
476 else if((thecentersuit - acent).Modulus() < theTolerance)
477 aseqsuit.Append(aEdge);
479 aseqreject.Append(aEdge);
483 atempList.Remove(alIter);
486 Standard_Boolean isDone = (!aseqsuit.IsEmpty() || !aseqreject.IsEmpty());
488 if(aseqsuit.IsEmpty()) {
489 theRejectEdges.Append(aEdge1);
490 theLEdges.RemoveFirst();
492 getNearestEdges(theLEdges,theVert,theSuitEdges,theRejectEdges,
493 theTolerance,thecentersuit,thecenterreject);
496 theSuitEdges.Append(aEdge1);
497 theSuitEdges.Append(aseqsuit);
498 theRejectEdges.Append(aseqreject);
502 theRejectEdges.Append(aEdge1);
508 //=======================================================================
509 //function : FixVertexPosition
511 //=======================================================================
513 Standard_Boolean ShapeFix::FixVertexPosition(TopoDS_Shape& theshape,
514 const Standard_Real theTolerance,
515 const Handle(ShapeBuild_ReShape)& thecontext)
517 TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdges;
518 TopExp_Explorer aExp1(theshape,TopAbs_EDGE);
519 for( ; aExp1.More(); aExp1.Next()) {
521 Standard_Integer nV =1;
522 TopoDS_Iterator aExp3(aExp1.Current());
523 for( ; aExp3.More(); aExp3.Next(),nV++) {
524 TopoDS_Shape aVert = aExp3.Value();
527 else if(aVert1.IsSame(aVert))
529 if(aMapVertEdges.Contains(aVert))
530 aMapVertEdges.ChangeFromKey(aVert).Append(aExp1.Current());
532 TopTools_ListOfShape alEdges;
533 alEdges.Append(aExp1.Current());
534 aMapVertEdges.Add(aVert,alEdges);
538 Standard_Boolean isDone = Standard_False;
539 Standard_Integer i=1;
540 for( ; i <= aMapVertEdges.Extent(); i++) {
541 TopoDS_Vertex aVert = TopoDS::Vertex(aMapVertEdges.FindKey(i));
542 Standard_Real aTolVert = BRep_Tool::Tolerance(aVert);
543 if(aTolVert <= theTolerance)
547 aB1.UpdateVertex(aVert,theTolerance);
548 gp_Pnt aPvert = BRep_Tool::Pnt(aVert);
549 gp_XYZ acenter(aPvert.XYZ()), acenterreject(aPvert.XYZ());
551 TopTools_SequenceOfShape aSuitEdges;
552 TopTools_SequenceOfShape aRejectEdges;
553 TopTools_ListOfShape aledges;
554 aledges= aMapVertEdges.FindFromIndex(i);
555 if(aledges.Extent() ==1)
557 //if tolerance of vertex is more than specified tolerance
558 // check distance between curves and vertex
560 if(!getNearestEdges(aledges,aVert,aSuitEdges,aRejectEdges,theTolerance,acenter,acenterreject))
563 //update vertex by nearest point
564 Standard_Boolean isAdd = Standard_False;
565 Standard_Integer k =1;
566 for( ; k <= aSuitEdges.Length(); k++) {
568 TopoDS_Edge aEdgeOld = TopoDS::Edge(aSuitEdges.Value(k));
569 TopoDS_Vertex aVert1,aVert2;
570 TopExp::Vertices(aEdgeOld, aVert1,aVert2 );
572 Standard_Boolean isFirst = (aVert1.IsSame(aVert));
573 Standard_Boolean isLast = (aVert2.IsSame(aVert));
574 if(!isFirst && !isLast)
576 Standard_Real aFirst,aLast;
577 Handle(Geom_Curve) aCurve;
578 TopoDS_Edge aEdge = TopoDS::Edge(thecontext->Apply(aEdgeOld));
580 TopoDS_Vertex aVert1n,aVert2n;
581 TopExp::Vertices(aEdge, aVert1n,aVert2n );
582 aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
583 if( !aCurve.IsNull()) {
584 gp_Pnt p1 = aCurve->Value(aFirst);
585 gp_Pnt p2 = aCurve->Value(aLast);
587 //if distance between ends of curve more than specified tolerance
588 //but vertices are the same that one of the vertex will be replaced.
590 Standard_Boolean isReplace = (aVert1n.IsSame(aVert2n) && p1.Distance(p2) >theTolerance);
592 //Standard_Real dd1 = (acenter - p1.XYZ()).Modulus();
593 //Standard_Real dd2 = (acenter - p2.XYZ()).Modulus();
601 if(p1.Distance(acenter) < p2.Distance(acenter))
602 enew = ReplaceVertex(aEdge,p2,Standard_False);
604 enew = ReplaceVertex(aEdge,p1,Standard_True);
605 thecontext->Replace(aEdge,enew);
606 isDone = Standard_True;
616 if(p1.Distance(acenter) < p2.Distance(acenter))
617 enew = ReplaceVertex(aEdge,p2,Standard_False);
619 enew = ReplaceVertex(aEdge,p1,Standard_True);
620 thecontext->Replace(aEdge,enew);
621 isDone = Standard_True;
627 isAdd = Standard_True;
633 if(isAdd && aPvert.Distance(acenter) > theTolerance)
638 // aB.UpdateVertex(aVert,Precision::Confusion());
640 isDone = Standard_True;
641 TopoDS_Vertex aNewVertex;
642 aB.MakeVertex(aNewVertex,acenter,Precision::Confusion());
643 aNewVertex.Orientation(aVert.Orientation());
644 thecontext->Replace(aVert,aNewVertex);
648 for( k =1; k <= aRejectEdges.Length(); k++) {
649 TopoDS_Edge aEdgeOld = TopoDS::Edge( aRejectEdges.Value(k));
650 TopoDS_Vertex aVert1,aVert2;
651 TopExp::Vertices(aEdgeOld, aVert1,aVert2 );
653 Standard_Boolean isFirst = (aVert1.IsSame(aVert));
654 Standard_Boolean isLast = (aVert2.IsSame(aVert));
655 if(!isFirst && !isLast)
657 Standard_Boolean isSame = aVert1.IsSame(aVert2);
658 Handle(Geom_Curve) aCurve;
659 TopoDS_Edge aEdge = TopoDS::Edge(thecontext->Apply(aEdgeOld));
661 TopoDS_Vertex aVert1n,aVert2n;
662 TopExp::Vertices(aEdge, aVert1n,aVert2n );
664 Standard_Real aFirst,aLast;
665 aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
666 if( !aCurve.IsNull()) {
667 gp_Pnt p1 = aCurve->Value(aFirst);
668 gp_Pnt p2 = aCurve->Value(aLast);
671 enew = ReplaceVertex(aEdge,p1,Standard_True);
673 enew = ReplaceVertex(enew,p2,Standard_False);
676 enew = ReplaceVertex(aEdge,p2,Standard_False);
678 enew = ReplaceVertex(enew ,p1,Standard_True);
681 thecontext->Replace(aEdge,enew);
682 isDone = Standard_True;
690 theshape = thecontext->Apply(theshape);
695 //=======================================================================
696 //function : LeastEdgeSize
698 //=======================================================================
700 Standard_Real ShapeFix::LeastEdgeSize(TopoDS_Shape& theShape)
702 Standard_Real aRes = RealLast();
703 for(TopExp_Explorer exp(theShape,TopAbs_EDGE); exp.More(); exp.Next()) {
704 TopoDS_Edge edge = TopoDS::Edge ( exp.Current() );
705 Standard_Real first,last;
706 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge, first, last);
709 bb.Add(c3d->Value(first));
710 bb.Add(c3d->Value(last));
711 bb.Add(c3d->Value((last+first)/2.));
712 Standard_Real x1,x2,y1,y2,z1,z2,size;
713 bb.Get(x1,y1,z1,x2,y2,z2);
714 size = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1);
715 if(size<aRes) aRes = size;