Back to index

salome-geom  6.5.0
BlockFix_UnionFaces.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  File:    BlockFix_UnionFaces.cxx
00024 //  Created: Tue Dec  7 17:15:42 2004
00025 //  Author:  Pavel DURANDIN
00026 
00027 #include <BlockFix_UnionFaces.ixx>
00028 
00029 #include <Basics_OCCTVersion.hxx>
00030 
00031 #include <ShapeAnalysis_WireOrder.hxx>
00032 #include <ShapeAnalysis_Edge.hxx>
00033 
00034 #include <ShapeBuild_Edge.hxx>
00035 #include <ShapeBuild_ReShape.hxx>
00036 
00037 #include <ShapeExtend_WireData.hxx>
00038 #include <ShapeExtend_CompositeSurface.hxx>
00039 
00040 #include <ShapeFix_Face.hxx>
00041 #include <ShapeFix_ComposeShell.hxx>
00042 #include <ShapeFix_SequenceOfWireSegment.hxx>
00043 #include <ShapeFix_WireSegment.hxx>
00044 #include <ShapeFix_Wire.hxx>
00045 #include <ShapeFix_Edge.hxx>
00046 
00047 #if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
00048 #include <IntPatch_ImpImpIntersection.hxx>
00049 #else
00050 #include <IntPatch_TheIIIntOfIntersection.hxx>
00051 #endif
00052 
00053 #include <BRep_Tool.hxx>
00054 #include <BRep_Builder.hxx>
00055 #include <BRepTools.hxx>
00056 #include <BRepTopAdaptor_TopolTool.hxx>
00057 
00058 #include <TopExp.hxx>
00059 #include <TopExp_Explorer.hxx>
00060 
00061 #include <TopTools_SequenceOfShape.hxx>
00062 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
00063 #include <TopTools_ListOfShape.hxx>
00064 #include <TopTools_ListIteratorOfListOfShape.hxx>
00065 #include <TopTools_MapOfShape.hxx>
00066 #include <TopTools_MapIteratorOfMapOfShape.hxx>
00067 
00068 #include <TopoDS.hxx>
00069 #include <TopoDS_Edge.hxx>
00070 #include <TopoDS_Wire.hxx>
00071 #include <TopoDS_Face.hxx>
00072 #include <TopoDS_Solid.hxx>
00073 #include <TopoDS_Vertex.hxx>
00074 #include <TopoDS_Shell.hxx>
00075 #include <TopoDS_Iterator.hxx>
00076 
00077 #include <TColGeom_HArray2OfSurface.hxx>
00078 
00079 #include <GeomAdaptor_HSurface.hxx>
00080 #include <GeomLib_IsPlanarSurface.hxx>
00081 
00082 #include <Geom_Surface.hxx>
00083 #include <Geom_Plane.hxx>
00084 #include <Geom_OffsetSurface.hxx>
00085 #include <Geom_SphericalSurface.hxx>
00086 #include <Geom_CylindricalSurface.hxx>
00087 #include <Geom_SurfaceOfRevolution.hxx>
00088 #include <Geom_SurfaceOfLinearExtrusion.hxx>
00089 #include <Geom_RectangularTrimmedSurface.hxx>
00090 
00091 #include <Geom_Curve.hxx>
00092 #include <Geom_Line.hxx>
00093 #include <Geom_Circle.hxx>
00094 
00095 #include <Geom2d_Line.hxx>
00096 
00097 #include <gp_XY.hxx>
00098 #include <gp_Pnt2d.hxx>
00099 
00100 #include <Standard_Failure.hxx>
00101 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
00102 
00103 //=======================================================================
00104 //function : BlockFix_UnionFaces
00105 //purpose  :
00106 //=======================================================================
00107 
00108 BlockFix_UnionFaces::BlockFix_UnionFaces()
00109   : myTolerance(Precision::Confusion()),
00110     myOptimumNbFaces(6)
00111 {
00112 }
00113 
00114 
00115 //=======================================================================
00116 //function : GetTolerance
00117 //purpose  :
00118 //=======================================================================
00119 
00120 Standard_Real& BlockFix_UnionFaces::GetTolerance()
00121 {
00122   return myTolerance;
00123 }
00124 
00125 
00126 //=======================================================================
00127 //function : GetOptimumNbFaces
00128 //purpose  :
00129 //=======================================================================
00130 
00131 Standard_Integer& BlockFix_UnionFaces::GetOptimumNbFaces()
00132 {
00133   return myOptimumNbFaces;
00134 }
00135 
00136 
00137 //=======================================================================
00138 //function : AddOrdinaryEdges
00139 //purpose  : auxilary
00140 //=======================================================================
00141 // adds edges from the shape to the sequence
00142 // seams and equal edges are dropped
00143 // Returns true if one of original edges dropped
00144 static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges,
00145                                          const TopoDS_Shape aShape,
00146                                          Standard_Integer& anIndex)
00147 {
00148   //map of edges
00149   TopTools_MapOfShape aNewEdges;
00150   //add edges without seams
00151   for(TopExp_Explorer exp(aShape,TopAbs_EDGE); exp.More(); exp.Next()) {
00152     TopoDS_Shape edge = exp.Current();
00153     if(aNewEdges.Contains(edge))
00154       aNewEdges.Remove(edge);
00155     else
00156       aNewEdges.Add(edge);
00157   }
00158 
00159   Standard_Boolean isDropped = Standard_False;
00160   //merge edges and drop seams
00161   for(Standard_Integer i = 1; i <= edges.Length(); i++) {
00162     TopoDS_Shape current = edges(i);
00163     if(aNewEdges.Contains(current)) {
00164 
00165       aNewEdges.Remove(current);
00166       edges.Remove(i);
00167       i--;
00168 
00169       if(!isDropped) {
00170         isDropped = Standard_True;
00171         anIndex = i;
00172       }
00173     }
00174   }
00175 
00176   //add edges to the sequemce
00177   for(TopTools_MapIteratorOfMapOfShape anIter(aNewEdges); anIter.More(); anIter.Next())
00178     edges.Append(anIter.Key());
00179 
00180   return isDropped;
00181 }
00182 
00183 
00184 //=======================================================================
00185 //function : ClearRts
00186 //purpose  : auxilary
00187 //=======================================================================
00188 static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface)
00189 {
00190   if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
00191     Handle(Geom_RectangularTrimmedSurface) rts =
00192       Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
00193     return rts->BasisSurface();
00194   }
00195   return aSurface;
00196 }
00197 
00198 
00199 //=======================================================================
00200 //function : Perform
00201 //purpose  :
00202 //=======================================================================
00203 
00204 TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
00205 {
00206   Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
00207   TopoDS_Shape aResShape = myContext->Apply(Shape);
00208 
00209   // processing each solid
00210   TopExp_Explorer exps;
00211   for (exps.Init(Shape, TopAbs_SOLID); exps.More(); exps.Next()) {
00212     TopoDS_Solid aSolid = TopoDS::Solid(exps.Current());
00213 
00214     // creating map of edge faces
00215     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
00216     TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
00217 
00218     // map of processed shapes
00219     TopTools_MapOfShape aProcessed;
00220 
00221     Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
00222 
00223     Standard_Integer NbModif = 0;
00224     Standard_Boolean hasFailed = Standard_False;
00225     Standard_Real tol = Min(Max(Precision::Confusion(), myTolerance/10.), 0.1);
00226 
00227     // count faces
00228     int nbf = 0;
00229     TopExp_Explorer exp;
00230     TopTools_MapOfShape mapF;
00231     for (exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) {
00232       if (mapF.Add(exp.Current()))
00233         nbf++;
00234     }
00235 
00236     bool doUnion = ((myOptimumNbFaces == 0) ||
00237                     ((myOptimumNbFaces > 0) && (nbf > myOptimumNbFaces)));
00238 
00239     // processing each face
00240     mapF.Clear();
00241     for (exp.Init(aSolid, TopAbs_FACE); exp.More() && doUnion; exp.Next()) {
00242       TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
00243 
00244       if (aProcessed.Contains(aFace))
00245         continue;
00246 
00247       Standard_Integer dummy;
00248       TopTools_SequenceOfShape edges;
00249       AddOrdinaryEdges(edges,aFace,dummy);
00250 
00251       TopTools_SequenceOfShape faces;
00252       faces.Append(aFace);
00253 
00254       //surface and location to construct result
00255       TopLoc_Location aBaseLocation;
00256       Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
00257       aBaseSurface = ClearRts(aBaseSurface);
00258 
00259       // find adjacent faces to union
00260       Standard_Integer i;
00261       for (i = 1; i <= edges.Length(); i++) {
00262         TopoDS_Edge edge = TopoDS::Edge(edges(i));
00263         if (BRep_Tool::Degenerated(edge))
00264           continue;
00265 
00266         const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
00267         TopTools_ListIteratorOfListOfShape anIter(aList);
00268         for (; anIter.More(); anIter.Next()) {
00269           TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD));
00270           if (anCheckedFace.IsSame(aFace))
00271             continue;
00272 
00273           if (aProcessed.Contains(anCheckedFace))
00274             continue;
00275 
00276           if (IsSameDomain(aFace,anCheckedFace)) {
00277 
00278             if (aList.Extent() != 2) {
00279               // non mainfold case is not processed
00280               continue;
00281             }
00282 
00283             // replacing pcurves
00284             TopoDS_Face aMockUpFace;
00285             BRep_Builder B;
00286             B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.);
00287             MovePCurves(aMockUpFace,anCheckedFace);
00288 
00289             if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) {
00290               // sequence edges is modified
00291               i = dummy;
00292             }
00293 
00294             faces.Append(anCheckedFace);
00295             aProcessed.Add(anCheckedFace);
00296             break;
00297           }
00298         }
00299       }
00300 
00301       // all faces collected in the sequence. Perform union of faces
00302       if (faces.Length() > 1) {
00303         NbModif++;
00304         TopoDS_Face aResult;
00305         BRep_Builder B;
00306         B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
00307         Standard_Integer nbWires = 0;
00308 
00309         // connecting wires
00310         while (edges.Length()>0) {
00311 
00312           Standard_Boolean isEdge3d = Standard_False;
00313           nbWires++;
00314           TopTools_MapOfShape aVertices;
00315           TopoDS_Wire aWire;
00316           B.MakeWire(aWire);
00317 
00318           TopoDS_Edge anEdge = TopoDS::Edge(edges(1));
00319           edges.Remove(1);
00320 
00321           isEdge3d |= !BRep_Tool::Degenerated(anEdge);
00322           B.Add(aWire,anEdge);
00323           TopoDS_Vertex V1,V2;
00324           TopExp::Vertices(anEdge,V1,V2);
00325           aVertices.Add(V1);
00326           aVertices.Add(V2);
00327 
00328           Standard_Boolean isNewFound = Standard_False;
00329           do {
00330             isNewFound = Standard_False;
00331             for(Standard_Integer j = 1; j <= edges.Length(); j++) {
00332               anEdge = TopoDS::Edge(edges(j));
00333               TopExp::Vertices(anEdge,V1,V2);
00334               if(aVertices.Contains(V1) || aVertices.Contains(V2)) {
00335                 isEdge3d |= !BRep_Tool::Degenerated(anEdge);
00336                 aVertices.Add(V1);
00337                 aVertices.Add(V2);
00338                 B.Add(aWire,anEdge);
00339                 edges.Remove(j);
00340                 j--;
00341                 isNewFound = Standard_True;
00342               }
00343             }
00344           } while (isNewFound);
00345 
00346           // sorting any type of edges
00347           aWire = TopoDS::Wire(aContext->Apply(aWire));
00348 
00349           TopoDS_Face tmpF = TopoDS::Face(aContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
00350           Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
00351           sfw->FixReorder();
00352           Standard_Boolean isDegRemoved = Standard_False;
00353           if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
00354             // clear degenerated edges if at least one with 3d curve exist
00355             if(isEdge3d) {
00356               Handle(ShapeExtend_WireData) sewd = sfw->WireData();
00357               for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) {
00358                 TopoDS_Edge E = sewd->Edge(j);
00359                 if(BRep_Tool::Degenerated(E)) {
00360                   sewd->Remove(j);
00361                   isDegRemoved = Standard_True;
00362                   j--;
00363                 }
00364               }
00365             }
00366             sfw->FixShifted();
00367             if(isDegRemoved)
00368               sfw->FixDegenerated();
00369           }
00370           TopoDS_Wire aWireFixed = sfw->Wire();
00371           aContext->Replace(aWire,aWireFixed);
00372           // add resulting wire
00373           if(isEdge3d) {
00374             B.Add(aResult,aWireFixed);
00375           }
00376           else  {
00377             // sorting edges
00378             Handle(ShapeExtend_WireData) sbwd = sfw->WireData();
00379             Standard_Integer nbEdges = sbwd->NbEdges();
00380             // sort degenerated edges and create one edge instead of several ones
00381             ShapeAnalysis_WireOrder sawo(Standard_False, 0);
00382             ShapeAnalysis_Edge sae;
00383             Standard_Integer aLastEdge = nbEdges;
00384             for(Standard_Integer j = 1; j <= nbEdges; j++) {
00385               Standard_Real f,l;
00386               //smh protection on NULL pcurve
00387               Handle(Geom2d_Curve) c2d;
00388               if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) {
00389                 aLastEdge--;
00390                 continue;
00391               }
00392               sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
00393             }
00394             sawo.Perform();
00395 
00396             // constructind one degenerative edge
00397             gp_XY aStart, anEnd, tmp;
00398             Standard_Integer nbFirst = sawo.Ordered(1);
00399             TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
00400             ShapeBuild_Edge sbe;
00401             TopoDS_Vertex aDummyV;
00402             TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
00403             sawo.XY(nbFirst,aStart,tmp);
00404             sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
00405 
00406             gp_XY aVec = anEnd-aStart;
00407             Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
00408 
00409             B.UpdateEdge(E,aLine,tmpF,0.);
00410             B.Range(E,tmpF,0.,aVec.Modulus());
00411             Handle(Geom_Curve) C3d;
00412             B.UpdateEdge(E,C3d,0.);
00413             B.Degenerated(E,Standard_True);
00414             TopoDS_Wire aW;
00415             B.MakeWire(aW);
00416             B.Add(aW,E);
00417             B.Add(aResult,aW);
00418           }
00419         }
00420 
00421         // perform substitution of face
00422         aContext->Replace(aContext->Apply(aFace),aResult);
00423 
00424         ShapeFix_Face sff (aResult);
00425         //Intializing by tolerances
00426         sff.SetPrecision(myTolerance);
00427         sff.SetMinTolerance(tol);
00428         sff.SetMaxTolerance(Max(1.,myTolerance*1000.));
00429         //Setting modes
00430         sff.FixOrientationMode() = 0;
00431         //sff.FixWireMode() = 0;
00432         sff.SetContext(aContext);
00433         // Applying the fixes
00434         sff.Perform();
00435         if(sff.Status(ShapeExtend_FAIL))
00436         hasFailed = Standard_True;
00437 
00438         // breaking down to several faces
00439         TopoDS_Shape theResult = aContext->Apply(aResult);
00440         for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) {
00441           TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD));
00442           Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
00443           grid->SetValue ( 1, 1, aBaseSurface );
00444           Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
00445           ShapeFix_ComposeShell CompShell;
00446           CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision
00447           CompShell.SetContext( aContext );
00448 
00449           TopTools_SequenceOfShape parts;
00450           ShapeFix_SequenceOfWireSegment wires;
00451           for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
00452             Handle(ShapeExtend_WireData) sbwd =
00453               new ShapeExtend_WireData ( TopoDS::Wire(W_Exp.Current() ));
00454             ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
00455             wires.Append(seg);
00456           }
00457 
00458           CompShell.DispatchWires ( parts,wires );
00459           for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
00460             ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
00461             aFixOrient.SetContext(aContext);
00462             aFixOrient.FixOrientation();
00463           }
00464 
00465           TopoDS_Shape CompRes;
00466           if ( faces.Length() !=1 ) {
00467             TopoDS_Shell S;
00468             B.MakeShell ( S );
00469             for ( i=1; i <= parts.Length(); i++ )
00470               B.Add ( S, parts(i) );
00471             CompRes = S;
00472           }
00473           else CompRes = parts(1);
00474 
00475           aContext->Replace(aCurrent,CompRes);
00476         }
00477 
00478         // remove the remaining faces
00479         for(i = 2; i <= faces.Length(); i++)
00480           aContext->Remove(faces(i));
00481       }
00482     } // end processing each face
00483 
00484     //TopoDS_Shape aResult = Shape;
00485     if (NbModif > 0 && !hasFailed) {
00486       TopoDS_Shape aResult = aContext->Apply(aSolid);
00487 
00488       ShapeFix_Edge sfe;
00489       for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
00490         TopoDS_Edge E = TopoDS::Edge(exp.Current());
00491         sfe.FixVertexTolerance (E);
00492         // ptv add fix same parameter
00493         sfe.FixSameParameter(E, myTolerance);
00494       }
00495 
00496       myContext->Replace(aSolid, aResult);
00497     }
00498     //else
00499     {
00500       for (exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) {
00501         TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
00502         Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
00503         sfw->SetContext(myContext);
00504         sfw->SetPrecision(myTolerance);
00505         sfw->SetMinTolerance(myTolerance);
00506         sfw->SetMaxTolerance(Max(1.,myTolerance*1000.));
00507         sfw->SetFace(aFace);
00508         for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
00509           TopoDS_Wire wire = TopoDS::Wire(iter.Value());
00510           sfw->Load(wire);
00511           sfw->FixReorder();
00512           sfw->FixShifted();
00513         }
00514       }
00515     }
00516   } // end processing each solid
00517 
00518   aResShape = myContext->Apply(Shape);
00519   return aResShape;
00520 }
00521 
00522 
00523 //=======================================================================
00524 //function : IsSameDomain
00525 //purpose  :
00526 //=======================================================================
00527 
00528 bool getCylinder (Handle(Geom_Surface)& theInSurface, gp_Cylinder& theOutCylinder)
00529 {
00530   bool isCylinder = false;
00531 
00532   if (theInSurface->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
00533     Handle(Geom_CylindricalSurface) aGC = Handle(Geom_CylindricalSurface)::DownCast(theInSurface);
00534 
00535     theOutCylinder = aGC->Cylinder();
00536     isCylinder = true;
00537   }
00538   else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
00539     Handle(Geom_SurfaceOfRevolution) aRS =
00540       Handle(Geom_SurfaceOfRevolution)::DownCast(theInSurface);
00541     Handle(Geom_Curve) aBasis = aRS->BasisCurve();
00542     if (aBasis->IsKind(STANDARD_TYPE(Geom_Line))) {
00543       Handle(Geom_Line) aBasisLine = Handle(Geom_Line)::DownCast(aBasis);
00544       gp_Dir aDir = aRS->Direction();
00545       gp_Dir aBasisDir = aBasisLine->Position().Direction();
00546       if (aBasisDir.IsParallel(aDir, Precision::Confusion())) {
00547         // basis line is parallel to the revolution axis: it is a cylinder
00548         gp_Pnt aLoc = aRS->Location();
00549         Standard_Real aR = aBasisLine->Lin().Distance(aLoc);
00550         gp_Ax3 aCylAx (aLoc, aDir);
00551 
00552         theOutCylinder = gp_Cylinder(aCylAx, aR);
00553         isCylinder = true;
00554       }
00555     }
00556   }
00557   else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
00558     Handle(Geom_SurfaceOfLinearExtrusion) aLES =
00559       Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(theInSurface);
00560     Handle(Geom_Curve) aBasis = aLES->BasisCurve();
00561     if (aBasis->IsKind(STANDARD_TYPE(Geom_Circle))) {
00562       Handle(Geom_Circle) aBasisCircle = Handle(Geom_Circle)::DownCast(aBasis);
00563       gp_Dir aDir = aLES->Direction();
00564       gp_Dir aBasisDir = aBasisCircle->Position().Direction();
00565       if (aBasisDir.IsParallel(aDir, Precision::Confusion())) {
00566         // basis circle is normal to the extrusion axis: it is a cylinder
00567         gp_Pnt aLoc = aBasisCircle->Location();
00568         Standard_Real aR = aBasisCircle->Radius();
00569         gp_Ax3 aCylAx (aLoc, aDir);
00570 
00571         theOutCylinder = gp_Cylinder(aCylAx, aR);
00572         isCylinder = true;
00573       }
00574     }
00575   }
00576   else {
00577   }
00578 
00579   return isCylinder;
00580 }
00581 
00582 Standard_Boolean BlockFix_UnionFaces::IsSameDomain(const TopoDS_Face& aFace,
00583                                                    const TopoDS_Face& aCheckedFace) const
00584 {
00585   //checking the same handles
00586   TopLoc_Location L1, L2;
00587   Handle(Geom_Surface) S1, S2;
00588 
00589   S1 = BRep_Tool::Surface(aFace,L1);
00590   S2 = BRep_Tool::Surface(aCheckedFace,L2);
00591 
00592   if (S1 == S2 && L1 == L2)
00593     return true;
00594 
00595   // planar and cylindrical cases (IMP 20052)
00596   Standard_Real aPrec = Precision::Confusion();
00597 
00598   S1 = BRep_Tool::Surface(aFace);
00599   S2 = BRep_Tool::Surface(aCheckedFace);
00600 
00601   S1 = ClearRts(S1);
00602   S2 = ClearRts(S2);
00603 
00604   //Handle(Geom_OffsetSurface) aGOFS1, aGOFS2;
00605   //aGOFS1 = Handle(Geom_OffsetSurface)::DownCast(S1);
00606   //aGOFS2 = Handle(Geom_OffsetSurface)::DownCast(S2);
00607   //if (!aGOFS1.IsNull()) S1 = aGOFS1->BasisSurface();
00608   //if (!aGOFS2.IsNull()) S2 = aGOFS2->BasisSurface();
00609 
00610   // case of two elementary surfaces: use OCCT tool
00611   // elementary surfaces: ConicalSurface, CylindricalSurface,
00612   //                      Plane, SphericalSurface and ToroidalSurface
00613   if (S1->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) &&
00614       S2->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
00615   {
00616     Handle(GeomAdaptor_HSurface) aGA1 = new GeomAdaptor_HSurface(S1);
00617     Handle(GeomAdaptor_HSurface) aGA2 = new GeomAdaptor_HSurface(S2);
00618 
00619     Handle(BRepTopAdaptor_TopolTool) aTT1 = new BRepTopAdaptor_TopolTool();
00620     Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool();
00621 
00622     try {
00623 #if OCC_VERSION_LARGE > 0x06010000
00624       OCC_CATCH_SIGNALS;
00625 #endif
00626 
00627 #if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
00628       IntPatch_ImpImpIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec);
00629 #else
00630       IntPatch_TheIIIntOfIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec);
00631 #endif
00632       if (!anIIInt.IsDone() || anIIInt.IsEmpty())
00633         return false;
00634 
00635       return anIIInt.TangentFaces();
00636     }
00637     catch (Standard_Failure) {
00638       return false;
00639     }
00640   }
00641 
00642   // case of two planar surfaces:
00643   // all kinds of surfaces checked, including b-spline and bezier
00644   GeomLib_IsPlanarSurface aPlanarityChecker1 (S1, aPrec);
00645   if (aPlanarityChecker1.IsPlanar()) {
00646     GeomLib_IsPlanarSurface aPlanarityChecker2 (S2, aPrec);
00647     if (aPlanarityChecker2.IsPlanar()) {
00648       gp_Pln aPln1 = aPlanarityChecker1.Plan();
00649       gp_Pln aPln2 = aPlanarityChecker2.Plan();
00650 
00651       if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(), aPrec) &&
00652           aPln1.Distance(aPln2) < aPrec) {
00653         return true;
00654       }
00655     }
00656   }
00657 
00658   // case of two cylindrical surfaces, at least one of which is a swept surface
00659   // swept surfaces: SurfaceOfLinearExtrusion, SurfaceOfRevolution
00660   if ((S1->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
00661        S1->IsKind(STANDARD_TYPE(Geom_SweptSurface))) &&
00662       (S2->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
00663        S2->IsKind(STANDARD_TYPE(Geom_SweptSurface))))
00664   {
00665     gp_Cylinder aCyl1, aCyl2;
00666     if (getCylinder(S1, aCyl1) && getCylinder(S2, aCyl2)) {
00667       if (fabs(aCyl1.Radius() - aCyl2.Radius()) < aPrec) {
00668         gp_Dir aDir1 = aCyl1.Position().Direction();
00669         gp_Dir aDir2 = aCyl2.Position().Direction();
00670         if (aDir1.IsParallel(aDir2, aPrec)) {
00671           gp_Pnt aLoc1 = aCyl1.Location();
00672           gp_Pnt aLoc2 = aCyl2.Location();
00673           gp_Vec aVec12 (aLoc1, aLoc2);
00674           if (aVec12.SquareMagnitude() < aPrec*aPrec ||
00675               aVec12.IsParallel(aDir1, aPrec)) {
00676             return true;
00677           }
00678         }
00679       }
00680     }
00681   }
00682 
00683   return false;
00684 }
00685 
00686 
00687 //=======================================================================
00688 //function : MovePCurves
00689 //purpose  :
00690 //=======================================================================
00691 
00692 void BlockFix_UnionFaces::MovePCurves(TopoDS_Face& aTarget,
00693                                       const TopoDS_Face& aSource) const
00694 {
00695   BRep_Builder B;
00696   for(TopExp_Explorer wexp(aSource,TopAbs_WIRE);wexp.More();wexp.Next()) {
00697     Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(wexp.Current()),
00698                                                   aTarget, Precision::Confusion());
00699     sfw->FixReorder();
00700     Standard_Boolean isReoredFailed = sfw->StatusReorder ( ShapeExtend_FAIL );
00701     sfw->FixEdgeCurves();
00702     if(isReoredFailed)
00703       continue;
00704 
00705     sfw->FixShifted();
00706     sfw->FixDegenerated();
00707 
00708     // remove degenerated edges from not degenerated points
00709     ShapeAnalysis_Edge sae;
00710     Handle(ShapeExtend_WireData) sewd = sfw->WireData();
00711     for(Standard_Integer i = 1; i<=sewd->NbEdges();i++) {
00712       TopoDS_Edge E = sewd->Edge(i);
00713       if(BRep_Tool::Degenerated(E)&&!sae.HasPCurve(E,aTarget)) {
00714         sewd->Remove(i);
00715         i--;
00716       }
00717     }
00718 
00719     TopoDS_Wire ResWire = sfw->Wire();
00720     B.Add(aTarget,ResWire);
00721   }
00722 }