]> SALOME platform Git repositories - modules/geom.git/blob - src/PARTITION/Partition_Inter3d.cxx
Salome HOME
NRI : Merge BRANCH_V1_2c
[modules/geom.git] / src / PARTITION / Partition_Inter3d.cxx
1 //  GEOM PARTITION : partition algorithm
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : Partition_Inter3d.cxx
25 //  Author : Benedicte MARTIN
26 //  Module : GEOM
27 //  $Header$
28
29 using namespace std;
30 #include "Partition_Inter2d.hxx"
31 #include "Partition_Inter3d.ixx"
32 #include "utilities.h"
33
34 #include <BRepAlgo_AsDes.hxx>
35 #include <BRepAlgo_Image.hxx>
36 #include <BRepLib.hxx>
37 #include <BRepOffset_Tool.hxx>
38 #include <BRep_Builder.hxx>
39 #include <BRep_Tool.hxx>
40
41 #include <TopExp.hxx>
42 #include <TopExp_Explorer.hxx>
43
44 #include <TopOpeBRepTool_BoxSort.hxx>
45 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
46 #include <TopTools_ListIteratorOfListOfShape.hxx>
47 #include <TopTools_ListOfShape.hxx>
48 #include <TopoDS.hxx>
49 #include <TopoDS_Compound.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopoDS_Face.hxx>
52 #include <TopoDS_Vertex.hxx>
53
54 #ifdef DEB
55 #include <DBRep.hxx>
56 #endif
57
58 #include <BRepLib_MakeVertex.hxx>
59 #include <BRepTools.hxx>
60 #include <Extrema_ExtPS.hxx>
61 #include <Extrema_POnSurf.hxx>
62 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
63 #include <Geom2d_Curve.hxx>
64 #include <GeomAPI_ProjectPointOnCurve.hxx>
65 #include <GeomAdaptor_Surface.hxx>
66 #include <Geom_Curve.hxx>
67 #include <Geom_RectangularTrimmedSurface.hxx>
68 #include <Geom_SphericalSurface.hxx>
69 #include <Geom_Surface.hxx>
70 #include <Geom_ToroidalSurface.hxx>
71 #include <Geom_TrimmedCurve.hxx>
72 #include <Precision.hxx>
73 #include <TColStd_MapOfInteger.hxx>
74 #include <TopOpeBRepBuild_Builder.hxx>
75 #include <TopOpeBRepDS_BuildTool.hxx>
76 #include <TopOpeBRepDS_CurveExplorer.hxx>
77 #include <TopOpeBRepDS_HDataStructure.hxx>
78 #include <TopOpeBRepDS_Interference.hxx>
79 #include <TopOpeBRepDS_PointIterator.hxx>
80 #include <TopOpeBRepDS_Transition.hxx>
81 #include <TopOpeBRepTool_CurveTool.hxx>
82 #include <TopOpeBRepTool_GeomTool.hxx>
83 #include <TopOpeBRepTool_OutCurveType.hxx>
84 #include <TopOpeBRep_DSFiller.hxx>
85 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
86 #include <stdio.h>
87
88 //=======================================================================
89 //function : Partition_Inter3d
90 //purpose  : 
91 //=======================================================================
92
93 Partition_Inter3d::Partition_Inter3d()
94 {
95 }
96 //=======================================================================
97 //function : Partition_Inter3d
98 //purpose  : 
99 //=======================================================================
100
101 Partition_Inter3d::Partition_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes)
102   :myAsDes(AsDes)
103 {
104   mySectionEdgesAD = new BRepAlgo_AsDes;
105 }
106
107 //=======================================================================
108 //function : CompletPart3d
109 //purpose  : FaceShapeMap is just to know the shape a face belongs to
110 //=======================================================================
111
112 void Partition_Inter3d::CompletPart3d(const TopTools_ListOfShape& SetOfFaces1,
113                                       const TopTools_DataMapOfShapeShape& FaceShapeMap)
114 {
115   if (myAsDes.IsNull())
116     myAsDes = new BRepAlgo_AsDes;
117   
118   TopTools_ListIteratorOfListOfShape it;
119
120   //---------------------------------------------------------------
121   // Construction of bounding boxes.
122   //---------------------------------------------------------------
123
124   BRep_Builder B;
125   TopoDS_Compound CompOS;
126   B.MakeCompound(CompOS);
127   for (it.Initialize(SetOfFaces1); it.More(); it.Next())
128     B.Add(CompOS, it.Value());
129     
130   TopOpeBRepTool_BoxSort BOS;
131   BOS.AddBoxesMakeCOB(CompOS,TopAbs_FACE);
132
133   for (it.Initialize(SetOfFaces1); it.More(); it.Next()) {
134     TopoDS_Face F1 = TopoDS::Face(it.Value());
135     
136     // avoid intersecting faces of one shape
137     TopoDS_Shape S1;
138     if (FaceShapeMap.IsBound(F1)) S1 = FaceShapeMap.Find(F1);
139     // avoid intersecting faces sharing vertices, suppose they belong to
140     // shapes sharing same faces
141     TopTools_IndexedMapOfShape VM;
142     TopExp::MapShapes( F1, TopAbs_VERTEX, VM);
143     
144     TColStd_ListIteratorOfListOfInteger itLI = BOS.Compare(F1);
145     for (; itLI.More(); itLI.Next()) {
146       TopoDS_Face F2 = TopoDS::Face(BOS.TouchedShape(itLI));
147       if (F1.IsSame(F2) || IsDone(F1,F2))
148         continue;
149
150       TopoDS_Shape S2;
151       if (FaceShapeMap.IsBound(F2)) S2 = FaceShapeMap.Find(F2);
152       if (!S1.IsNull() && S1.IsSame(S2))
153         continue; // descendants of one shape
154
155       TopExp_Explorer expV (F2, TopAbs_VERTEX);
156       for ( ; expV.More(); expV.Next())
157         if (VM.Contains( expV.Current() ))
158           break;
159       if (expV.More())
160         continue; // faces have a common edge
161       
162       F1.Orientation(TopAbs_FORWARD);
163       F2.Orientation(TopAbs_FORWARD);
164       FacesPartition(F1,F2);      
165     }
166
167     // mark as modified a face which has at least one new edge
168     if (!myAsDes->HasDescendant( F1 ))
169       continue;
170     TopTools_ListIteratorOfListOfShape itE (myAsDes->Descendant( F1 ));
171     for ( ; itE.More(); itE.Next()) {
172       if (myNewEdges.Contains( itE.Value())) {
173         myTouched.Add( F1 );
174         break;
175       }
176     }
177   }
178 }
179
180 //=======================================================================
181 //function : PutInBounds
182 //purpose  : 
183 //=======================================================================
184
185 static void PutInBounds (const TopoDS_Face&          F,
186                          const TopoDS_Edge&          E,
187                          Handle(Geom2d_Curve)&       C2d)
188 {
189   Standard_Real   umin,umax,vmin,vmax;
190   Standard_Real   f,l;
191   BRep_Tool::Range(E,f,l);
192
193   TopLoc_Location L; // Recup S avec la location pour eviter la copie.
194   Handle (Geom_Surface) S   = BRep_Tool::Surface(F,L);
195
196   if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
197     S = (*(Handle_Geom_RectangularTrimmedSurface*)&S)->BasisSurface();
198   }
199   if (!S->IsUPeriodic() && !S->IsVPeriodic())
200     return;
201
202   BRepTools::UVBounds(F,umin,umax,vmin,vmax);
203
204   gp_Pnt2d Pf = C2d->Value(f);
205   gp_Pnt2d Pl = C2d->Value(l);
206   const Standard_Real Um = 0.34*f + 0.66*l;
207   gp_Pnt2d Pm = C2d->Value( Um );
208
209   // sometimes on shpere, pcurve is out of domain by V though S is
210   // UPeriodic, sometimes it is in domain but nontheless it has
211   // wrong position.
212   // Check pcurve position by 3D point
213   if (S->IsKind(STANDARD_TYPE( Geom_SphericalSurface )) ||
214       S->IsKind(STANDARD_TYPE( Geom_ToroidalSurface )))
215   {
216     // get point on the surface
217     gp_Pnt Ps = S->Value( Pm.X(), Pm.Y() );
218     // get point on the edge
219     Handle(Geom_Curve) C = BRep_Tool::Curve( E, f, l );
220     gp_Pnt Pc = C->Value( Um );
221     // compare points
222     Standard_Real TolE = BRep_Tool::Tolerance( E );
223     if ( Pc.SquareDistance( Ps ) * 0.95 < TolE * TolE )
224       return; // OK
225
226     // find good UV for Pc: project Pc on S
227     GeomAdaptor_Surface  SA (S);
228     Extrema_ExtPS anExtPS (Pc, SA,
229                            SA.UResolution( TolE ), SA.VResolution( TolE ));
230     if (anExtPS.IsDone())
231     {
232       Standard_Integer i, nbExt = anExtPS.NbExt();
233       Extrema_POnSurf aPOnSurf;
234       for (i = 1; i <= nbExt; ++i )
235         if (anExtPS.Value( i ) <= TolE) {
236           aPOnSurf = anExtPS.Point( i );
237           break;
238         }
239       if (i <= nbExt) {
240         // a point found
241         Standard_Real u, v;
242         aPOnSurf.Parameter( u, v );
243         gp_Pnt2d aGoodPm ( u, v );
244         C2d->Translate( Pm , aGoodPm );
245       }
246     }
247   }
248
249   //---------------
250   // Recadre en U.
251   //---------------
252   if (S->IsUPeriodic()) {
253     Standard_Real period  = S->UPeriod();
254     Standard_Real eps     = period*1.e-6;
255     Standard_Real minC    = Min(Pf.X(),Pl.X()); minC = Min(minC,Pm.X());
256     Standard_Real maxC    = Max(Pf.X(),Pl.X()); maxC = Max(maxC,Pm.X());
257     Standard_Real du = 0.;
258     if (minC< umin - eps) {
259       du = (int((umin - minC)/period) + 1)*period;
260     }
261     if (minC > umax + eps) {
262       du = -(int((minC - umax)/period) + 1)*period;
263     }
264     if (du != 0) {
265       gp_Vec2d T1(du,0.);
266       C2d->Translate(T1);
267       minC += du; maxC += du;
268     }
269     // Ajuste au mieux la courbe dans le domaine.
270     if (maxC > umax +100*eps) {
271       Standard_Real d1 = maxC - umax;
272       Standard_Real d2 = umin - minC + period;
273       if (d2 < d1) du =-period;
274       if ( du != 0.) {
275         gp_Vec2d T2(du,0.);
276         C2d->Translate(T2);
277       }
278     }
279   }
280   //------------------
281   // Recadre en V.
282   //------------------
283   if (S->IsVPeriodic()) {
284     Standard_Real period  = S->VPeriod();
285     Standard_Real eps     = period*1.e-6;
286     Standard_Real minC    = Min(Pf.Y(),Pl.Y()); minC = Min(minC,Pm.Y());
287     Standard_Real maxC    = Max(Pf.Y(),Pl.Y()); maxC = Max(maxC,Pm.Y());
288     Standard_Real dv = 0.;
289     if (minC< vmin - eps) {
290       dv = (int((vmin - minC)/period) + 1)*period;
291     }
292     if (minC > vmax + eps) {
293       dv = -(int((minC - vmax)/period) + 1)*period;
294     }
295     if (dv != 0) {
296       gp_Vec2d T1(0.,dv);
297       C2d->Translate(T1);
298       minC += dv; maxC += dv;
299     }
300     // Ajuste au mieux la courbe dans le domaine.
301     if (maxC > vmax +100*eps) {
302       Standard_Real d1 = maxC - vmax;
303       Standard_Real d2 = vmin - minC + period;
304       if (d2 < d1) dv =-period;
305       if ( dv != 0.) {
306         gp_Vec2d T2(0.,dv);
307         C2d->Translate(T2);
308       }
309     }
310   }
311 }
312
313 //=======================================================================
314 //function : Inter3D
315 //purpose  : 
316 //=======================================================================
317
318 void Partition_Inter3d::Inter3D(const TopoDS_Face& F1,
319                                 const TopoDS_Face& F2,
320                                 TopTools_ListOfShape& L)
321 {
322   BRep_Builder B;
323   
324   // fill the data Structure
325   Handle(TopOpeBRepDS_HDataStructure) DatStr = new TopOpeBRepDS_HDataStructure();
326   TopOpeBRep_DSFiller DSFiller;
327   DSFiller.Insert(F1,F2,DatStr);
328
329   // define the GeomTool used by the DSFiller :
330   // compute BSpline of degree 1 on intersection curves.
331   Standard_Real tol3dAPPROX = 1e-7;
332   Standard_Real tol2dAPPROX = 1e-7;
333   TopOpeBRepTool_GeomTool GT2 (TopOpeBRepTool_APPROX);  
334   GT2.SetTolerances(tol3dAPPROX,tol2dAPPROX);
335   TopOpeBRepDS_BuildTool  BT(GT2);
336
337   // Perform Section
338   TopOpeBRepBuild_Builder TopB(BT);
339   TopB.Perform(DatStr);
340
341   // ===============
342   // Store new edges
343   // ===============
344   
345   L.Clear();
346   TopOpeBRepDS_CurveExplorer cex(DatStr->DS());
347   for (; cex.More(); cex.Next()) {
348     const TopOpeBRepDS_Curve& CDS = cex.Curve();
349     Standard_Integer ic = cex.Index();
350     Handle(Geom2d_Curve) pc1 = CDS.Curve1();
351     Handle(Geom2d_Curve) pc2 = CDS.Curve2();
352     
353     TopTools_ListIteratorOfListOfShape itLE = TopB.NewEdges(ic);
354     while (itLE.More()) {
355       TopoDS_Edge E = TopoDS::Edge(itLE.Value());
356       
357       PutInBounds (F1,E,pc1);
358       PutInBounds (F2,E,pc2);
359       
360       B.UpdateEdge (E,pc1,F1,0.);
361       B.UpdateEdge (E,pc2,F2,0.);
362       
363       L.Append (E);
364       
365       itLE.Next();
366       if (itLE.More()) {
367         pc1 = Handle(Geom2d_Curve)::DownCast(pc1->Copy());
368         pc2 = Handle(Geom2d_Curve)::DownCast(pc2->Copy());
369       }
370     }
371   }
372
373   // ========================
374   // store same domain faces 
375   // ========================
376
377
378   if ( DatStr->HasSameDomain( F1 ))
379   {
380     TopTools_ListOfShape emptyList;
381     if (!mySameDomainFM.IsBound(F1))
382       mySameDomainFM.Bind(F1,emptyList);
383     if (!mySameDomainFM.IsBound(F2))
384       mySameDomainFM.Bind(F2,emptyList);
385     mySameDomainFM(F1).Append(F2);
386     mySameDomainFM(F2).Append(F1);
387   }
388
389   // ====================
390   // Store section edges
391   // ====================
392
393   const TopOpeBRepDS_DataStructure& DS = DatStr->DS();
394   Standard_Integer j,i,nse = DS.NbSectionEdges();
395   if (nse == 0) return;
396
397     
398   TopoDS_Vertex V, sdeV1, sdeV2;
399   TopTools_MapOfShape MV;
400   TopTools_ListOfShape LSE; // list of section edges
401   TopoDS_Face dummyF;
402   
403   for (i = 1; i <= nse; i++)
404   {
405     const TopoDS_Edge & se = DS.SectionEdge(i);
406     if (! TopB.IsSplit(se,TopAbs_ON))
407       continue;
408     LSE.Append( se );
409
410     // add vertices where section edges interferes with other
411     // edges as its descendant in myAsDes
412     
413     TopoDS_Edge sde, oe; // same domain, other edge
414     if (DatStr->HasSameDomain(se)) {
415       sde = TopoDS::Edge( DatStr->SameDomain(se).Value() );
416       TopExp::Vertices( sde, sdeV1, sdeV2);
417     }
418     TColStd_MapOfInteger MIV; // indices of added edges
419     TopOpeBRepDS_PointIterator itP (DS.ShapeInterferences( se ));
420     itP.SupportKind( TopOpeBRepDS_EDGE );
421     // loop on intersections of se
422     for (; itP.More(); itP.Next()) {
423       oe = TopoDS::Edge( DS.Shape( itP.Support()));
424       if (itP.IsVertex()) {
425         // there is a vertex at intersection
426         if ( !MIV.Add( itP.Current() ))
427           continue;
428         V = TopoDS::Vertex( DS.Shape( itP.Current()));
429         if ( !sde.IsNull() && (V.IsSame(sdeV1) || V.IsSame(sdeV2)) )
430           oe = sde;
431         V = ReplaceSameDomainV( V , oe );
432         V.Orientation( TopAbs_INTERNAL);
433         B.UpdateVertex( V, itP.Parameter(), se, 0.); // AddVonE() sets real U
434       }
435       else {
436         // create a new vertex at the intersection point
437         const TopOpeBRepDS_Point& DSP = DS.Point( itP.Current());
438         V = BRepLib_MakeVertex( DSP.Point() );
439         V.Orientation( TopAbs_INTERNAL);
440         B.UpdateVertex( V, itP.Parameter(), se, DSP.Tolerance());
441         // make V be on the other edge
442         TopOpeBRepDS_PointIterator itOP (DS.ShapeInterferences( oe ));
443         for (; itOP.More(); itOP.Next()) {
444           const TopOpeBRepDS_Point& ODSP = DS.Point( itOP.Current());
445           if ( DSP.IsEqual (ODSP)) {
446             B.UpdateVertex( V, itOP.Parameter(), TopoDS::Edge(oe), ODSP.Tolerance());
447             break;
448           }
449         }
450       }
451       // add V on the both intersecting edges
452       TopoDS_Vertex addedV = Partition_Inter2d::AddVonE( V,se,oe,myAsDes,dummyF);
453       if (!addedV.IsSame( V ))
454         mySameDomainVM.Bind (V, addedV); // equal vertex is already there
455
456       MV.Add( addedV ); // to ease storage of vertices of ON splits
457     }
458   }
459
460   // add section edge to the face it intersects and find
461   // splits ON that do not have same domain pair
462   
463   TopB.SplitSectionEdges(); // let TopB find ON splits
464
465   TopTools_MapOfShape SPM; // map of ON splits
466   TopTools_IndexedMapOfShape ME[2];
467   TopExp::MapShapes( F1, TopAbs_EDGE, ME[1]);
468   TopExp::MapShapes( F2, TopAbs_EDGE, ME[0]);
469
470   TopTools_ListIteratorOfListOfShape itSP, itLSE (LSE);
471   while ( itLSE.More() ) {
472
473     TopoDS_Edge se = TopoDS::Edge( itLSE.Value() );
474
475     Standard_Integer ancRank = DS.AncestorRank(se);
476     if (ME[ancRank-1].Contains( se ))
477       LSE.Remove( itLSE ); // se is an edge of face it intersects
478     else
479       itLSE.Next();
480
481     const TopoDS_Face& F = (ancRank == 1) ? F2 : F1;
482
483     // add se to face but dont add twice
484     TopTools_ListIteratorOfListOfShape itE( myAsDes->Descendant( F ));
485     if (myAsDes->HasDescendant( F )) {
486       for ( ; itE.More(); itE.Next())
487         if (se.IsSame( itE.Value() ))
488           break;
489     }
490     if (!itE.More())
491     {
492       myAsDes->Add( F, se );
493
494       // check se pcurve on F
495       Standard_Real tol, f,l, umin=1e100, umax=-1e100;
496       Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( se, F, f,l);
497       if (pc.IsNull()) {
498         itSP.Initialize( TopB.Splits(se,TopAbs_ON) );
499         for ( ; itSP.More(); itSP.Next()) {
500           const TopoDS_Edge& E = TopoDS::Edge ( itSP.Value());
501           BRep_Tool::Range(E, f, l);
502           umin = Min( umin, f);
503           umax = Max( umax, l);
504         }
505         Handle(Geom_Curve) C3d = BRep_Tool::Curve( se, f, l);
506         if (umin < umax) // sometimes umin == umax for closed edge
507           C3d = new Geom_TrimmedCurve( C3d, umin, umax);
508         pc = TopOpeBRepTool_CurveTool::MakePCurveOnFace (F,C3d,tol);
509         if (pc.IsNull()) {
510           MESSAGE (" CANT BUILD PCURVE ");
511         }
512         B.UpdateEdge( se, pc, F, tol);
513       }
514     }
515
516     // to detect splits that do not have same domain pair
517     // ie which split a face into parts and not pass by its boundary
518     itSP.Initialize( TopB.Splits(se,TopAbs_ON) );
519     for ( ; itSP.More(); itSP.Next()) {
520       const TopoDS_Shape& SP = itSP.Value();
521       if (!SPM.Add( SP ))
522         SPM.Remove( SP );
523     }
524   }
525
526   // store vertices of ON splits and bind section edges to faces
527   
528   for (itLSE.Initialize (LSE); itLSE.More(); itLSE.Next())
529   {
530     const TopoDS_Shape& se = itLSE.Value();
531
532     Standard_Integer ancRank = DS.AncestorRank(se);
533     TopoDS_Face F = (ancRank == 1) ? F2 : F1;
534
535     // add vertices of ON splits which have no same domain pair
536     Standard_Boolean added = Standard_False;
537     itSP.Initialize( TopB.Splits(se,TopAbs_ON) );
538     for ( ; itSP.More(); itSP.Next())
539     {
540       if (!SPM.Contains( itSP.Value() ))
541         continue;
542       
543       const TopoDS_Edge& S = TopoDS::Edge ( itSP.Value());
544
545       added = Standard_True;
546       mySectionEdgesAD->Add( F, se );
547       
548       TopoDS_Vertex VS[2];
549       TopExp::Vertices (S, VS[0], VS[1]);
550       for (j=0; j<2; ++j)
551       {
552         if (mySameDomainVM.IsBound( VS[j] ))
553           VS[j] = TopoDS::Vertex( mySameDomainVM( VS[j] ));
554         if ( !MV.Contains( VS[j] )) {
555           // find equal vertex on se - point interference
556           gp_Pnt P1 = BRep_Tool::Pnt( VS[j] );
557           TopTools_ListIteratorOfListOfShape itV( myAsDes->Descendant(se) );
558           for (; itV.More(); itV.Next()) {
559             V = TopoDS::Vertex( itV.Value() );
560             if ( V.IsSame( VS[j] ))
561               break;
562             gp_Pnt P2 = BRep_Tool::Pnt( V );
563             if (P1.IsEqual( P2, Precision::Confusion())) {
564               mySameDomainVM.Bind (VS[j], V);
565               VS[j] = V;
566               break;
567             }
568           }
569           if (!itV.More())  // no interferences with edges
570             myAsDes->Add( se, VS[j]);
571         }
572
573         // add ends of ON splits to F in order to detect later
574         // if a split is on face in IsSplitOn()
575         mySectionEdgesAD->Add( F, VS[j]);
576       }
577       // in the descendants of F, first go ends of an ON split and
578       // then a split itself
579       mySectionEdgesAD->Add( F, S );
580     }
581     if (!added)
582       mySectionEdgesAD->Add( F, se );
583     
584     myNewEdges.Add( se );
585   }
586 }
587
588 //=======================================================================
589 //function : FacesPartition
590 //purpose  : 
591 //=======================================================================
592
593 void Partition_Inter3d::FacesPartition(const TopoDS_Face& F1,
594                                        const TopoDS_Face& F2)
595      //(const TopTools_DataMapOfShapeListOfShape& /*SetOfFaces2*/)
596 {
597   TopTools_ListOfShape LInt;
598
599   Inter3D (F1,F2,LInt);
600   
601   StorePart3d (F1,F2,LInt);
602 }
603
604 //=======================================================================
605 //function : SetDone
606 //purpose  : 
607 //=======================================================================
608
609 void Partition_Inter3d::SetDone(const TopoDS_Face& F1, 
610                                 const TopoDS_Face& F2)
611 {
612   if (!myDone.IsBound(F1)) {
613     TopTools_ListOfShape emptyList;
614     myDone.Bind(F1,emptyList);
615   }
616   myDone(F1).Append(F2);
617   if (!myDone.IsBound(F2)) {
618     TopTools_ListOfShape emptyList;
619     myDone.Bind(F2,emptyList);
620   }
621   myDone(F2).Append(F1);
622 }
623
624 //=======================================================================
625 //function : IsDone
626 //purpose  : 
627 //=======================================================================
628
629 Standard_Boolean Partition_Inter3d::IsDone(const TopoDS_Face& F1, 
630                                            const TopoDS_Face& F2) 
631
632   const 
633 {
634   if (myDone.IsBound(F1)) {
635     TopTools_ListIteratorOfListOfShape it (myDone(F1));
636     for (; it.More(); it.Next()) {
637       if (it.Value().IsSame(F2)) return Standard_True;
638     }
639   }
640   return Standard_False;
641 }
642
643 //=======================================================================
644 //function : StorePart3d
645 //purpose  : 
646 //=======================================================================
647
648 void Partition_Inter3d::StorePart3d(const TopoDS_Face& F1, 
649                                     const TopoDS_Face& F2, 
650                                     const TopTools_ListOfShape& LInt)
651 {
652   if (!LInt.IsEmpty()) {
653     myAsDes->Add( F1,LInt);
654     myAsDes->Add( F2,LInt);
655
656     TopTools_ListIteratorOfListOfShape it(LInt);
657     for (; it.More(); it.Next()) {
658
659       TopoDS_Edge E = TopoDS::Edge(it.Value());
660
661       BRep_Builder B;
662       B.SameParameter(E,Standard_False);
663       BRepLib::SameParameter(E,1.0e-7);
664       
665       myNewEdges.Add(E);
666     }
667   }
668   SetDone(F1,F2);
669 }
670
671 //=======================================================================
672 //function : TouchedFaces
673 //purpose  : 
674 //=======================================================================
675
676 TopTools_MapOfShape& Partition_Inter3d::TouchedFaces()
677 {
678   return myTouched;
679 }
680
681 //=======================================================================
682 //function : AsDes
683 //purpose  : 
684 //=======================================================================
685
686 Handle(BRepAlgo_AsDes) Partition_Inter3d::AsDes() const 
687 {
688   return myAsDes;
689 }
690
691 //=======================================================================
692 //function : NewEdges
693 //purpose  : 
694 //=======================================================================
695
696 TopTools_MapOfShape& Partition_Inter3d::NewEdges() 
697 {
698   return myNewEdges;
699 }
700
701 //=======================================================================
702 //function : Affiche
703 //purpose  : 
704 //=======================================================================
705
706 void Partition_Inter3d::Affiche(const TopTools_ListOfShape& SetOfFaces) const
707 {
708 #ifdef DEB
709   char PSection[1024];
710   char *section=PSection;
711   Standard_Integer i = 0;
712   Standard_Real j=1;
713   TopTools_ListOfShape aList;
714   TopTools_ListIteratorOfListOfShape it;
715   for (it.Initialize(SetOfFaces); it.More(); it.Next()) {
716     const TopoDS_Shape& OS = it.Value();
717     aList=myAsDes->Descendant(OS);
718     MESSAGE ( " the number of items stored in the list " << j << " :  " << aList.Extent() )
719     j++;
720     TopTools_ListIteratorOfListOfShape itaList;
721     for (itaList.Initialize(aList); itaList.More(); itaList.Next()) {
722       const TopoDS_Shape& SS = itaList.Value();
723       i++;
724       sprintf(PSection,"section_%d",i);
725       DBRep::Set(section,SS);  
726     }
727   }
728 #endif
729 }
730
731 //=======================================================================
732 //function : SameDomain
733 //purpose  : 
734 //=======================================================================
735
736 const TopTools_ListOfShape& Partition_Inter3d::SameDomain(const TopoDS_Face& F) const
737 {
738   if (mySameDomainFM.IsBound( F ))
739     return mySameDomainFM (F);
740
741   static TopTools_ListOfShape emptyList;
742   return emptyList;
743 }
744
745 //=======================================================================
746 //function : HasSameDomainF
747 //purpose  : Return true if F has same domain faces
748 //=======================================================================
749
750 Standard_Boolean Partition_Inter3d::HasSameDomainF(const TopoDS_Shape& F) const
751 {
752   return mySameDomainFM.IsBound( F );
753 }
754
755 //=======================================================================
756 //function : IsSameDomain
757 //purpose  : Return true if F1 and F2 are same domain faces
758 //=======================================================================
759
760 Standard_Boolean Partition_Inter3d::IsSameDomainF(const TopoDS_Shape& F1,
761                                                  const TopoDS_Shape& F2) const
762 {
763   if (mySameDomainFM.IsBound( F1 )) {
764     TopTools_ListIteratorOfListOfShape it (mySameDomainFM( F1 ));
765     for (; it.More(); it.Next()) 
766       if (F2.IsSame( it.Value()))
767         return Standard_True;
768   }
769   return F1.IsSame( F2 );
770 }
771
772 //=======================================================================
773 //function : ReplaceSameDomainV
774 //purpose  : return same domain vertex of  V if it was replaced
775 //           and make this vertex to be on E too, else return V
776 //=======================================================================
777
778 TopoDS_Vertex Partition_Inter3d::ReplaceSameDomainV(const TopoDS_Vertex& V,
779                                                     const TopoDS_Edge&   E) const
780 {
781   TopoDS_Vertex SDV = V;
782   if (mySameDomainVM.IsBound( V )) {
783
784     TopoDS_Vertex V1,V2;
785     TopExp::Vertices(E,V1,V2);
786     Standard_Boolean isClosed = V1.IsSame( V2 ) && V.IsSame(V1);
787
788     SDV = TopoDS::Vertex( mySameDomainVM(V) );
789     Standard_Real tol = BRep_Tool::Tolerance( V );
790     BRep_Builder B;
791     SDV.Orientation( V.Orientation());
792
793     if (isClosed) {
794       Standard_Real f, l;
795       BRep_Tool::Range (E, f, l);
796       Standard_Boolean isFirst = IsEqual( BRep_Tool::Parameter(V,E), f );
797       B.UpdateVertex(SDV, (isFirst ? f : l), E, tol);
798       SDV.Reverse();
799       B.UpdateVertex(SDV, (isFirst ? l : f), E, tol);
800     }
801     else
802       B.UpdateVertex (SDV, BRep_Tool::Parameter(V,E), E, tol);
803       
804   }
805   return SDV;
806 }
807
808 //=======================================================================
809 //function : SectionEdgesAD
810 //purpose  : 
811 //=======================================================================
812
813 Handle(BRepAlgo_AsDes) Partition_Inter3d::SectionEdgesAD() const
814 {
815   return mySectionEdgesAD;
816 }
817
818 //=======================================================================
819 //function : IsSectionEdge
820 //purpose  : return True if  E  is  an  edge  of  a face and it
821 //           intersects an other face
822 //=======================================================================
823
824 Standard_Boolean
825   Partition_Inter3d::IsSectionEdge(const TopoDS_Edge& E) const
826 {
827   return mySectionEdgesAD->HasAscendant(E);
828 }
829
830 //=======================================================================
831 //function : HasSectionEdge
832 //purpose  : return True if an  edge  of  F intersects an other
833 //           face or F is intersected by edge of an other face
834 //=======================================================================
835
836 Standard_Boolean
837   Partition_Inter3d::HasSectionEdge(const TopoDS_Face& F) const
838 {
839   return mySectionEdgesAD->HasDescendant(F);
840 }
841
842 //=======================================================================
843 //function : IsSplitOn
844 //purpose  : return True if NewE is split of OldE on F
845 //=======================================================================
846
847 Standard_Boolean
848   Partition_Inter3d::IsSplitOn(const TopoDS_Edge& NewE,
849                                const TopoDS_Edge& OldE,
850                                const TopoDS_Face& F) const
851 {
852   if (! mySectionEdgesAD->HasDescendant(F))
853     return Standard_False;
854
855   TopTools_ListIteratorOfListOfShape itE ( mySectionEdgesAD->Descendant(F) );
856   for ( ; itE.More(); itE.Next()) {
857     if ( itE.Value().ShapeType() != TopAbs_EDGE ||
858         ! OldE.IsSame ( itE.Value() ))
859       continue;
860     // an edge encountered, its vertices and a split come next
861     itE.Next();
862     if (!itE.More()) break;
863     const TopoDS_Shape& V3 = itE.Value();
864     if (V3.ShapeType() != TopAbs_VERTEX) continue;
865     itE.Next();
866     if (!itE.More()) break;
867     const TopoDS_Shape& V4 = itE.Value();
868     if (V4.ShapeType() != TopAbs_VERTEX) continue;
869
870     TopoDS_Vertex V1, V2;
871     TopExp::Vertices( OldE, V1, V2);
872     
873     if ( V1.IsSame(V2) &&
874         (V1.IsSame(V3) || V1.IsSame(V4)) ) {
875       // closed old edge; use the split for the test 
876       itE.Next();
877       if (!itE.More()) break;
878       const TopoDS_Edge& split = TopoDS::Edge( itE.Value() );
879       // check distance at middle point of NewE
880       Standard_Real f1,l1, f2,l2;
881       Handle(Geom2d_Curve) PC1 = BRep_Tool::CurveOnSurface( split, F ,f1,l1);
882       if (!PC1.IsNull()) {
883         Handle(Geom2d_Curve) PC2 = BRep_Tool::CurveOnSurface(NewE, F ,f2,l2);
884         gp_Pnt2d P = PC2->Value( 0.5*(f2+l2) );
885         Geom2dAPI_ProjectPointOnCurve proj (P, PC1, f1, l1);
886         if (proj.NbPoints() &&
887             proj.LowerDistance() <= Precision::Confusion())
888           return Standard_True;
889       }
890       else {
891         Handle(Geom_Curve) C1 = BRep_Tool::Curve( split ,f1,l1);
892         Handle(Geom_Curve) C2 = BRep_Tool::Curve( NewE  ,f2,l2);
893         gp_Pnt P = C2->Value( 0.5*(f2+l2) );
894         GeomAPI_ProjectPointOnCurve proj (P, C1, f1, l1);
895         if (proj.NbPoints() &&
896             proj.LowerDistance() <= Precision::Confusion())
897           return Standard_True;
898       }
899     }
900     else {
901       Standard_Real u3 = BRep_Tool::Parameter( TopoDS::Vertex(V3), OldE);
902       Standard_Real u4 = BRep_Tool::Parameter( TopoDS::Vertex(V4), OldE);
903
904       Standard_Real f,l, u;
905       BRep_Tool::Range( NewE, f,l);
906       u = 0.5*(f+l);
907       f = Min(u3,u4);
908       l = Max(u3,u4);
909
910       if (u <= l && u >= f)
911         return Standard_True;
912     }
913   }
914   return Standard_False;
915 }
916
917 //=======================================================================
918 //function : SectionEdgeFaces
919 //purpose  : return faces cut by section edge
920 //=======================================================================
921
922 const TopTools_ListOfShape&
923   Partition_Inter3d::SectionEdgeFaces(const TopoDS_Edge& SecE) const
924 {
925   return mySectionEdgesAD->Ascendant( SecE );
926 }