1 // Created on: 1996-09-05
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRep_TVertex.hxx>
21 #include <BRepAlgo_AsDes.hxx>
22 #include <BRepAlgo_Image.hxx>
23 #include <BRepAlgo_Loop.hxx>
24 #include <BRepOffset_Analyse.hxx>
25 #include <BRepOffset_MakeLoops.hxx>
26 #include <TopExp.hxx>
27 #include <TopExp_Explorer.hxx>
28 #include <TopoDS.hxx>
29 #include <TopoDS_Edge.hxx>
30 #include <TopoDS_Face.hxx>
31 #include <TopoDS_Iterator.hxx>
32 #include <TopoDS_Vertex.hxx>
33 #include <TopTools_ListIteratorOfListOfShape.hxx>
34 #include <TopTools_MapOfShape.hxx>
35
36 #include <stdio.h>
37 #ifdef DRAW
38 #include <DBRep.hxx>
39 Standard_Integer NbF = 1;
40 static Standard_Boolean Affich = Standard_False;
41 #endif
42
BRepOffset_MakeLoops()43 BRepOffset_MakeLoops::BRepOffset_MakeLoops()
44 {
45 }
46
47 //=======================================================================
48 //function : Build
49 //purpose :
50 //=======================================================================
51
Build(const TopTools_ListOfShape & LF,const Handle (BRepAlgo_AsDes)& AsDes,BRepAlgo_Image & Image,BRepAlgo_Image & theImageVV,const Message_ProgressRange & theRange)52 void BRepOffset_MakeLoops::Build(const TopTools_ListOfShape& LF,
53 const Handle(BRepAlgo_AsDes)& AsDes,
54 BRepAlgo_Image& Image,
55 BRepAlgo_Image& theImageVV,
56 const Message_ProgressRange& theRange)
57 {
58 TopTools_ListIteratorOfListOfShape it(LF);
59 TopTools_ListIteratorOfListOfShape itl,itLCE;
60 BRepAlgo_Loop Loops;
61 Loops.VerticesForSubstitute( myVerVerMap );
62 Loops.SetImageVV (theImageVV);
63 Message_ProgressScope aPSOuter(theRange, NULL, 2);
64 Message_ProgressScope aPS1(aPSOuter.Next(), "Init loops", LF.Size());
65 for (; it.More(); it.Next(), aPS1.Next()) {
66 if (!aPS1.More())
67 {
68 return;
69 }
70 const TopoDS_Face& F = TopoDS::Face(it.Value());
71 //---------------------------
72 // Initialization of Loops.
73 //---------------------------
74 Loops.Init(F);
75 //-----------------------------
76 // return edges of F.
77 //-----------------------------
78 const TopTools_ListOfShape& LE = AsDes->Descendant(F);
79 TopTools_ListOfShape AddedEdges;
80
81 for (itl.Initialize(LE); itl.More(); itl.Next()) {
82 TopoDS_Edge E = TopoDS::Edge(itl.Value());
83 if (Image.HasImage(E)) {
84 //-------------------------------------------
85 // E was already cut in another face.
86 // Return the cut edges reorientate them as E.
87 // See pb for the edges that have disappeared?
88 //-------------------------------------------
89 const TopTools_ListOfShape& LCE = Image.Image(E);
90 for (itLCE.Initialize(LCE); itLCE.More(); itLCE.Next()) {
91 TopoDS_Shape CE = itLCE.Value().Oriented(E.Orientation());
92 Loops.AddConstEdge(TopoDS::Edge(CE));
93 }
94 }
95 else {
96 Loops .AddEdge(E, AsDes->Descendant(E));
97 AddedEdges.Append (E);
98 }
99 }
100 //------------------------
101 // Unwind.
102 //------------------------
103 Loops.Perform();
104 Loops.WiresToFaces();
105 //------------------------
106 // MAJ SD.
107 //------------------------
108 const TopTools_ListOfShape& NF = Loops.NewFaces();
109 //-----------------------
110 // F => New faces;
111 //-----------------------
112 Image.Bind(F,NF);
113
114 TopTools_ListIteratorOfListOfShape itAdded;
115 for (itAdded.Initialize(AddedEdges); itAdded.More(); itAdded.Next()) {
116 const TopoDS_Edge& E = TopoDS::Edge(itAdded.Value());
117 //-----------------------
118 // E => New edges;
119 //-----------------------
120 const TopTools_ListOfShape& LoopNE = Loops.NewEdges(E);
121 if (Image.HasImage(E)) {
122 Image.Add(E,LoopNE);
123 }
124 else {
125 Image.Bind(E,LoopNE);
126 }
127 }
128 }
129 Loops.GetVerticesForSubstitute( myVerVerMap );
130 if (myVerVerMap.IsEmpty())
131 return;
132 BRep_Builder BB;
133 Message_ProgressScope aPS2(aPSOuter.Next(), "Building loops", LF.Size());
134 for (it.Initialize(LF); it.More(); it.Next(), aPS2.Next())
135 {
136 if (!aPS2.More())
137 {
138 return;
139 }
140 TopoDS_Shape F = it.Value();
141 TopTools_ListOfShape LIF;
142 Image.LastImage(F, LIF);
143 for (itl.Initialize(LIF); itl.More(); itl.Next())
144 {
145 const TopoDS_Shape& IF = itl.Value();
146 TopExp_Explorer EdExp(IF, TopAbs_EDGE);
147 for (; EdExp.More(); EdExp.Next())
148 {
149 TopoDS_Shape E = EdExp.Current();
150 TopTools_ListOfShape VList;
151 TopoDS_Iterator VerExp(E);
152 for (; VerExp.More(); VerExp.Next())
153 VList.Append(VerExp.Value());
154 TopTools_ListIteratorOfListOfShape itlv(VList);
155 for (; itlv.More(); itlv.Next())
156 {
157 const TopoDS_Shape& V = itlv.Value();
158 if (myVerVerMap.IsBound(V))
159 {
160 TopoDS_Shape NewV = myVerVerMap(V);
161 E.Free(Standard_True);
162 NewV.Orientation(V.Orientation());
163 Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &V.TShape());
164 Handle(BRep_TVertex)& NewTV = *((Handle(BRep_TVertex)*) &NewV.TShape());
165 if (TV->Tolerance() > NewTV->Tolerance())
166 NewTV->Tolerance(TV->Tolerance());
167 NewTV->ChangePoints().Append(TV->ChangePoints());
168 AsDes->Replace(V, NewV);
169 BB.Remove(E, V);
170 BB.Add(E, NewV);
171 }
172 }
173 }
174 }
175 }
176 }
177
178 //=======================================================================
179 //function : IsBetweenCorks
180 //purpose :
181 //=======================================================================
182
IsBetweenCorks(const TopoDS_Shape & E,const Handle (BRepAlgo_AsDes)& AsDes,const TopTools_ListOfShape & LContext)183 static Standard_Boolean IsBetweenCorks(const TopoDS_Shape& E,
184 const Handle(BRepAlgo_AsDes)& AsDes,
185 const TopTools_ListOfShape& LContext)
186 {
187 if (!AsDes->HasAscendant(E)) return 1;
188 const TopTools_ListOfShape& LF = AsDes->Ascendant(E);
189 TopTools_ListIteratorOfListOfShape it;
190 for (it.Initialize(LF); it.More(); it.Next()) {
191 const TopoDS_Shape& S = it.Value();
192 Standard_Boolean found = 0;
193 TopTools_ListIteratorOfListOfShape it2;
194 for (it2.Initialize(LContext); it2.More(); it2.Next()) {
195 if(S.IsSame(it2.Value())) {
196 found = 1;
197 break;
198 }
199 }
200 if (!found) return 0;
201 }
202 return 1;
203 }
204 //=======================================================================
205 //function : BuildOnContext
206 //purpose :
207 //=======================================================================
208
BuildOnContext(const TopTools_ListOfShape & LContext,const BRepOffset_Analyse & Analyse,const Handle (BRepAlgo_AsDes)& AsDes,BRepAlgo_Image & Image,const Standard_Boolean InSide,const Message_ProgressRange & theRange)209 void BRepOffset_MakeLoops::BuildOnContext(const TopTools_ListOfShape& LContext,
210 const BRepOffset_Analyse& Analyse,
211 const Handle(BRepAlgo_AsDes)& AsDes,
212 BRepAlgo_Image& Image,
213 const Standard_Boolean InSide,
214 const Message_ProgressRange& theRange)
215 {
216 //-----------------------------------------
217 // unwinding of caps.
218 //-----------------------------------------
219 TopTools_ListIteratorOfListOfShape it(LContext);
220 TopTools_ListIteratorOfListOfShape itl,itLCE;
221 BRepAlgo_Loop Loops;
222 Loops.VerticesForSubstitute( myVerVerMap );
223 TopExp_Explorer exp;
224 TopTools_MapOfShape MapExtent;
225
226 Message_ProgressScope aPS(theRange, "Building deepening faces", LContext.Extent());
227 for (; it.More(); it.Next(), aPS.Next()) {
228 if (!aPS.More())
229 {
230 return;
231 }
232 const TopoDS_Face& F = TopoDS::Face(it.Value());
233 TopTools_MapOfShape MBound;
234 //-----------------------------------------------
235 // Initialisation of Loops.
236 // F is reversed it will be added in myOffC.
237 // and myOffC will be reversed in the final result.
238 //-----------------------------------------------
239 TopoDS_Shape aReversedF = F.Reversed();
240 if (InSide) Loops.Init(TopoDS::Face(aReversedF));
241 // if (InSide) Loops.Init(TopoDS::Face(F.Reversed()));
242 else Loops.Init(F);
243 //--------------------------------------------------------
244 // return edges of F not modified by definition.
245 //--------------------------------------------------------
246 for (exp.Init(F.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
247 exp.More();
248 exp.Next()) {
249 TopoDS_Edge CE = TopoDS::Edge(exp.Current());
250 MBound.Add(CE);
251 if (Analyse.HasAncestor(CE)) {
252 // the stop of cups except for the connectivity stops between caps.
253 // if (!AsDes->HasAscendant(CE)) {
254 TopoDS_Shape aReversedE = CE.Reversed();
255 if (InSide) Loops.AddConstEdge(CE);
256 else Loops.AddConstEdge(TopoDS::Edge(aReversedE));
257 // else Loops.AddConstEdge(TopoDS::Edge(CE.Reversed()));
258 }
259 }
260 //------------------------------------------------------
261 // Trace of offsets + connectivity edge between caps.
262 //------------------------------------------------------
263 const TopTools_ListOfShape& LE = AsDes->Descendant(F);
264 TopTools_ListOfShape AddedEdges;
265
266 for (itl.Initialize(LE); itl.More(); itl.Next()) {
267 TopoDS_Edge E = TopoDS::Edge(itl.Value());
268 if (Image.HasImage(E)) {
269 //-------------------------------------------
270 // E was already cut in another face.
271 // Return cut edges and orientate them as E.
272 // See pb for the edges that have disappeared?
273 //-------------------------------------------
274 const TopTools_ListOfShape& LCE = Image.Image(E);
275 for (itLCE.Initialize(LCE); itLCE.More(); itLCE.Next()) {
276 TopoDS_Shape CE = itLCE.Value().Oriented(E.Orientation());
277 if (MapExtent.Contains(E)) {
278 Loops.AddConstEdge(TopoDS::Edge(CE));
279 continue;
280 }
281 if (!MBound.Contains(E)) CE.Reverse();
282 if (InSide) Loops.AddConstEdge(TopoDS::Edge(CE));
283 else
284 {
285 TopoDS_Shape aReversedE = CE.Reversed();
286 Loops.AddConstEdge(TopoDS::Edge(aReversedE));
287 }
288 // else Loops.AddConstEdge(TopoDS::Edge(CE.Reversed()));
289 }
290 }
291 else {
292 if (IsBetweenCorks(E,AsDes,LContext) && AsDes->HasDescendant(E)) {
293 //connection between 2 caps
294 MapExtent.Add(E);
295 TopTools_ListOfShape LV;
296 if (InSide) {
297 for (itLCE.Initialize(AsDes->Descendant(E)); itLCE.More(); itLCE.Next()) {
298 LV.Append(itLCE.Value().Reversed());
299 }
300 Loops.AddEdge(E,LV);
301 }
302 else {
303 Loops.AddEdge(E,AsDes->Descendant(E));
304 }
305 AddedEdges.Append (E);
306 }
307 else if (IsBetweenCorks(E,AsDes,LContext)) {
308 TopoDS_Shape aLocalShape = E.Reversed();
309 if (InSide) Loops.AddConstEdge(E);
310 else Loops.AddConstEdge(TopoDS::Edge(aLocalShape));
311 // if (InSide) Loops.AddConstEdge(TopoDS::Edge(E));
312 // else Loops.AddConstEdge(TopoDS::Edge(E.Reversed()));
313 }
314 else {
315 TopoDS_Shape aLocalShape = E.Reversed();
316 if (InSide) Loops.AddConstEdge(TopoDS::Edge(aLocalShape));
317 else Loops.AddConstEdge(E);
318 // if (InSide) Loops.AddConstEdge(TopoDS::Edge(E.Reversed()));
319 // else Loops.AddConstEdge(TopoDS::Edge(E));
320 }
321 }
322 }
323 //------------------------
324 // Unwind.
325 //------------------------
326 Loops.Perform();
327 Loops.WiresToFaces();
328 //------------------------
329 // MAJ SD.
330 //------------------------
331 const TopTools_ListOfShape& NF = Loops.NewFaces();
332 //-----------------------
333 // F => New faces;
334 //-----------------------
335 Image.Bind(F,NF);
336
337 TopTools_ListIteratorOfListOfShape itAdded;
338 for (itAdded.Initialize(AddedEdges); itAdded.More(); itAdded.Next()) {
339 const TopoDS_Edge& E = TopoDS::Edge(itAdded.Value());
340 //-----------------------
341 // E => New edges;
342 //-----------------------
343 if (Image.HasImage(E)) {
344 Image.Add(E,Loops.NewEdges(E));
345 }
346 else {
347 Image.Bind(E,Loops.NewEdges(E));
348 }
349 }
350 }
351 Loops.GetVerticesForSubstitute( myVerVerMap );
352 if (myVerVerMap.IsEmpty())
353 return;
354 BRep_Builder BB;
355 for (it.Initialize( LContext ); it.More(); it.Next())
356 {
357 TopoDS_Shape F = it.Value();
358 TopTools_ListOfShape LIF;
359 Image.LastImage( F, LIF );
360 for (itl.Initialize(LIF); itl.More(); itl.Next())
361 {
362 const TopoDS_Shape& IF = itl.Value();
363 TopExp_Explorer EdExp( IF, TopAbs_EDGE );
364 for (; EdExp.More(); EdExp.Next())
365 {
366 TopoDS_Shape E = EdExp.Current();
367 TopTools_ListOfShape VList;
368 TopoDS_Iterator VerExp( E );
369 for (; VerExp.More(); VerExp.Next())
370 VList.Append( VerExp.Value() );
371 TopTools_ListIteratorOfListOfShape itlv( VList );
372 for (; itlv.More(); itlv.Next())
373 {
374 const TopoDS_Shape& V = itlv.Value();
375 if (myVerVerMap.IsBound( V ))
376 {
377 TopoDS_Shape NewV = myVerVerMap( V );
378 E.Free( Standard_True );
379 NewV.Orientation( V.Orientation() );
380 Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &V.TShape());
381 Handle(BRep_TVertex)& NewTV = *((Handle(BRep_TVertex)*) &NewV.TShape());
382 if (TV->Tolerance() > NewTV->Tolerance())
383 NewTV->Tolerance( TV->Tolerance() );
384 NewTV->ChangePoints().Append( TV->ChangePoints() );
385 AsDes->Replace( V, NewV );
386 BB.Remove( E, V );
387 BB.Add( E, NewV );
388 }
389 }
390 }
391 }
392 }
393 }
394
395
396 //=======================================================================
397 //function : BuildFaces
398 //purpose :
399 //=======================================================================
400
BuildFaces(const TopTools_ListOfShape & LF,const Handle (BRepAlgo_AsDes)& AsDes,BRepAlgo_Image & Image,const Message_ProgressRange & theRange)401 void BRepOffset_MakeLoops::BuildFaces(const TopTools_ListOfShape& LF,
402 const Handle(BRepAlgo_AsDes)& AsDes,
403 BRepAlgo_Image& Image,
404 const Message_ProgressRange& theRange)
405 {
406 TopTools_ListIteratorOfListOfShape itr,itl,itLCE;
407 Standard_Boolean ToRebuild;
408 BRepAlgo_Loop Loops;
409 Loops.VerticesForSubstitute( myVerVerMap );
410 BRep_Builder B;
411
412 //----------------------------------
413 // Loop on all faces //.
414 //----------------------------------
415 Message_ProgressScope aPS(theRange, "Building faces", LF.Size());
416 for (itr.Initialize(LF); itr.More(); itr.Next(), aPS.Next()) {
417 if (!aPS.More())
418 {
419 return;
420 }
421 TopoDS_Face F = TopoDS::Face(itr.Value());
422 Loops.Init(F);
423 ToRebuild = Standard_False;
424 TopTools_ListOfShape AddedEdges;
425
426 if (!Image.HasImage(F)) {
427 //----------------------------------
428 // Face F not yet reconstructed.
429 //----------------------------------
430 const TopTools_ListOfShape& LE = AsDes->Descendant(F);
431 //----------------------------------------------------------------
432 // first loop to find if the edges of the face were reconstructed.
433 // - maj on map MONV. Some vertices on reconstructed edges
434 // coincide geometrically with old but are not IsSame.
435 //----------------------------------------------------------------
436 TopTools_DataMapOfShapeShape MONV;
437 TopoDS_Vertex OV1,OV2,NV1,NV2;
438
439 for (itl.Initialize(LE); itl.More(); itl.Next()) {
440 TopoDS_Edge E = TopoDS::Edge(itl.Value());
441 if (Image.HasImage(E)) {
442 const TopTools_ListOfShape& LCE = Image.Image(E);
443 if (LCE.Extent() == 1 && LCE.First().IsSame(E)) {
444 TopoDS_Shape aLocalShape = LCE.First().Oriented(E.Orientation());
445 TopoDS_Edge CE = TopoDS::Edge(aLocalShape);
446 // TopoDS_Edge CE = TopoDS::Edge(LCE.First().Oriented(E.Orientation()));
447 Loops.AddConstEdge(CE);
448 continue;
449 }
450 //----------------------------------
451 // F should be reconstructed.
452 //----------------------------------
453 ToRebuild = Standard_True;
454 for (itLCE.Initialize(LCE); itLCE.More(); itLCE.Next()) {
455 TopoDS_Shape aLocalShape = itLCE.Value().Oriented(E.Orientation());
456 TopoDS_Edge CE = TopoDS::Edge(aLocalShape);
457 // TopoDS_Edge CE = TopoDS::Edge(itLCE.Value().Oriented(E.Orientation()));
458 TopExp::Vertices (E ,OV1,OV2);
459 TopExp::Vertices (CE,NV1,NV2);
460 if (!OV1.IsSame(NV1)) MONV.Bind(OV1,NV1);
461 if (!OV2.IsSame(NV2)) MONV.Bind(OV2,NV2);
462 Loops.AddConstEdge(CE);
463 }
464 }
465 }
466 if (ToRebuild) {
467 #ifdef DRAW
468 if ( Affich) {
469 char name[256];
470 sprintf(name,"CF_%d",NbF++);
471 DBRep::Set(name,F);
472 }
473 #endif
474
475 //-----------------------------------------------------------
476 // Non-reconstructed edges on other faces are added.
477 // If their vertices were reconstructed they are reconstructed.
478 //-----------------------------------------------------------
479 for (itl.Initialize(LE); itl.More(); itl.Next()) {
480 Standard_Real f,l;
481 TopoDS_Edge E = TopoDS::Edge(itl.Value());
482 BRep_Tool::Range(E,f,l);
483 if (!Image.HasImage(E)) {
484 TopExp::Vertices (E,OV1,OV2);
485 TopTools_ListOfShape LV;
486 if (MONV.IsBound(OV1)) {
487 TopoDS_Vertex VV = TopoDS::Vertex(MONV(OV1));
488 VV.Orientation(TopAbs_FORWARD);
489 LV.Append(VV);
490 TopoDS_Shape aLocalShape = VV.Oriented(TopAbs_INTERNAL);
491 B.UpdateVertex(TopoDS::Vertex(aLocalShape),
492 f,E,BRep_Tool::Tolerance(VV));
493 }
494 if (MONV.IsBound(OV2)) {
495 TopoDS_Vertex VV = TopoDS::Vertex(MONV(OV2));
496 VV.Orientation(TopAbs_REVERSED);
497 LV.Append(VV);
498 TopoDS_Shape aLocalShape = VV.Oriented(TopAbs_INTERNAL);
499 B.UpdateVertex(TopoDS::Vertex(aLocalShape),
500 l,E,BRep_Tool::Tolerance(VV));
501 // B.UpdateVertex(TopoDS::Vertex(VV.Oriented(TopAbs_INTERNAL)),
502 // l,E,BRep_Tool::Tolerance(VV));
503 }
504 if (LV.IsEmpty()) Loops.AddConstEdge(E);
505 else {
506 Loops.AddEdge (E,LV);
507 AddedEdges.Append(E);
508 }
509 }
510 }
511 }
512 }
513 if (ToRebuild) {
514 //------------------------
515 // Reconstruction.
516 //------------------------
517 Loops.Perform();
518 Loops.WiresToFaces();
519 //------------------------
520 // MAJ SD.
521 //------------------------
522 const TopTools_ListOfShape& NF = Loops.NewFaces();
523 //-----------------------
524 // F => New faces;
525 //-----------------------
526 Image.Bind(F,NF);
527
528 TopTools_ListIteratorOfListOfShape itAdded;
529 for (itAdded.Initialize(AddedEdges); itAdded.More(); itAdded.Next()) {
530 const TopoDS_Edge& E = TopoDS::Edge(itAdded.Value());
531 //-----------------------
532 // E => New edges;
533 //-----------------------
534 if (Image.HasImage(E)) {
535 Image.Add(E,Loops.NewEdges(E));
536 }
537 else {
538 Image.Bind(E,Loops.NewEdges(E));
539 }
540 }
541 }
542 }
543 Loops.GetVerticesForSubstitute( myVerVerMap );
544 if (myVerVerMap.IsEmpty())
545 return;
546 BRep_Builder BB;
547 for (itr.Initialize( LF ); itr.More(); itr.Next())
548 {
549 TopoDS_Shape F = itr.Value();
550 TopTools_ListOfShape LIF;
551 Image.LastImage( F, LIF );
552 for (itl.Initialize(LIF); itl.More(); itl.Next())
553 {
554 const TopoDS_Shape& IF = itl.Value();
555 TopExp_Explorer EdExp( IF, TopAbs_EDGE );
556 for (; EdExp.More(); EdExp.Next())
557 {
558 TopoDS_Shape E = EdExp.Current();
559 TopTools_ListOfShape VList;
560 TopoDS_Iterator VerExp( E );
561 for (; VerExp.More(); VerExp.Next())
562 VList.Append( VerExp.Value() );
563 TopTools_ListIteratorOfListOfShape itlv( VList );
564 for (; itlv.More(); itlv.Next())
565 {
566 const TopoDS_Shape& V = itlv.Value();
567 if (myVerVerMap.IsBound( V ))
568 {
569 TopoDS_Shape NewV = myVerVerMap( V );
570 E.Free( Standard_True );
571 NewV.Orientation( V.Orientation() );
572 Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &V.TShape());
573 Handle(BRep_TVertex)& NewTV = *((Handle(BRep_TVertex)*) &NewV.TShape());
574 if (TV->Tolerance() > NewTV->Tolerance())
575 NewTV->Tolerance( TV->Tolerance() );
576 NewTV->ChangePoints().Append( TV->ChangePoints() );
577 AsDes->Replace( V, NewV );
578 BB.Remove( E, V );
579 BB.Add( E, NewV );
580 }
581 }
582 }
583 }
584 }
585 }
586