1 // File: BlockFix_UnionFaces.cxx
2 // Created: Tue Dec 7 17:15:42 2004
3 // Author: Pavel DURANDIN
4 // Open CASCADE SA 2004
6 #include <BlockFix_UnionFaces.ixx>
7 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
9 #include <TopTools_MapOfShape.hxx>
10 #include <ShapeBuild_ReShape.hxx>
12 #include <TopoDS_Edge.hxx>
13 #include <TopoDS_Wire.hxx>
14 #include <TopoDS_Face.hxx>
15 #include <TopoDS_Solid.hxx>
16 #include <TopExp_Explorer.hxx>
17 #include <TopTools_SequenceOfShape.hxx>
18 #include <Geom_Surface.hxx>
19 #include <BRep_Tool.hxx>
20 #include <TopTools_ListOfShape.hxx>
21 #include <TopTools_ListIteratorOfListOfShape.hxx>
22 #include <BRep_Builder.hxx>
23 #include <TopTools_MapIteratorOfMapOfShape.hxx>
24 #include <TopoDS_Vertex.hxx>
25 #include <ShapeFix_Face.hxx>
26 #include <BRep_Tool.hxx>
27 #include <ShapeExtend_WireData.hxx>
28 #include <ShapeAnalysis_WireOrder.hxx>
29 #include <ShapeAnalysis_Edge.hxx>
30 #include <Geom2d_Line.hxx>
32 #include <gp_Pnt2d.hxx>
33 #include <ShapeBuild_Edge.hxx>
34 #include <Geom_Curve.hxx>
35 #include <TopoDS_Vertex.hxx>
37 #include <ShapeFix_Wire.hxx>
38 #include <ShapeFix_Edge.hxx>
40 #include <Geom_RectangularTrimmedSurface.hxx>
41 #include <BRepTools.hxx>
43 #include <TColGeom_HArray2OfSurface.hxx>
44 #include <ShapeExtend_CompositeSurface.hxx>
45 #include <ShapeFix_ComposeShell.hxx>
46 #include <TopTools_SequenceOfShape.hxx>
47 #include <ShapeFix_SequenceOfWireSegment.hxx>
48 #include <ShapeFix_WireSegment.hxx>
49 #include <TopoDS_Shell.hxx>
50 #include <TopoDS_Iterator.hxx>
52 #include <Geom_CylindricalSurface.hxx>
53 #include <Geom_SphericalSurface.hxx>
56 //=======================================================================
57 //function : BlockFix_UnionFaces
59 //=======================================================================
61 BlockFix_UnionFaces::BlockFix_UnionFaces()
62 : myTolerance(Precision::Confusion())
67 //=======================================================================
68 //function : GetTolearnce
70 //=======================================================================
72 Standard_Real& BlockFix_UnionFaces::GetTolerance()
78 //=======================================================================
79 //function : AddOrdinaryEdges
81 //=======================================================================
82 // adds edges from the shape to the sequence
83 // seams and equal edges are dropped
84 // Returns true if one of original edges dropped
85 static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges,
86 const TopoDS_Shape aShape,
87 Standard_Integer& anIndex)
90 TopTools_MapOfShape aNewEdges;
91 //add edges without seams
92 for(TopExp_Explorer exp(aShape,TopAbs_EDGE); exp.More(); exp.Next()) {
93 TopoDS_Shape edge = exp.Current();
94 if(aNewEdges.Contains(edge))
95 aNewEdges.Remove(edge);
100 Standard_Boolean isDropped = Standard_False;
101 //merge edges and drop seams
102 for(Standard_Integer i = 1; i <= edges.Length(); i++) {
103 TopoDS_Shape current = edges(i);
104 if(aNewEdges.Contains(current)) {
106 aNewEdges.Remove(current);
111 isDropped = Standard_True;
117 //add edges to the sequemce
118 for(TopTools_MapIteratorOfMapOfShape anIter(aNewEdges); anIter.More(); anIter.Next())
119 edges.Append(anIter.Key());
125 //=======================================================================
126 //function : ClearRts
128 //=======================================================================
129 static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface)
131 if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
132 Handle(Geom_RectangularTrimmedSurface) rts =
133 Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
134 return rts->BasisSurface();
140 //=======================================================================
143 //=======================================================================
145 TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
147 Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
148 TopoDS_Shape aResShape = myContext->Apply(Shape);
150 // processing each solid
151 TopExp_Explorer exps;
152 for(exps.Init(Shape, TopAbs_SOLID); exps.More(); exps.Next()) {
153 TopoDS_Solid aSolid = TopoDS::Solid(exps.Current());
155 // creating map of edge faces
156 TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
157 TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
159 // map of processed shapes
160 TopTools_MapOfShape aProcessed;
162 Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
164 Standard_Integer NbModif=0;
165 Standard_Boolean hasFailed = Standard_False;
166 Standard_Real tol = Min(Max(Precision::Confusion(), myTolerance/10.),0.1);
167 // processing each face
169 //for( exp.Init(Shape, TopAbs_FACE); exp.More(); exp.Next()) {
170 for( exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) {
171 TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
173 if(aProcessed.Contains(aFace))
176 Standard_Integer dummy;
177 TopTools_SequenceOfShape edges;
178 AddOrdinaryEdges(edges,aFace,dummy);
180 TopTools_SequenceOfShape faces;
183 //surface and location to construct result
184 TopLoc_Location aBaseLocation;
185 Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
186 aBaseSurface = ClearRts(aBaseSurface);
188 // find adjacent faces to union
190 for( i = 1; i <= edges.Length(); i++) {
191 TopoDS_Edge edge = TopoDS::Edge(edges(i));
192 if(BRep_Tool::Degenerated(edge))
195 const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
196 TopTools_ListIteratorOfListOfShape anIter(aList);
197 for( ; anIter.More(); anIter.Next()) {
198 TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD));
199 if(anCheckedFace.IsSame(aFace))
202 if(aProcessed.Contains(anCheckedFace))
205 if(IsSameDomain(aFace,anCheckedFace)) {
207 if(aList.Extent() != 2) {
208 // non mainfold case is not processed
213 TopoDS_Face aMockUpFace;
215 B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.);
216 MovePCurves(aMockUpFace,anCheckedFace);
218 if(AddOrdinaryEdges(edges,aMockUpFace,dummy)) {
219 // sequence edges is modified
223 faces.Append(anCheckedFace);
224 aProcessed.Add(anCheckedFace);
230 // all faces collected in the sequence. Perform union of faces
231 if(faces.Length() > 1) {
235 B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
236 Standard_Integer nbWires = 0;
239 while(edges.Length()>0) {
241 Standard_Boolean isEdge3d = Standard_False;
243 TopTools_MapOfShape aVertices;
247 TopoDS_Edge anEdge = TopoDS::Edge(edges(1));
250 isEdge3d |= !BRep_Tool::Degenerated(anEdge);
253 TopExp::Vertices(anEdge,V1,V2);
257 Standard_Boolean isNewFound = Standard_False;
259 isNewFound = Standard_False;
260 for(Standard_Integer j = 1; j <= edges.Length(); j++) {
261 anEdge = TopoDS::Edge(edges(j));
262 TopExp::Vertices(anEdge,V1,V2);
263 if(aVertices.Contains(V1) || aVertices.Contains(V2)) {
264 isEdge3d |= !BRep_Tool::Degenerated(anEdge);
270 isNewFound = Standard_True;
273 } while (isNewFound);
275 // sorting eny type of edges
276 aWire = TopoDS::Wire(aContext->Apply(aWire));
278 TopoDS_Face tmpF = TopoDS::Face(aContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
279 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
281 Standard_Boolean isDegRemoved = Standard_False;
282 if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
283 // clear degenerated edges if at least one with 3d curve exist
285 Handle(ShapeExtend_WireData) sewd = sfw->WireData();
286 for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) {
287 TopoDS_Edge E = sewd->Edge(j);
288 if(BRep_Tool::Degenerated(E)) {
290 isDegRemoved = Standard_True;
297 sfw->FixDegenerated();
299 TopoDS_Wire aWireFixed = sfw->Wire();
300 aContext->Replace(aWire,aWireFixed);
301 // add resulting wire
303 B.Add(aResult,aWireFixed);
307 Handle(ShapeExtend_WireData) sbwd = sfw->WireData();
308 Standard_Integer nbEdges = sbwd->NbEdges();
309 // sort degenerated edges and create one edge instead of several ones
310 ShapeAnalysis_WireOrder sawo(Standard_False, 0);
311 ShapeAnalysis_Edge sae;
312 Standard_Integer aLastEdge = nbEdges;
313 for(Standard_Integer j = 1; j <= nbEdges; j++) {
315 //smh protection on NULL pcurve
316 Handle(Geom2d_Curve) c2d;
317 if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) {
321 sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
325 // constructind one degenerative edge
326 gp_XY aStart, anEnd, tmp;
327 Standard_Integer nbFirst = sawo.Ordered(1);
328 TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
330 TopoDS_Vertex aDummyV;
331 TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
332 sawo.XY(nbFirst,aStart,tmp);
333 sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
335 gp_XY aVec = anEnd-aStart;
336 Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
338 B.UpdateEdge(E,aLine,tmpF,0.);
339 B.Range(E,tmpF,0.,aVec.Modulus());
340 Handle(Geom_Curve) C3d;
341 B.UpdateEdge(E,C3d,0.);
342 B.Degenerated(E,Standard_True);
351 // perform substitution of face
352 aContext->Replace(aContext->Apply(aFace),aResult);
355 ShapeFix_Face sff (aResult);
356 //Intializing by tolerances
357 sff.SetPrecision(myTolerance);
358 sff.SetMinTolerance(tol);
359 sff.SetMaxTolerance(Max(1.,myTolerance*1000.));
361 sff.FixOrientationMode() = 0;
362 //sff.FixWireMode() = 0;
363 sff.SetContext(aContext);
364 // Applying the fixes
366 if(sff.Status(ShapeExtend_FAIL))
367 hasFailed = Standard_True;
369 // breaking down to several faces
370 TopoDS_Shape theResult = aContext->Apply(aResult);
371 for(TopExp_Explorer aFaceExp(theResult,TopAbs_FACE);aFaceExp.More();aFaceExp.Next()) {
372 TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD));
373 Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
374 grid->SetValue ( 1, 1, aBaseSurface );
375 Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
376 ShapeFix_ComposeShell CompShell;
377 CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision
378 CompShell.SetContext( aContext );
380 TopTools_SequenceOfShape parts;
381 ShapeFix_SequenceOfWireSegment wires;
382 for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
383 Handle(ShapeExtend_WireData) sbwd =
384 new ShapeExtend_WireData ( TopoDS::Wire(W_Exp.Current() ));
385 ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
389 CompShell.DispatchWires ( parts,wires );
390 for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
391 ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
392 aFixOrient.SetContext(aContext);
393 aFixOrient.FixOrientation();
396 TopoDS_Shape CompRes;
397 if ( faces.Length() !=1 ) {
400 for ( i=1; i <= parts.Length(); i++ )
401 B.Add ( S, parts(i) );
404 else CompRes = parts(1);
406 aContext->Replace(aCurrent,CompRes);
409 // remove the remaining faces
410 for(i = 2; i <= faces.Length(); i++)
411 aContext->Remove(faces(i));
415 //TopoDS_Shape aResult = Shape;
417 TopoDS_Shape aResult = aSolid;
419 aResult = aContext->Apply(aSolid);
422 for(exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
423 TopoDS_Edge E = TopoDS::Edge(exp.Current());
424 sfe.FixVertexTolerance (E);
425 // ptv add fix same parameter
426 sfe.FixSameParameter(E, myTolerance);
429 myContext->Replace(aSolid,aResult);
433 for( exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) {
434 TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
435 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
436 sfw->SetContext(myContext);
437 sfw->SetPrecision(myTolerance);
438 sfw->SetMinTolerance(myTolerance);
439 sfw->SetMaxTolerance(Max(1.,myTolerance*1000.));
441 for ( TopoDS_Iterator iter(aFace,Standard_False); iter.More(); iter.Next()) {
442 TopoDS_Wire wire = TopoDS::Wire ( iter.Value() );
450 } // end processing each solid
452 aResShape = myContext->Apply(Shape);
457 //=======================================================================
458 //function : IsSameDomain
460 //=======================================================================
462 Standard_Boolean BlockFix_UnionFaces::IsSameDomain(const TopoDS_Face& aFace,
463 const TopoDS_Face& aCheckedFace) const
465 //checking the same handless
466 TopLoc_Location L1, L2;
467 Handle(Geom_Surface) S1, S2;
469 S1 = BRep_Tool::Surface(aFace,L1);
470 S2 = BRep_Tool::Surface(aCheckedFace,L2);
472 return (S1 == S2 && L1 == L2);
476 //=======================================================================
477 //function : MovePCurves
479 //=======================================================================
481 void BlockFix_UnionFaces::MovePCurves(TopoDS_Face& aTarget,
482 const TopoDS_Face& aSource) const
485 for(TopExp_Explorer wexp(aSource,TopAbs_WIRE);wexp.More();wexp.Next()) {
486 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(wexp.Current()),
487 aTarget, Precision::Confusion());
489 Standard_Boolean isReoredFailed = sfw->StatusReorder ( ShapeExtend_FAIL );
490 sfw->FixEdgeCurves();
495 sfw->FixDegenerated();
497 // remove degenerated edges from not degenerated points
498 ShapeAnalysis_Edge sae;
499 Handle(ShapeExtend_WireData) sewd = sfw->WireData();
500 for(Standard_Integer i = 1; i<=sewd->NbEdges();i++) {
501 TopoDS_Edge E = sewd->Edge(i);
502 if(BRep_Tool::Degenerated(E)&&!sae.HasPCurve(E,aTarget)) {
508 TopoDS_Wire ResWire = sfw->Wire();
509 B.Add(aTarget,ResWire);