1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14 
15 // Robert Boehne 30 May 2000 : Dec Osf
16 
17 #include <BRep_Builder.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepAdaptor_Curve.hxx>
20 #include <TopExp_Explorer.hxx>
21 #include <TopoDS.hxx>
22 #include <TopOpeBRepDS_CurvePointInterference.hxx>
23 #include <TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State.hxx>
24 #include <TopOpeBRepDS_define.hxx>
25 #include <TopOpeBRepDS_FaceInterferenceTool.hxx>
26 #include <TopOpeBRepDS_FIR.hxx>
27 #include <TopOpeBRepDS_HDataStructure.hxx>
28 #include <TopOpeBRepDS_ListOfShapeOn1State.hxx>
29 #include <TopOpeBRepDS_MapOfShapeData.hxx>
30 #include <TopOpeBRepDS_ProcessInterferencesTool.hxx>
31 #include <TopOpeBRepDS_ShapeData.hxx>
32 #include <TopOpeBRepDS_ShapeShapeInterference.hxx>
33 #include <TopOpeBRepTool_EXPORT.hxx>
34 #include <TopOpeBRepTool_SC.hxx>
35 
36 #define MDSke TopOpeBRepDS_EDGE
37 #define MDSkf TopOpeBRepDS_FACE
38 
39 Standard_EXPORT Standard_Boolean FUN_Parameters(const gp_Pnt& Pnt,const TopoDS_Shape& F,Standard_Real& u,Standard_Real& v);
40 Standard_EXPORT Standard_Boolean FUN_edgeofface(const TopoDS_Shape& E,const TopoDS_Shape& F);
41 
42 //------------------------------------------------------
FUN_isPonF(const TopOpeBRepDS_ListOfInterference & LIF,const gp_Pnt & P,const TopOpeBRepDS_DataStructure & BDS,const TopoDS_Edge & E)43 Standard_Boolean FUN_isPonF(const TopOpeBRepDS_ListOfInterference& LIF,const gp_Pnt& P,const TopOpeBRepDS_DataStructure& BDS,const TopoDS_Edge& E)
44 {
45   Standard_Boolean Pok = Standard_True;
46   TopOpeBRepDS_Kind GT1,ST1; Standard_Integer G1,S1;
47 
48   TopOpeBRepDS_ListIteratorOfListOfInterference itF(LIF);
49   for (;itF.More();itF.Next()) {
50     Handle(TopOpeBRepDS_Interference)& IF = itF.Value(); FDS_data(IF,GT1,G1,ST1,S1);
51     const TopoDS_Face& F = TopoDS::Face(BDS.Shape(S1));
52     TopAbs_Orientation oEinF; Standard_Boolean edonfa = FUN_tool_orientEinFFORWARD(E,F,oEinF );
53     if ( edonfa ) Pok = Standard_True;
54     else {
55       // P est NOK pour une face de LIF : arret
56       Standard_Real u,v; Pok = FUN_Parameters(P,F,u,v);
57       if (!Pok) break;
58     }
59   }
60   return Pok;
61 }
62 
63 //------------------------------------------------------
FUN_findPonF(const TopoDS_Edge & E,const TopOpeBRepDS_DataStructure & BDS,const TopOpeBRepDS_ListOfInterference & LIF,gp_Pnt & P,Standard_Real & par)64 Standard_Boolean FUN_findPonF(const TopoDS_Edge& E,const TopOpeBRepDS_DataStructure& BDS, const TopOpeBRepDS_ListOfInterference& LIF,gp_Pnt& P,Standard_Real& par)
65 {
66   Standard_Boolean Pok = Standard_False;
67   BRepAdaptor_Curve BAC(E);
68   const TopOpeBRepDS_ListOfInterference& LIE = BDS.ShapeInterferences(E);
69   TopOpeBRepDS_ListIteratorOfListOfInterference itI; itI.Initialize(LIE);
70 
71   if ( !itI.More() ) {
72     Pok = FUN_tool_findPinBAC(BAC,P,par);
73     Pok = FUN_isPonF(LIF,P,BDS,E);
74     return Pok;
75   }
76 
77   TopOpeBRepDS_Kind GT1,ST1;Standard_Integer G1,S1;
78   for (;itI.More();itI.Next()) {
79     Standard_Boolean pardef = Standard_False;
80 
81     Handle(TopOpeBRepDS_Interference)& I = itI.Value(); FDS_data(I,GT1,G1,ST1,S1);
82     Handle(TopOpeBRepDS_CurvePointInterference) CPI (Handle(TopOpeBRepDS_CurvePointInterference)::DownCast(I));
83     Handle(TopOpeBRepDS_ShapeShapeInterference) SSI (Handle(TopOpeBRepDS_ShapeShapeInterference)::DownCast(I));
84     if      (!CPI.IsNull()) {
85       par = CPI->Parameter(); pardef = Standard_True;
86     }
87     else if (!SSI.IsNull()) {
88       Standard_Boolean gb = SSI->GBound();
89       if (gb) {
90 	const TopoDS_Vertex& V = TopoDS::Vertex(BDS.Shape(G1));
91 	P = BRep_Tool::Pnt(V); par = BRep_Tool::Parameter(V,E); pardef = Standard_True;
92       }
93       else {
94 	pardef = Standard_False;
95 	if      (GT1 == TopOpeBRepDS_POINT)  P = BDS.Point(G1).Point();
96 	else if (GT1 == TopOpeBRepDS_VERTEX) P = BRep_Tool::Pnt(TopoDS::Vertex(BDS.Shape(G1)));
97 	if (pardef) {
98 	  Standard_Real dist; pardef = FUN_tool_projPonC(P,BAC,par,dist);
99 	}
100       }
101     }
102     else {
103       continue;
104     }
105 
106     if (!pardef) {
107       continue;
108     }
109 
110     BAC.D0(par,P);
111     Pok = FUN_isPonF(LIF,P,BDS,E);
112     // P est OK pour toutes les faces de LIF : on arrete de chercher
113     if (Pok) {
114       break;
115     }
116   }
117   return Pok;
118 }
119 
120 // --------------------------------------------------------
FDS_ADDEDGE(const Standard_Boolean,const TCollection_AsciiString &,const Standard_Integer,TopOpeBRepDS_FaceInterferenceTool & FITool,const TopoDS_Shape & FI,const TopoDS_Shape & F,const TopoDS_Shape & Ecpx,const Standard_Boolean isEGsp,const Handle (TopOpeBRepDS_Interference)& I)121 static void FDS_ADDEDGE (const Standard_Boolean
122  , const TCollection_AsciiString&
123  , const Standard_Integer
124  ,TopOpeBRepDS_FaceInterferenceTool& FITool
125  ,const TopoDS_Shape& FI
126  ,const TopoDS_Shape& F
127  ,const TopoDS_Shape& Ecpx
128  ,const Standard_Boolean isEGsp
129  ,const Handle(TopOpeBRepDS_Interference)& I
130 )
131 {
132   FITool.Add(FI,F,Ecpx,isEGsp,I);
133 }
134 
135 //------------------------------------------------------
136 // EGsp = edge splittee de iEG ( Null si iEG n'est pas splittee)
FUN_reduceEDGEgeometry1(TopOpeBRepDS_ListOfInterference & LI,const TopOpeBRepDS_DataStructure & BDS,const Standard_Integer iFI,const Standard_Integer iEG,const TopoDS_Shape & EGsp,const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State &)137 void FUN_reduceEDGEgeometry1
138 (TopOpeBRepDS_ListOfInterference& LI,const TopOpeBRepDS_DataStructure& BDS,const Standard_Integer iFI,const Standard_Integer iEG,const TopoDS_Shape& EGsp,
139 // const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State& MEsp)
140  const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State& )
141 {
142   Standard_Boolean TRCF = Standard_False;
143   TopOpeBRepDS_ListIteratorOfListOfInterference ili(LI); if (!ili.More()) return;
144 
145   // choix de l'arete Ecpx, lieu de resolution de la transition complexe
146   const TopoDS_Face& FI = TopoDS::Face(BDS.Shape(iFI));
147   Standard_Boolean isEGsp = (! EGsp.IsNull());
148   TopoDS_Edge Ecpx;
149   if (isEGsp) Ecpx = TopoDS::Edge(EGsp);
150   else        Ecpx = TopoDS::Edge(BDS.Shape(iEG));
151 
152   TopOpeBRepDS_PDataStructure pbds = (TopOpeBRepDS_PDataStructure)(void*)&BDS;
153   TopOpeBRepDS_FaceInterferenceTool FITool(pbds);
154   gp_Pnt Pok; Standard_Boolean isPok = Standard_False; Standard_Real parPok;
155   if ( LI.Extent() >= 2) {
156     if ( isEGsp ) isPok = FUN_tool_findPinE(Ecpx,Pok,parPok);
157     else          isPok = FUN_findPonF(Ecpx,BDS,LI,Pok,parPok); // NYI pas necessaire
158     if (!isPok) { LI.Clear(); return; }
159     FITool.SetEdgePntPar(Pok,parPok);
160   }
161 
162   // xpu :090498 :
163   //      CTS20205 : sp(e5) = sp(e4 of rank=1) and c3d(e5) c3d(e4) are diff oriented
164   //            As transitions on face<iFI> are given relative to the geometry of e5,
165   //            we have to complement them.
166 //  Standard_Boolean toreverse = Standard_False;
167 //  Standard_Boolean hsdm = !BDS.ShapeSameDomain(iEG).IsEmpty();
168 //  if (hsdm) {
169 //    Standard_Boolean sameoriented = Standard_False;
170 //    Standard_Boolean ok = FUN_tool_curvesSO(TopoDS::Edge(Ecpx),parPok,TopoDS::Edge(BDS.Shape(iEG)),
171 //			       sameoriented);
172 //    if (ok) toreverse = !sameoriented;
173 //  }
174   // xpu :090498
175 
176   // FI = face de reference (shape), iFI (indice)
177   // E = arete geometrie d'interference (shape), iEG (indice)
178   // LI = liste d'interf de geom iEG et dont les Support() sont a transitionner complexe
179 
180   Handle(TopOpeBRepDS_Interference) I1,I2; TopOpeBRepDS_Kind GT1,ST1,GT2,ST2; Standard_Integer G1,S1,G2,S2;
181   TopOpeBRepDS_ListIteratorOfListOfInterference it1; it1.Initialize(LI);
182   while (it1.More()) {
183     Standard_Boolean u1 = FDS_data(it1,I1,GT1,G1,ST1,S1);if (u1) {it1.Next();continue;}
184     Standard_Boolean ya1 = (GT1 == MDSke); if (!ya1) {it1.Next();continue;}
185 
186     Standard_Boolean isComplex = Standard_False; // True if at least two interfs on the same edge
187     const TopoDS_Face& F1 = TopoDS::Face(BDS.Shape(S1));
188 
189     TopOpeBRepDS_ListIteratorOfListOfInterference it2(it1); it2.Next();
190     while (it2.More()) {
191       Standard_Boolean u2 = FDS_data(it2,I2,GT2,G2,ST2,S2);if (u2) {it2.Next();continue;}
192       Standard_Boolean ya2 = (GT2==GT1 && G2==G1 && ST2==ST1); if (!ya2) {it2.Next();continue;}
193       const TopoDS_Face& F2 = TopoDS::Face(BDS.Shape(S2));
194       if (!isComplex) {
195 	isComplex = Standard_True;
196 
197 
198 //	TopOpeBRepDS_Transition T1 = I1->Transition(); TopAbs_Orientation O1 = T1.Orientation(TopAbs_IN); // xpu :090498
199 //	Standard_Boolean revT1 = toreverse && (M_FORWARD(O1) || M_REVERSED(O1));      // xpu :090498
200 //	if (revT1) I1->ChangeTransition() = T1.Complement();  //xpu :090498
201 	FITool.Init(FI,Ecpx,isEGsp,I1);
202 	FDS_ADDEDGE(TRCF,"\ninit transition complexe F",iFI,FITool,FI,F1,Ecpx,isEGsp,I1);
203 //	if (revT1) I1->ChangeTransition() = T1.Complement();  //xpu :090498
204       }
205 
206 //      TopOpeBRepDS_Transition T2 = I2->Transition(); TopAbs_Orientation O2 = T2.Orientation(TopAbs_IN);  // xpu :090498
207 //      Standard_Boolean revT2 = toreverse && (M_FORWARD(O2) || M_REVERSED(O2));       // xpu :090498
208 //      if (revT2) I2->ChangeTransition() = T2.Complement();  //xpu :090498
209       FDS_ADDEDGE(TRCF,"add transition complexe F",iFI,FITool,FI,F2,Ecpx,isEGsp,I2);
210 //      if (revT2) I2->ChangeTransition() = T2.Complement();  //xpu :090498
211 
212       LI.Remove(it2);
213     }
214     if (isComplex) {
215       FITool.Transition(I1);
216     }
217     it1.Next();
218   }  // it1.More()
219 } // FUN_reduceEDGEgeometry1
220 
221 //------------------------------------------------------
FUN_GmapS(TopOpeBRepDS_ListOfInterference & LI,const TopOpeBRepDS_DataStructure & BDS,TopOpeBRepDS_MapOfShapeData & mosd)222 void FUN_GmapS(TopOpeBRepDS_ListOfInterference& LI, const TopOpeBRepDS_DataStructure& BDS, TopOpeBRepDS_MapOfShapeData& mosd)
223 {
224   mosd.Clear();
225   TopOpeBRepDS_Kind GT1,ST1;Standard_Integer G1,S1;
226   for (TopOpeBRepDS_ListIteratorOfListOfInterference it1(LI);it1.More();it1.Next()) {
227     Handle(TopOpeBRepDS_Interference)& I1=it1.Value(); FDS_data(I1,GT1,G1,ST1,S1);
228     if ( GT1 != MDSke || ST1 != MDSkf ) continue;
229     const TopoDS_Shape& SG1 = BDS.Shape(G1);
230     TopOpeBRepDS_ShapeData thedata;
231     if (!mosd.Contains(SG1)) mosd.Add(SG1, thedata);
232     mosd.ChangeFromKey(SG1).ChangeInterferences().Append(I1);
233   }
234 }
235 
236 //------------------------------------------------------
FUN_stateedgeface(const TopoDS_Shape & E,const TopoDS_Shape & F,gp_Pnt & P)237 TopAbs_State FUN_stateedgeface(const TopoDS_Shape& E, const TopoDS_Shape& F, gp_Pnt& P)
238 {
239   TopAbs_State state = TopAbs_UNKNOWN;
240   Standard_Real par; FUN_tool_findPinE(E,P,par);
241   Standard_Real u,v; Standard_Boolean Pok = FUN_Parameters(P,F,u,v);
242   if (Pok) { // classifier u,v dans F
243     TopOpeBRepTool_ShapeClassifier& PSC = FSC_GetPSC(F);
244     gp_Pnt2d Puv(u,v);
245     PSC.StateP2DReference(Puv);
246     state = PSC.State();
247   }
248   return state;
249 }
250 
251 #define  M_IN(ssstate) ((ssstate) == TopAbs_IN)
252 #define  M_ON(ssstate) ((ssstate) == TopAbs_ON)
253 #define M_OUT(ssstate) ((ssstate) == TopAbs_OUT)
254 #define M_UNK(ssstate) ((ssstate) == TopAbs_UNK)
255 
256 //------------------------------------------------------
FUN_reduceEDGEgeometry(TopOpeBRepDS_ListOfInterference & LI,const TopOpeBRepDS_DataStructure & BDS,const Standard_Integer iFI,const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State & MEsp)257 void FUN_reduceEDGEgeometry
258 (TopOpeBRepDS_ListOfInterference& LI,const TopOpeBRepDS_DataStructure& BDS,const Standard_Integer iFI,
259 const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State& MEsp)
260 {
261   if (!LI.Extent()) return;
262 
263   TopOpeBRepDS_MapOfShapeData mosd;
264   FUN_GmapS(LI,BDS,mosd);
265 
266   TopOpeBRepDS_ListOfInterference LIout;
267   //modified by NIZNHY-PKV Thu Mar 16 09:44:24 2000 f
268   Standard_Integer i, aN;
269   aN=mosd.Extent();
270   //for(Standard_Integer i=1,n=mosd.Extent(); i<=n; i++) {
271   //modified by NIZNHY-PKV Thu Mar 16 09:44:27 2000 t
272   for(i=1 ; i<=aN; i++) {
273     const TopoDS_Shape& EG = mosd.FindKey(i);
274     Standard_Integer iEG = BDS.Shape(EG);
275 
276     // donnees samedomain attachees a l'arete iEG
277     const TopTools_ListOfShape& esdeg = BDS.ShapeSameDomain(iEG);
278     Standard_Boolean egissect = BDS.IsSectionEdge(TopoDS::Edge(EG));
279     Standard_Boolean eghasesd = (! esdeg.IsEmpty());
280 
281     TopOpeBRepDS_ListOfInterference& LIEG = mosd.ChangeFromKey(EG).ChangeInterferences();
282     Standard_Integer nExt = LIEG.Extent();
283     // LIEG = toutes les interferences dont le Support() est une
284     // face possedant une interference dont la Geometry() est EG.
285     if      (nExt == 0) {
286       continue;
287     }
288     if      (nExt == 1) {
289       LIout.Append(LIEG);
290     }
291 
292     else if (nExt >= 2) {
293       Standard_Boolean isEGsp = MEsp.IsBound(EG);
294       //modified by NIZNHY-PKV Thu Mar 16 11:03:44 2000 from
295       //Standard_Integer nEGsp = 0;
296       //modified by NIZNHY-PKV Thu Mar 16 11:03:49 2000 to
297       if (isEGsp) {
298 	const TopOpeBRepDS_ListOfShapeOn1State& los1 = MEsp.Find(EG);
299 	isEGsp = los1.IsSplit();
300 	//modified by NIZNHY-PKV Thu Mar 16 11:02:40 2000 from
301 	//if ( isEGsp ) {
302 	//  const TopTools_ListOfShape& los = los1.ListOnState();
303 	//  nEGsp = los.Extent();
304 	//}
305 	//modified by NIZNHY-PKV Thu Mar 16 11:02:46 2000 to
306       }
307 
308       if ( isEGsp ) {
309 	const TopTools_ListOfShape& los = MEsp.Find(EG).ListOnState();
310 	TopTools_ListIteratorOfListOfShape itlos(los);
311 	for(;itlos.More();itlos.Next()) {
312 	  // EGsp est une arete splitee de EG.
313 	  const TopoDS_Shape& EGsp = itlos.Value();
314 
315 	  // LISFIN = liste des interferences de LI dont le Support()
316 	  // est une face contenant geometriquement l'arete EGsp
317 	  TopOpeBRepDS_ListOfInterference LISFIN;
318 	  TopOpeBRepDS_ListIteratorOfListOfInterference itLIEG(LIEG);
319 	  for(; itLIEG.More(); itLIEG.Next()) {
320 	    const Handle(TopOpeBRepDS_Interference)& ILIEG = itLIEG.Value();
321 	    Standard_Integer  iS = ILIEG->Support();
322 	    TopOpeBRepDS_Kind kS = ILIEG->SupportType();
323 	    if ( kS == MDSkf ) {
324 	      const TopoDS_Shape& SFILIEG = BDS.Shape(iS);
325 	      gp_Pnt P;
326 	      TopAbs_State staef = FUN_stateedgeface(EGsp,SFILIEG,P);
327 
328 	      Standard_Boolean Pok = M_IN(staef);
329 	      if ( eghasesd || egissect ) {
330 		Pok = Pok || M_ON(staef);
331 	      }
332 
333 	      if (Pok) {
334 		LISFIN.Append(ILIEG);
335 	      }
336 	    }
337 	  } // itLIEG.More
338 
339 	  Standard_Integer nLISFIN = LISFIN.Extent();
340 	  if (nLISFIN >= 2 ) {
341 	    Standard_Boolean gb;
342 	    gb = Handle(TopOpeBRepDS_ShapeShapeInterference)::DownCast(LISFIN.First())->GBound();
343 
344 	    if (gb) {
345 	      //modified by NIZNHY-PKV Thu Mar 16 10:40:57 2000 f
346 	      // we have to rest at least one  Interference on the face.
347 	      // To kill all of them is too bravely.
348 	      Handle(TopOpeBRepDS_Interference) anInterference = LISFIN.First();
349 	      LISFIN.Clear();
350 	      LISFIN.Append(anInterference);
351 	      //modified by NIZNHY-PKV Thu Mar 16 10:41:01 2000 t
352 	    }
353 	    else
354 	      FUN_reduceEDGEgeometry1(LISFIN,BDS,iFI,iEG,EGsp,MEsp);
355 	  }
356 
357 	  nLISFIN = LISFIN.Extent();
358 	  if (nLISFIN)
359 	    LIout.Append(LISFIN);
360 	}
361       } // isEGsp
362       else {
363 	// iFI = face de reference (indice)
364 	// E = arete geometrie d'interference (shape), iEG (indice)
365 	// LIEG = liste d'interferences de geometrie EG
366 	//        et dont les Support() sont a transitionner complexe
367 	TopoDS_Shape Enull;
368 	FUN_reduceEDGEgeometry1(LIEG,BDS,iFI,iEG,Enull,MEsp);
369 	LIout.Append(LIEG);
370       }
371     }
372   }
373 
374   LI.Clear();
375   LI.Append(LIout);
376 } // FUN_reduceEDGEgeometry
377 
378 //=======================================================================
379 //function : TopOpeBRepDS_FIR
380 //purpose  :
381 //=======================================================================
TopOpeBRepDS_FIR(const Handle (TopOpeBRepDS_HDataStructure)& HDS)382 TopOpeBRepDS_FIR::TopOpeBRepDS_FIR
383 (const Handle(TopOpeBRepDS_HDataStructure)& HDS) : myHDS(HDS)
384 {}
385 
386 //=======================================================================
387 //function : ProcessFaceInterferences
388 //purpose  :
389 //=======================================================================
ProcessFaceInterferences(const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State & M)390 void TopOpeBRepDS_FIR::ProcessFaceInterferences(const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State& M)
391 {
392   TopOpeBRepDS_DataStructure& BDS = myHDS->ChangeDS();
393   Standard_Integer i,nshape = BDS.NbShapes();
394   for (i = 1; i <= nshape; i++) {
395     const TopoDS_Shape& S = BDS.Shape(i);
396     if(S.IsNull()) continue;
397     if ( S.ShapeType() == TopAbs_FACE ) {
398       ProcessFaceInterferences(i,M);
399     }
400   }
401 }
402 
403 //=======================================================================
404 //function : ProcessFaceInterferences
405 //purpose  :
406 //=======================================================================
ProcessFaceInterferences(const Standard_Integer SIX,const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State & MEsp)407 void TopOpeBRepDS_FIR::ProcessFaceInterferences
408 (const Standard_Integer SIX,const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State& MEsp)
409 {
410   TopOpeBRepDS_DataStructure& BDS = myHDS->ChangeDS();
411   TopOpeBRepDS_ListOfInterference& LI = BDS.ChangeShapeInterferences(SIX);
412   TopOpeBRepDS_ListOfInterference lw, lE, lFE, lFEF, lF; lw.Assign(LI);
413 
414   ::FUN_selectTRASHAinterference(lw,TopAbs_FACE,lF);
415   ::FUN_selectGKinterference(lF,MDSke,lFE);
416   ::FUN_selectSKinterference(lFE,MDSkf,lFEF);
417   ::FUN_selectTRASHAinterference(lw,TopAbs_EDGE,lE);
418   FUN_reduceEDGEgeometry(lFEF,BDS,SIX,MEsp);
419 
420   LI.Clear();
421   LI.Append(lF);
422   LI.Append(lFE);
423   LI.Append(lFEF);
424   LI.Append(lE);
425   // MSV: filter duplicates
426   ::FUN_reducedoublons(LI,BDS,SIX);
427 }
428