0029915: Porting to VC 2017 : Regressions in Modeling Algorithms on VC 2017
[occt.git] / src / LocOpe / LocOpe_Spliter.cxx
CommitLineData
b311480e 1// Created on: 1996-01-09
2// Created by: Jacques GOUSSARD
3// Copyright (c) 1996-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
17// Modified by skv - Mon May 31 12:34:09 2004 OCC5865
18
42cf5bc1 19#include <BRep_Builder.hxx>
7fd59977 20#include <BRep_Tool.hxx>
7fd59977 21#include <BRepTools_Substitution.hxx>
42cf5bc1 22#include <Geom_Curve.hxx>
23#include <GeomAPI_ProjectPointOnCurve.hxx>
24#include <gp_Vec.hxx>
25#include <gp_Vec2d.hxx>
26#include <LocOpe_BuildWires.hxx>
27#include <LocOpe_Spliter.hxx>
7fd59977 28#include <LocOpe_SplitShape.hxx>
42cf5bc1 29#include <LocOpe_WiresOnShape.hxx>
7fd59977 30#include <Standard_ConstructionError.hxx>
42cf5bc1 31#include <Standard_NoSuchObject.hxx>
32#include <Standard_NullObject.hxx>
33#include <StdFail_NotDone.hxx>
34#include <TopExp.hxx>
35#include <TopExp_Explorer.hxx>
36#include <TopoDS.hxx>
37#include <TopoDS_Edge.hxx>
38#include <TopoDS_Face.hxx>
39#include <TopoDS_Iterator.hxx>
40#include <TopoDS_Shape.hxx>
41#include <TopoDS_Vertex.hxx>
42#include <TopoDS_Wire.hxx>
43#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
44#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
45#include <TopTools_DataMapOfShapeShape.hxx>
46#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
47#include <TopTools_IndexedMapOfShape.hxx>
48#include <TopTools_ListIteratorOfListOfShape.hxx>
49#include <TopTools_MapIteratorOfMapOfShape.hxx>
50#include <TopTools_MapOfShape.hxx>
b94d4858 51
7fd59977 52
42cf5bc1 53//#include <LocOpe_ProjectedWires.hxx>
7fd59977 54// Modified by skv - Mon May 31 13:00:30 2004 OCC5865 Begin
55// static void RebuildWires(TopTools_ListOfShape&);
56static void RebuildWires(TopTools_ListOfShape&,
59af51e3 57 const Handle(LocOpe_WiresOnShape)&);
7fd59977 58// Modified by skv - Mon May 31 13:00:31 2004 OCC5865 End
59
60static void Put(const TopoDS_Shape&,
61 TopTools_DataMapOfShapeListOfShape&);
62
63static void Select(const TopoDS_Edge&,
64 TopTools_ListOfShape&);
65
66
67//=======================================================================
68//function : Perform
69//purpose :
70//=======================================================================
71
59af51e3 72void LocOpe_Spliter::Perform(const Handle(LocOpe_WiresOnShape)& PW)
7fd59977 73{
74 if (myShape.IsNull()) {
9775fa61 75 throw Standard_NullObject();
7fd59977 76 }
77 myDone = Standard_False;
78 myMap.Clear();
79 myRes.Nullify();
80
81 Put(myShape,myMap);
82
83 TopTools_MapOfShape mapV,mapE;
84 TopTools_DataMapOfShapeShape EdgOnEdg;
85 TopTools_IndexedDataMapOfShapeListOfShape mapFE;
86 TopExp_Explorer exp,exp2;
87
88 // 1ere etape : substitution des vertex
89
90 TopoDS_Vertex Vb;
91 TopTools_ListOfShape lsubs;
92 BRepTools_Substitution theSubs;
93 BRep_Builder BB;
94
95 for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
96 const TopoDS_Edge& edg = PW->Edge();
97 mapE.Add(edg);
98 for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
99 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
100 if (!mapV.Contains(vtx)) {
101 if (PW->OnVertex(vtx,Vb)) {
102 mapV.Add(vtx);
b94d4858 103 if (vtx.IsSame(Vb))
104 continue;
7fd59977 105 lsubs.Clear();
106 TopoDS_Vertex vsub = TopoDS::Vertex(vtx.Oriented(TopAbs_FORWARD));
107 gp_Pnt p1 = BRep_Tool::Pnt(vsub), p2 = BRep_Tool::Pnt(Vb);
108 Standard_Real d = p1.Distance(p2);
109 d = d + BRep_Tool::Tolerance(Vb);
110 BB.UpdateVertex(vsub, d);
111 lsubs.Append(vsub);
112 theSubs.Substitute(Vb.Oriented(TopAbs_FORWARD),lsubs);
113 }
114
115 }
116 }
117 }
118
119 theSubs.Build(myShape);
120 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdesc(myMap);
121 if (theSubs.IsCopied(myShape)) {
122 // on n`a fait que des substitutions de vertex. Donc chaque element
123 // est remplace par lui meme ou par un seul element du meme type.
124 for (; itdesc.More(); itdesc.Next()) {
125 if (theSubs.IsCopied(itdesc.Key())) {
126 const TopTools_ListOfShape& lsub = theSubs.Copy(itdesc.Key());
0797d9d3 127#ifdef OCCT_DEBUG
7fd59977 128 if (lsub.Extent() != 1) {
9775fa61 129 throw Standard_ConstructionError();
7fd59977 130 }
131#endif
132 myMap(itdesc.Key()).Clear();
133 myMap(itdesc.Key()).Append(lsub.First());
134 }
135 }
136 }
137
138 myRes = myMap(myShape).First();
139 LocOpe_SplitShape theCFace(myRes);
140
141 // Adds every vertices lying on an edge of the shape, and prepares
142 // work to rebuild wires on each face
143 TopoDS_Edge Ed;
144 Standard_Real prm;
145
ed60a55e 146 TopTools_MapOfShape theFacesWithSection;
7fd59977 147 for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
aee24cb5 148 TopoDS_Edge edg = PW->Edge();
7fd59977 149 for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
150 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
151 if (!mapV.Contains(vtx)) {
152 mapV.Add(vtx);
59af51e3 153 if (PW->OnEdge(vtx,edg,Ed,prm)) {
7fd59977 154 // on devrait verifier que le vtx n`existe pas deja sur l`edge
155 if(!myMap.IsBound(Ed)) continue;
156 Ed = TopoDS::Edge(myMap(Ed).First());
157 theCFace.Add(vtx,prm,Ed);
158 }
159 }
160 }
161 TopoDS_Edge Ebis;
162 if (PW->OnEdge(Ebis)) {
163 // Ebis = TopoDS::Edge(myMap(Ebis).First());
164 EdgOnEdg.Bind(edg,Ebis);
165 }
166 else {
167 TopoDS_Face fac = PW->OnFace();
ed60a55e 168 if(!myMap.IsBound(fac)) continue;
169 Standard_Boolean IsFaceWithSec = PW->IsFaceWithSection(fac);
7fd59977 170 fac = TopoDS::Face(myMap(fac).First());
ed60a55e 171 if (IsFaceWithSec)
172 theFacesWithSection.Add(fac);
7fd59977 173 if (!mapFE.Contains(fac)) {
174 TopTools_ListOfShape thelist;
175 mapFE.Add(fac, thelist);
176 }
177 mapFE.ChangeFromKey(fac).Append(edg);
178 }
179 }
180
181 // Rebuilds wires on each face of the shape
182
183 TopTools_ListIteratorOfListOfShape itl;
184 for (Standard_Integer i=1; i<=mapFE.Extent(); i++) {
185 const TopoDS_Face& fac = TopoDS::Face(mapFE.FindKey(i));
186 TopTools_ListOfShape& ledges = mapFE(i);
187// Modified by skv - Mon May 31 12:32:54 2004 OCC5865 Begin
188// RebuildWires(ledges);
189 RebuildWires(ledges, PW);
190// Modified by skv - Mon May 31 12:32:54 2004 OCC5865 End
ed60a55e 191 if (theFacesWithSection.Contains(fac))
192 theCFace.Add(ledges, fac);
193 else
194 for (itl.Initialize(ledges); itl.More(); itl.Next())
195 theCFace.Add(TopoDS::Wire(itl.Value()),fac);
7fd59977 196 }
197
198
199 // Mise a jour des descendants
200
201 for (itdesc.Reset(); itdesc.More(); itdesc.Next()) {
202 const TopoDS_Shape& sori = itdesc.Key();
203 const TopoDS_Shape& scib = itdesc.Value().First();
204 myMap(sori) = theCFace.DescendantShapes(scib);
205 }
206
207 const TopTools_ListOfShape& lres = myMap(myShape);
208
209 TopAbs_ShapeEnum typS = myShape.ShapeType();
210 if (typS == TopAbs_FACE && lres.Extent() >=2) {
211 BRep_Builder B;
212 myRes.Nullify();
213 B.MakeShell(TopoDS::Shell(myRes));
214 myRes.Orientation(TopAbs_FORWARD);
215 for (itl.Initialize(lres); itl.More(); itl.Next()) {
216 B.Add(myRes,itl.Value().Oriented(myShape.Orientation()));
217 }
218 }
219 else if (typS == TopAbs_EDGE && lres.Extent() >=2) {
220 BRep_Builder B;
221 myRes.Nullify();
222 B.MakeWire(TopoDS::Wire(myRes));
223 myRes.Orientation(TopAbs_FORWARD);
224 for (itl.Initialize(lres); itl.More(); itl.Next()) {
225 B.Add(myRes,itl.Value().Oriented(myShape.Orientation()));
226 }
227 }
228 else {
229 if (lres.Extent() != 1) {
230 return;
231 }
232 myRes = lres.First();
233 }
234
235 theSubs.Clear();
236 for (TopTools_DataMapIteratorOfDataMapOfShapeShape itee(EdgOnEdg);
237 itee.More();
238 itee.Next()) {
239 const TopoDS_Edge& e1 = TopoDS::Edge(itee.Key());
240 // on recherche dans les descendants de e2 l`edge qui correspont a e1
241
242 TopoDS_Vertex vf1,vl1,vf2,vl2;
243 TopExp::Vertices(e1,vf1,vl1);
244 lsubs.Clear();
245 for (itl.Initialize(myMap(itee.Value()));
246 itl.More();
247 itl.Next()) {
248 const TopoDS_Edge& e2 = TopoDS::Edge(itl.Value());
249 TopExp::Vertices(e2,vf2,vl2);
250
251 if (!vl1.IsSame(vf1)) {
252 if (vf1.IsSame(vf2) && vl1.IsSame(vl2)) {
253 lsubs.Append(e2.Oriented(TopAbs_FORWARD));
254 // break;
255 }
256 else if (vf1.IsSame(vl2) && vl1.IsSame(vf2)) {
257 lsubs.Append(e2.Oriented(TopAbs_REVERSED));
258 // break;
259 }
260 }
261 else { // discrimination sur les tangentes
262 if (vf2.IsSame(vl2) && vl2.IsSame(vl1)) { // tout au meme point
263 TopLoc_Location Loc;
264 Standard_Real f,l;
265 gp_Pnt pbid;
266 gp_Vec v1,v2;
267 Handle(Geom_Curve) C = BRep_Tool::Curve(e1,Loc,f,l);
268 C->D1(f,pbid,v1);
269 v1.Transform(Loc.Transformation());
270
271 C = BRep_Tool::Curve(e2,Loc,f,l);
272 C->D1(f,pbid,v2);
273 v2.Transform(Loc.Transformation());
274 if (v1.Dot(v2) >0.) {
275 lsubs.Append(e2.Oriented(TopAbs_FORWARD));
276 }
277 else {
278 lsubs.Append(e2.Oriented(TopAbs_REVERSED));
279 }
280 }
281 }
282
283 }
284 if (lsubs.Extent() >= 2) { // il faut faire un choix
285 Select(e1,lsubs);
286 }
287 if (lsubs.Extent() == 1) {
288 TopoDS_Shape ebase = lsubs.First();
289 lsubs.Clear();
290 lsubs.Append(e1.Oriented(ebase.Orientation()));
aee24cb5 291 theSubs.Substitute(ebase,lsubs);
7fd59977 292 }
293 else {
0797d9d3 294#ifdef OCCT_DEBUG
7fd59977 295 cout << "Pb pour substitution" << endl;
296#endif
297 }
298 }
299
300 theSubs.Build(myRes);
301
302 for (itdesc.Reset(); itdesc.More(); itdesc.Next()) {
303 TopTools_ListOfShape& ldesc = myMap(itdesc.Key());
304 TopTools_ListOfShape newdesc;
305 for (itl.Initialize(ldesc); itl.More(); itl.Next()) {
306 if (theSubs.IsCopied(itl.Value())) {
307 const TopTools_ListOfShape& lsub = theSubs.Copy(itl.Value());
0797d9d3 308#ifdef OCCT_DEBUG
7fd59977 309 if (lsub.Extent() != 1) {
9775fa61 310 throw Standard_ConstructionError();
7fd59977 311 }
312#endif
313 newdesc.Append(lsub.First());
314 }
315 else {
316 newdesc.Append(itl.Value());
317 }
318 }
319 myMap(itdesc.Key()) = newdesc;
320 }
321
322 if (theSubs.IsCopied(myRes)) {
323 myRes = theSubs.Copy(myRes).First();
324 }
325
59af51e3 326 ////remove superfluous vertices on degenerated edges
327 theSubs.Clear();
328 TopTools_IndexedMapOfShape Emap;
329 TopExp::MapShapes(myRes, TopAbs_EDGE, Emap);
330 TopTools_SequenceOfShape DegEdges;
331 Standard_Integer i, j;
332 for (i = 1; i <= Emap.Extent(); i++)
333 {
334 const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(i));
335 if (BRep_Tool::Degenerated(anEdge))
336 DegEdges.Append(anEdge);
337 }
338
339 TopTools_SequenceOfShape DegWires;
340 for (;;)
341 {
342 if (DegEdges.IsEmpty())
343 break;
344 TopoDS_Wire aDegWire;
345 BB.MakeWire(aDegWire);
346 BB.Add(aDegWire, DegEdges(1));
347 DegEdges.Remove(1);
348 TopoDS_Vertex Vfirst, Vlast;
349 for (;;)
350 {
351 TopExp::Vertices(aDegWire, Vfirst, Vlast);
352 Standard_Boolean found = Standard_False;
353 for (i = 1; i <= DegEdges.Length(); i++)
354 {
355 const TopoDS_Edge& anEdge = TopoDS::Edge(DegEdges(i));
356 TopoDS_Vertex V1, V2;
357 TopExp::Vertices(anEdge, V1, V2);
358 if (V1.IsSame(Vfirst) || V1.IsSame(Vlast) || V2.IsSame(Vfirst) || V2.IsSame(Vlast))
359 {
360 BB.Add(aDegWire, anEdge);
361 DegEdges.Remove(i);
362 found = Standard_True;
363 break;
364 }
365 }
366 if (!found)
367 break;
368 }
369 DegWires.Append(aDegWire);
370 }
371
372 for (i = 1; i <= DegWires.Length(); i++)
373 {
374 TopTools_IndexedMapOfShape Vmap;
375 TopExp::MapShapes(DegWires(i), TopAbs_VERTEX, Vmap);
376 TopTools_ListOfShape LV;
377 LV.Append(Vmap(1).Oriented(TopAbs_FORWARD));
378 for (j = 2; j <= Vmap.Extent(); j++)
379 {
380 if (!Vmap(j).IsSame(Vmap(1)))
381 theSubs.Substitute(Vmap(j), LV);
382 }
383 }
384 theSubs.Build(myRes);
385 if (theSubs.IsCopied(myRes))
386 myRes = theSubs.Copy(myRes).First();
387 ////
388
7fd59977 389 myDLeft.Clear();
390 myLeft.Clear();
391 mapV.Clear();
392
393 TopTools_MapIteratorOfMapOfShape itms;
394
395 for (exp.Init(myRes, TopAbs_FACE); exp.More(); exp.Next()) {
396 const TopoDS_Face& fac = TopoDS::Face(exp.Current());
397 for (exp2.Init(fac,TopAbs_EDGE); exp2.More(); exp2.Next()) {
398 const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
399 for (itms.Initialize(mapE);
400 itms.More(); itms.Next()) {
401 if (itms.Key().IsSame(edg) &&
402 edg.Orientation() == itms.Key().Orientation()) {
403 break;
404 }
405 }
406 if (itms.More()) {
407 break;
408 }
409 }
410 if (exp2.More()) {
411 myDLeft.Append(fac);
412 myLeft.Append(fac);
413 }
414 else {
415 mapV.Add(fac);
416 }
417 }
418
419/* JAG : Ne peut pas marcher
420
421 Standard_Boolean full = mapV.IsEmpty();
422 while (!full) {
423 full = Standard_True;
424 itms.Initialize(mapV);
425 const TopoDS_Face& fac = TopoDS::Face(itms.Key());
426 for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
427 if (!mapE.Contains(exp.Current())) {
428 for (itl.Initialize(myLeft); itl.More(); itl.Next()) {
429 const TopoDS_Face& fac2 = TopoDS::Face(itl.Value());
430 for (exp2.Init(fac2,TopAbs_EDGE); exp2.More(); exp2.Next()) {
431 if (exp2.Current().IsSame(exp.Current())) {
432 myLeft.Append(fac);
433 mapV.Remove(fac);
434 full = mapV.IsEmpty();
435 break;
436 }
437 }
438 if (exp2.More()) {
439 break;
440 }
441 }
442 if (itl.More()) {
443 break;
444 }
445 }
446 }
447 }
448*/
449
450 // Map des edges ou les connexions sont possibles
451 TopTools_MapOfShape Mapebord;
452 for (itl.Initialize(myLeft); itl.More(); itl.Next()) {
453 for (exp.Init(itl.Value(),TopAbs_EDGE); exp.More(); exp.Next()) {
454 if (!mapE.Contains(exp.Current())) {
455 if (!Mapebord.Add(exp.Current())) {
456 Mapebord.Remove(exp.Current());
457 }
458 }
459 }
460 }
461
462
463 while (Mapebord.Extent() != 0) {
464 itms.Initialize(Mapebord);
465 TopoDS_Shape edg = itms.Key();
466
467 for (itms.Initialize(mapV); itms.More(); itms.Next()) {
468 const TopoDS_Shape& fac = itms.Key();
469 for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
470 if (exp.Current().IsSame(edg)) {
471 break;
472 }
473 }
474 if (exp.More()) {
475 break; // face a gauche
476 }
477 }
478 if (itms.More()) {
479 TopoDS_Shape fac = itms.Key();
480 for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
481 if (!Mapebord.Add(exp.Current())) {
482 Mapebord.Remove(exp.Current());
483 }
484 }
485 mapV.Remove(fac);
486 myLeft.Append(fac);
487 }
488 else {
489 Mapebord.Remove(edg);
490 }
491 }
492
493 myDone = Standard_True;
494}
495
496
497//=======================================================================
498//function : DescendantShapes
499//purpose :
500//=======================================================================
501
502const TopTools_ListOfShape& LocOpe_Spliter::
503 DescendantShapes(const TopoDS_Shape& F)
504{
9775fa61 505 if (!myDone) {throw StdFail_NotDone();}
7fd59977 506 if (myMap.IsBound(F))
507 return myMap(F);
508 else {
509 static TopTools_ListOfShape empty;
510 return empty;
511 }
512}
513
514
515//=======================================================================
516//function : DirectLeft
517//purpose :
518//=======================================================================
519
520const TopTools_ListOfShape& LocOpe_Spliter::DirectLeft() const
521{
9775fa61 522 if (!myDone) {throw StdFail_NotDone();}
7fd59977 523 return myDLeft;
524
525}
526
527
528//=======================================================================
529//function : Left
530//purpose :
531//=======================================================================
532
533const TopTools_ListOfShape& LocOpe_Spliter::Left() const
534{
9775fa61 535 if (!myDone) {throw StdFail_NotDone();}
7fd59977 536 return myLeft;
537
538}
539
540
541//=======================================================================
542//function : RebuildWires
543//purpose :
544//=======================================================================
545
546// Modified by skv - Mon May 31 12:31:39 2004 OCC5865 Begin
547//static void RebuildWires(TopTools_ListOfShape& ledge)
548static void RebuildWires(TopTools_ListOfShape& ledge,
59af51e3 549 const Handle(LocOpe_WiresOnShape)& PW)
7fd59977 550{
551 LocOpe_BuildWires theBuild(ledge, PW);
552// Modified by skv - Mon May 31 12:31:40 2004 OCC5865 End
553 if (!theBuild.IsDone()) {
9775fa61 554 throw Standard_ConstructionError();
7fd59977 555 }
556 ledge = theBuild.Result();
557
558
559}
560
561
562
563//=======================================================================
564//function : Put
565//purpose :
566//=======================================================================
567
568static void Put(const TopoDS_Shape& S,
569 TopTools_DataMapOfShapeListOfShape& theMap)
570{
571 if (theMap.IsBound(S)) {
572 return;
573 }
574 TopTools_ListOfShape thelist;
575 theMap.Bind(S, thelist);
576 theMap(S).Append(S);
577 for (TopoDS_Iterator it(S); it.More(); it.Next()) {
578 Put(it.Value(),theMap);
579 }
580}
581
582
583//=======================================================================
584//function : Select
585//purpose :
586//=======================================================================
587
588static void Select(const TopoDS_Edge& Ebase,
589 TopTools_ListOfShape& lsubs)
590{
591
592 // Choix d`un point
593
594 Handle(Geom_Curve) C;
595 TopLoc_Location Loc;
596 Standard_Real f,l,dmin = RealLast();
597 Standard_Integer i=0,imin = 0;
598
599 C = BRep_Tool::Curve(Ebase,Loc,f,l);
600
601 if (!Loc.IsIdentity()) {
602 Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
c5f3a425 603 C = Handle(Geom_Curve)::DownCast (GG);
7fd59977 604 }
605 gp_Pnt Pt(C->Value((f+l)/2.));
606
607 GeomAPI_ProjectPointOnCurve proj;
608// for (TopTools_ListIteratorOfListOfShape itl(lsubs);
609 TopTools_ListIteratorOfListOfShape itl(lsubs);
610 for ( ;itl.More();itl.Next()) {
611 i++;
612 const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
613 C = BRep_Tool::Curve(edg,Loc,f,l);
614 if (!Loc.IsIdentity()) {
615 Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
c5f3a425 616 C = Handle(Geom_Curve)::DownCast (GG);
7fd59977 617 }
618 proj.Init(Pt,C,f,l);
619 if (proj.NbPoints() > 0) {
620 if (proj.LowerDistance() < dmin) {
621 imin = i;
622 dmin = proj.LowerDistance();
623 }
624 }
625 }
626 if (imin == 0) {
627 lsubs.Clear();
628 }
629 else {
630 itl.Initialize(lsubs);
631 i = 1;
632 while (i < imin) {
633 lsubs.Remove(itl);
634 i++;
635 }
636 itl.Next();
637 while (itl.More()) {
638 lsubs.Remove(itl);
639 }
640 }
641}