1 // Created on: 1993-12-15
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1993-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 //pmn 26/09/97 Add parameters of approximation in BuildCurve3d
18 // Modified by skv - Thu Jun 3 12:39:19 2004 OCC5898
19
20 #include <BRepLib.hxx>
21
22 #include <Adaptor3d_CurveOnSurface.hxx>
23 #include <AdvApprox_ApproxAFunction.hxx>
24 #include <AppParCurves_MultiBSpCurve.hxx>
25 #include <AppParCurves_MultiCurve.hxx>
26 #include <Approx_CurvilinearParameter.hxx>
27 #include <Approx_SameParameter.hxx>
28 #include <Bnd_Box.hxx>
29 #include <BRep_Builder.hxx>
30 #include <BRep_CurveRepresentation.hxx>
31 #include <BRep_GCurve.hxx>
32 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
33 #include <BRep_ListOfCurveRepresentation.hxx>
34 #include <BRepCheck.hxx>
35 #include <BRep_TEdge.hxx>
36 #include <BRep_TFace.hxx>
37 #include <BRep_Tool.hxx>
38 #include <BRep_TVertex.hxx>
39 #include <BRepAdaptor_Curve.hxx>
40 #include <BRepAdaptor_Curve2d.hxx>
41 #include <BRepAdaptor_Surface.hxx>
42 #include <BRepBndLib.hxx>
43 #include <BRepClass3d_SolidClassifier.hxx>
44 #include <BRepLib_MakeFace.hxx>
45 #include <BSplCLib.hxx>
46 #include <ElSLib.hxx>
47 #include <Extrema_LocateExtPC.hxx>
48 #include <GCPnts_QuasiUniformDeflection.hxx>
49 #include <Geom2d_BSplineCurve.hxx>
50 #include <Geom2d_Curve.hxx>
51 #include <Geom2d_TrimmedCurve.hxx>
52 #include <Geom2dAdaptor.hxx>
53 #include <Geom2dAdaptor_Curve.hxx>
54 #include <Geom2dConvert.hxx>
55 #include <Geom_BSplineCurve.hxx>
56 #include <Geom_BSplineSurface.hxx>
57 #include <Geom_Curve.hxx>
58 #include <Geom_Plane.hxx>
59 #include <Geom_RectangularTrimmedSurface.hxx>
60 #include <Geom_Surface.hxx>
61 #include <Geom_TrimmedCurve.hxx>
62 #include <GeomAdaptor_Curve.hxx>
63 #include <GeomAdaptor_Surface.hxx>
64 #include <GeomLib.hxx>
65 #include <GeomLProp_SLProps.hxx>
66 #include <gp.hxx>
67 #include <gp_Ax2.hxx>
68 #include <gp_Pln.hxx>
69 #include <Poly_PolygonOnTriangulation.hxx>
70 #include <Poly_Triangulation.hxx>
71 #include <Precision.hxx>
72 #include <ProjLib_ProjectedCurve.hxx>
73 #include <Standard_ErrorHandler.hxx>
74 #include <Standard_Real.hxx>
75 #include <TColgp_Array1OfPnt.hxx>
76 #include <TColgp_Array1OfPnt2d.hxx>
77 #include <TColStd_Array1OfReal.hxx>
78 #include <TColStd_MapOfTransient.hxx>
79 #include <TopExp.hxx>
80 #include <TopExp_Explorer.hxx>
81 #include <TopoDS.hxx>
82 #include <TopoDS_Edge.hxx>
83 #include <TopoDS_Face.hxx>
84 #include <TopoDS_Shape.hxx>
85 #include <TopoDS_Solid.hxx>
86 #include <TopoDS_Vertex.hxx>
87 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
88 #include <TopTools_ListIteratorOfListOfShape.hxx>
89 #include <TopTools_MapOfShape.hxx>
90 #include <TShort_HArray1OfShortReal.hxx>
91 #include <TColgp_Array1OfXY.hxx>
92 #include <BRepTools_ReShape.hxx>
93 #include <TopTools_DataMapOfShapeReal.hxx>
94 #include <TopoDS_LockedShape.hxx>
95
96 #include <algorithm>
97
98 // TODO - not thread-safe static variables
99 static Standard_Real thePrecision = Precision::Confusion();
100 static Handle(Geom_Plane) thePlane;
101
102 static void InternalUpdateTolerances(const TopoDS_Shape& theOldShape,
103 const Standard_Boolean IsVerifyTolerance, const Standard_Boolean IsMutableInput, BRepTools_ReShape& theReshaper);
104
105 //=======================================================================
106 // function: BRepLib_ComparePoints
107 // purpose: implementation of IsLess() function for two points
108 //=======================================================================
109 struct BRepLib_ComparePoints {
operator ()BRepLib_ComparePoints110 bool operator()(const gp_Pnt& theP1, const gp_Pnt& theP2)
111 {
112 for (Standard_Integer i = 1; i <= 3; ++i) {
113 if (theP1.Coord(i) < theP2.Coord(i)) {
114 return Standard_True;
115 }
116 else if (theP1.Coord(i) > theP2.Coord(i)) {
117 return Standard_False;
118 }
119 }
120 return Standard_False;
121 }
122 };
123
124
125 //=======================================================================
126 //function : Precision
127 //purpose :
128 //=======================================================================
129
Precision(const Standard_Real P)130 void BRepLib::Precision(const Standard_Real P)
131 {
132 thePrecision = P;
133 }
134
135 //=======================================================================
136 //function : Precision
137 //purpose :
138 //=======================================================================
139
Precision()140 Standard_Real BRepLib::Precision()
141 {
142 return thePrecision;
143 }
144
145 //=======================================================================
146 //function : Plane
147 //purpose :
148 //=======================================================================
149
Plane(const Handle (Geom_Plane)& P)150 void BRepLib::Plane(const Handle(Geom_Plane)& P)
151 {
152 thePlane = P;
153 }
154
155
156 //=======================================================================
157 //function : Plane
158 //purpose :
159 //=======================================================================
160
Handle(Geom_Plane)161 const Handle(Geom_Plane)& BRepLib::Plane()
162 {
163 if (thePlane.IsNull()) thePlane = new Geom_Plane(gp::XOY());
164 return thePlane;
165 }
166 //=======================================================================
167 //function : CheckSameRange
168 //purpose :
169 //=======================================================================
170
CheckSameRange(const TopoDS_Edge & AnEdge,const Standard_Real Tolerance)171 Standard_Boolean BRepLib::CheckSameRange(const TopoDS_Edge& AnEdge,
172 const Standard_Real Tolerance)
173 {
174 Standard_Boolean IsSameRange = Standard_True,
175 first_time_in = Standard_True ;
176
177 BRep_ListIteratorOfListOfCurveRepresentation an_Iterator
178 ((*((Handle(BRep_TEdge)*)&AnEdge.TShape()))->ChangeCurves());
179
180 Standard_Real first, last;
181 Standard_Real current_first =0., current_last =0. ;
182 Handle(BRep_GCurve) geometric_representation_ptr ;
183
184 while (IsSameRange && an_Iterator.More()) {
185 geometric_representation_ptr =
186 Handle(BRep_GCurve)::DownCast(an_Iterator.Value());
187 if (!geometric_representation_ptr.IsNull()) {
188
189 first = geometric_representation_ptr->First();
190 last = geometric_representation_ptr->Last();
191 if (first_time_in ) {
192 current_first = first ;
193 current_last = last ;
194 first_time_in = Standard_False ;
195 }
196 else {
197 IsSameRange = (Abs(current_first - first) <= Tolerance)
198 && (Abs(current_last -last) <= Tolerance ) ;
199 }
200 }
201 an_Iterator.Next() ;
202 }
203 return IsSameRange ;
204 }
205
206 //=======================================================================
207 //function : SameRange
208 //purpose :
209 //=======================================================================
210
SameRange(const TopoDS_Edge & AnEdge,const Standard_Real Tolerance)211 void BRepLib::SameRange(const TopoDS_Edge& AnEdge,
212 const Standard_Real Tolerance)
213 {
214 BRep_ListIteratorOfListOfCurveRepresentation an_Iterator
215 ((*((Handle(BRep_TEdge)*)&AnEdge.TShape()))->ChangeCurves());
216
217 Handle(Geom2d_Curve) Curve2dPtr, Curve2dPtr2, NewCurve2dPtr, NewCurve2dPtr2;
218 TopLoc_Location LocalLoc ;
219
220 Standard_Boolean first_time_in = Standard_True,
221 has_curve,
222 has_closed_curve ;
223 Handle(BRep_GCurve) geometric_representation_ptr ;
224 Standard_Real first,
225 current_first,
226 last,
227 current_last ;
228
229 const Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,
230 LocalLoc,
231 current_first,
232 current_last);
233 if (!C.IsNull()) {
234 first_time_in = Standard_False ;
235 }
236
237 while (an_Iterator.More()) {
238 geometric_representation_ptr =
239 Handle(BRep_GCurve)::DownCast(an_Iterator.Value());
240 if (! geometric_representation_ptr.IsNull()) {
241 has_closed_curve =
242 has_curve = Standard_False ;
243 first = geometric_representation_ptr->First();
244 last = geometric_representation_ptr->Last();
245 if (geometric_representation_ptr->IsCurveOnSurface()) {
246 Curve2dPtr = geometric_representation_ptr->PCurve() ;
247 has_curve = Standard_True ;
248 }
249 if (geometric_representation_ptr->IsCurveOnClosedSurface()) {
250 Curve2dPtr2 = geometric_representation_ptr->PCurve2() ;
251 has_closed_curve = Standard_True ;
252 }
253 if (has_curve || has_closed_curve) {
254 if (first_time_in) {
255 current_first = first ;
256 current_last = last ;
257 first_time_in = Standard_False ;
258 }
259
260 if (Abs(first - current_first) > Precision::Confusion() ||
261 Abs(last - current_last) > Precision::Confusion() )
262 {
263 if (has_curve)
264 {
265 GeomLib::SameRange(Tolerance,
266 Curve2dPtr,
267 geometric_representation_ptr->First(),
268 geometric_representation_ptr->Last(),
269 current_first,
270 current_last,
271 NewCurve2dPtr);
272 geometric_representation_ptr->PCurve(NewCurve2dPtr) ;
273 }
274 if (has_closed_curve)
275 {
276 GeomLib::SameRange(Tolerance,
277 Curve2dPtr2,
278 geometric_representation_ptr->First(),
279 geometric_representation_ptr->Last(),
280 current_first,
281 current_last,
282 NewCurve2dPtr2);
283 geometric_representation_ptr->PCurve2(NewCurve2dPtr2) ;
284 }
285 }
286 }
287 }
288 an_Iterator.Next() ;
289 }
290 BRep_Builder B;
291 B.Range(TopoDS::Edge(AnEdge),
292 current_first,
293 current_last) ;
294
295 B.SameRange(AnEdge,
296 Standard_True) ;
297 }
298
299 //=======================================================================
300 //function : EvaluateMaxSegment
301 //purpose : return MaxSegment to pass in approximation, if MaxSegment==0 provided
302 //=======================================================================
303
evaluateMaxSegment(const Standard_Integer aMaxSegment,const Adaptor3d_CurveOnSurface & aCurveOnSurface)304 static Standard_Integer evaluateMaxSegment(const Standard_Integer aMaxSegment,
305 const Adaptor3d_CurveOnSurface& aCurveOnSurface)
306 {
307 if (aMaxSegment != 0) return aMaxSegment;
308
309 Handle(Adaptor3d_Surface) aSurf = aCurveOnSurface.GetSurface();
310 Handle(Adaptor2d_Curve2d) aCurv2d = aCurveOnSurface.GetCurve();
311
312 Standard_Real aNbSKnots = 0, aNbC2dKnots = 0;
313
314 if (aSurf->GetType() == GeomAbs_BSplineSurface) {
315 Handle(Geom_BSplineSurface) aBSpline = aSurf->BSpline();
316 aNbSKnots = Max(aBSpline->NbUKnots(), aBSpline->NbVKnots());
317 }
318 if (aCurv2d->GetType() == GeomAbs_BSplineCurve) {
319 aNbC2dKnots = aCurv2d->NbKnots();
320 }
321 Standard_Integer aReturn = (Standard_Integer) ( 30 + Max(aNbSKnots, aNbC2dKnots) ) ;
322 return aReturn;
323 }
324
325 //=======================================================================
326 //function : BuildCurve3d
327 //purpose :
328 //=======================================================================
329
BuildCurve3d(const TopoDS_Edge & AnEdge,const Standard_Real Tolerance,const GeomAbs_Shape Continuity,const Standard_Integer MaxDegree,const Standard_Integer MaxSegment)330 Standard_Boolean BRepLib::BuildCurve3d(const TopoDS_Edge& AnEdge,
331 const Standard_Real Tolerance,
332 const GeomAbs_Shape Continuity,
333 const Standard_Integer MaxDegree,
334 const Standard_Integer MaxSegment)
335 {
336 Standard_Integer //ErrorCode,
337 // ReturnCode = 0,
338 ii,
339 // num_knots,
340 jj;
341
342 TopLoc_Location LocalLoc,L[2],LC;
343 Standard_Real f,l,fc,lc, first[2], last[2],
344 tolerance,
345 max_deviation,
346 average_deviation ;
347 Handle(Geom2d_Curve) Curve2dPtr, Curve2dArray[2] ;
348 Handle(Geom_Surface) SurfacePtr, SurfaceArray[2] ;
349
350 Standard_Integer not_done ;
351 // if the edge has a 3d curve returns true
352
353
354 const Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,LocalLoc,f,l);
355 if (!C.IsNull())
356 return Standard_True;
357 //
358 // this should not exists but UpdateEdge makes funny things
359 // if the edge is not same range
360 //
361 if (! CheckSameRange(AnEdge,
362 Precision::Confusion())) {
363 SameRange(AnEdge,
364 Tolerance) ;
365 }
366
367
368
369 // search a curve on a plane
370 Handle(Geom_Surface) S;
371 Handle(Geom2d_Curve) PC;
372 Standard_Integer i = 0;
373 Handle(Geom_Plane) P;
374 not_done = 1 ;
375
376 while (not_done) {
377 i++;
378 BRep_Tool::CurveOnSurface(AnEdge,PC,S,LocalLoc,f,l,i);
379 Handle(Geom_RectangularTrimmedSurface) RT =
380 Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
381 if ( RT.IsNull()) {
382 P = Handle(Geom_Plane)::DownCast(S);
383 }
384 else {
385 P = Handle(Geom_Plane)::DownCast(RT->BasisSurface());
386 }
387 not_done = ! (S.IsNull() || !P.IsNull()) ;
388 }
389 if (! P.IsNull()) {
390 // compute the 3d curve
391 gp_Ax2 axes = P->Position().Ax2();
392 Handle(Geom_Curve) C3d = GeomLib::To3d(axes,PC);
393 if (C3d.IsNull())
394 return Standard_False;
395 // update the edge
396 Standard_Real First, Last;
397
398 BRep_Builder B;
399 B.UpdateEdge(AnEdge,C3d,LocalLoc,0.0e0);
400 BRep_Tool::Range(AnEdge, S, LC, First, Last);
401 B.Range(AnEdge, First, Last); //Do not forget 3D range.(PRO6412)
402 }
403 else {
404 //
405 // compute the 3d curve using existing surface
406 //
407 fc = f ;
408 lc = l ;
409 if (!BRep_Tool::Degenerated(AnEdge)) {
410 jj = 0 ;
411 for (ii = 0 ; ii < 3 ; ii++ ) {
412 BRep_Tool::CurveOnSurface(TopoDS::Edge(AnEdge),
413 Curve2dPtr,
414 SurfacePtr,
415 LocalLoc,
416 fc,
417 lc,
418 ii) ;
419
420 if (!Curve2dPtr.IsNull() && jj < 2){
421 Curve2dArray[jj] = Curve2dPtr ;
422 SurfaceArray[jj] = SurfacePtr ;
423 L[jj] = LocalLoc ;
424 first[jj] = fc ;
425 last[jj] = lc ;
426 jj += 1 ;
427 }
428 }
429 f = first[0] ;
430 l = last[0] ;
431 Curve2dPtr = Curve2dArray[0] ;
432 SurfacePtr = SurfaceArray[0] ;
433
434 Geom2dAdaptor_Curve AnAdaptor3dCurve2d (Curve2dPtr, f, l) ;
435 GeomAdaptor_Surface AnAdaptor3dSurface (SurfacePtr) ;
436 Handle(Geom2dAdaptor_Curve) AnAdaptor3dCurve2dPtr =
437 new Geom2dAdaptor_Curve(AnAdaptor3dCurve2d) ;
438 Handle(GeomAdaptor_Surface) AnAdaptor3dSurfacePtr =
439 new GeomAdaptor_Surface (AnAdaptor3dSurface) ;
440 Adaptor3d_CurveOnSurface CurveOnSurface( AnAdaptor3dCurve2dPtr,
441 AnAdaptor3dSurfacePtr) ;
442
443 Handle(Geom_Curve) NewCurvePtr ;
444
445 GeomLib::BuildCurve3d(Tolerance,
446 CurveOnSurface,
447 f,
448 l,
449 NewCurvePtr,
450 max_deviation,
451 average_deviation,
452 Continuity,
453 MaxDegree,
454 evaluateMaxSegment(MaxSegment,CurveOnSurface)) ;
455 BRep_Builder B;
456 tolerance = BRep_Tool::Tolerance(AnEdge) ;
457 //Patch
458 //max_deviation = Max(tolerance, max_deviation) ;
459 max_deviation = Max( tolerance, Tolerance );
460 if (NewCurvePtr.IsNull())
461 return Standard_False;
462 B.UpdateEdge(TopoDS::Edge(AnEdge),
463 NewCurvePtr,
464 L[0],
465 max_deviation) ;
466 if (jj == 1 ) {
467 //
468 // if there is only one curve on surface attached to the edge
469 // than it can be qualified sameparameter
470 //
471 B.SameParameter(TopoDS::Edge(AnEdge),
472 Standard_True) ;
473 }
474 }
475 else {
476 return Standard_False ;
477 }
478
479 }
480 return Standard_True;
481 }
482 //=======================================================================
483 //function : BuildCurves3d
484 //purpose :
485 //=======================================================================
486
BuildCurves3d(const TopoDS_Shape & S)487 Standard_Boolean BRepLib::BuildCurves3d(const TopoDS_Shape& S)
488
489 {
490 return BRepLib::BuildCurves3d(S,
491 1.0e-5) ;
492 }
493
494 //=======================================================================
495 //function : BuildCurves3d
496 //purpose :
497 //=======================================================================
498
BuildCurves3d(const TopoDS_Shape & S,const Standard_Real Tolerance,const GeomAbs_Shape Continuity,const Standard_Integer MaxDegree,const Standard_Integer MaxSegment)499 Standard_Boolean BRepLib::BuildCurves3d(const TopoDS_Shape& S,
500 const Standard_Real Tolerance,
501 const GeomAbs_Shape Continuity,
502 const Standard_Integer MaxDegree,
503 const Standard_Integer MaxSegment)
504 {
505 Standard_Boolean boolean_value,
506 ok = Standard_True;
507 TopTools_MapOfShape a_counter ;
508 TopExp_Explorer ex(S,TopAbs_EDGE);
509
510 while (ex.More()) {
511 if (a_counter.Add(ex.Current())) {
512 boolean_value =
513 BuildCurve3d(TopoDS::Edge(ex.Current()),
514 Tolerance, Continuity,
515 MaxDegree, MaxSegment);
516 ok = ok && boolean_value ;
517 }
518 ex.Next();
519 }
520 return ok;
521 }
522 //=======================================================================
523 //function : UpdateEdgeTolerance
524 //purpose :
525 //=======================================================================
526
UpdateEdgeTol(const TopoDS_Edge & AnEdge,const Standard_Real MinToleranceRequested,const Standard_Real MaxToleranceToCheck)527 Standard_Boolean BRepLib::UpdateEdgeTol(const TopoDS_Edge& AnEdge,
528 const Standard_Real MinToleranceRequested,
529 const Standard_Real MaxToleranceToCheck)
530 {
531
532 Standard_Integer curve_on_surface_index,
533 curve_index,
534 not_done,
535 has_closed_curve,
536 has_curve,
537 jj,
538 ii,
539 geom_reference_curve_flag = 0,
540 max_sampling_points = 90,
541 min_sampling_points = 30 ;
542
543 Standard_Real factor = 100.0e0,
544 // sampling_array[2],
545 safe_factor = 1.4e0,
546 current_last,
547 current_first,
548 max_distance,
549 coded_edge_tolerance,
550 edge_tolerance = 0.0e0 ;
551 Handle(TColStd_HArray1OfReal) parameters_ptr ;
552 Handle(BRep_GCurve) geometric_representation_ptr ;
553
554 if (BRep_Tool::Degenerated(AnEdge)) return Standard_False ;
555 coded_edge_tolerance = BRep_Tool::Tolerance(AnEdge) ;
556 if (coded_edge_tolerance > MaxToleranceToCheck) return Standard_False ;
557
558 const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&AnEdge.TShape());
559 BRep_ListOfCurveRepresentation& list_curve_rep = TE->ChangeCurves() ;
560 BRep_ListIteratorOfListOfCurveRepresentation an_iterator(list_curve_rep),
561 second_iterator(list_curve_rep) ;
562 Handle(Geom2d_Curve) curve2d_ptr, new_curve2d_ptr;
563 Handle(Geom_Surface) surface_ptr ;
564 TopLoc_Location local_location ;
565 GCPnts_QuasiUniformDeflection a_sampler ;
566 GeomAdaptor_Curve geom_reference_curve ;
567 Adaptor3d_CurveOnSurface curve_on_surface_reference ;
568 Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,
569 local_location,
570 current_first,
571 current_last);
572 curve_on_surface_index = -1 ;
573 if (!C.IsNull()) {
574 if (! local_location.IsIdentity()) {
575 C = Handle(Geom_Curve)::
576 DownCast(C-> Transformed(local_location.Transformation()) ) ;
577 }
578 geom_reference_curve.Load(C) ;
579 geom_reference_curve_flag = 1 ;
580 a_sampler.Initialize(geom_reference_curve,
581 MinToleranceRequested * factor,
582 current_first,
583 current_last) ;
584 }
585 else {
586 not_done = 1 ;
587 curve_on_surface_index = 0 ;
588
589 while (not_done && an_iterator.More()) {
590 geometric_representation_ptr =
591 Handle(BRep_GCurve)::DownCast(second_iterator.Value());
592 if (!geometric_representation_ptr.IsNull()
593 && geometric_representation_ptr->IsCurveOnSurface()) {
594 curve2d_ptr = geometric_representation_ptr->PCurve() ;
595 local_location = geometric_representation_ptr->Location() ;
596 current_first = geometric_representation_ptr->First();
597 //first = geometric_representation_ptr->First();
598 current_last = geometric_representation_ptr->Last();
599 // must be inverted
600 //
601 if (! local_location.IsIdentity() ) {
602 surface_ptr = Handle(Geom_Surface)::
603 DownCast( geometric_representation_ptr->Surface()->
604 Transformed(local_location.Transformation()) ) ;
605 }
606 else {
607 surface_ptr =
608 geometric_representation_ptr->Surface() ;
609 }
610 not_done = 0 ;
611 }
612 curve_on_surface_index += 1 ;
613 }
614 Geom2dAdaptor_Curve AnAdaptor3dCurve2d (curve2d_ptr) ;
615 GeomAdaptor_Surface AnAdaptor3dSurface (surface_ptr) ;
616 Handle(Geom2dAdaptor_Curve) AnAdaptor3dCurve2dPtr =
617 new Geom2dAdaptor_Curve(AnAdaptor3dCurve2d) ;
618 Handle(GeomAdaptor_Surface) AnAdaptor3dSurfacePtr =
619 new GeomAdaptor_Surface (AnAdaptor3dSurface) ;
620 curve_on_surface_reference.Load (AnAdaptor3dCurve2dPtr, AnAdaptor3dSurfacePtr);
621 a_sampler.Initialize(curve_on_surface_reference,
622 MinToleranceRequested * factor,
623 current_first,
624 current_last) ;
625 }
626 TColStd_Array1OfReal sampling_parameters(1,a_sampler.NbPoints()) ;
627 for (ii = 1 ; ii <= a_sampler.NbPoints() ; ii++) {
628 sampling_parameters(ii) = a_sampler.Parameter(ii) ;
629 }
630 if (a_sampler.NbPoints() < min_sampling_points) {
631 GeomLib::DensifyArray1OfReal(min_sampling_points,
632 sampling_parameters,
633 parameters_ptr) ;
634 }
635 else if (a_sampler.NbPoints() > max_sampling_points) {
636 GeomLib::RemovePointsFromArray(max_sampling_points,
637 sampling_parameters,
638 parameters_ptr) ;
639 }
640 else {
641 jj = 1 ;
642 parameters_ptr =
643 new TColStd_HArray1OfReal(1,sampling_parameters.Length()) ;
644 for (ii = sampling_parameters.Lower() ; ii <= sampling_parameters.Upper() ; ii++) {
645 parameters_ptr->ChangeArray1()(jj) =
646 sampling_parameters(ii) ;
647 jj +=1 ;
648 }
649 }
650
651 curve_index = 0 ;
652
653 while (second_iterator.More()) {
654 geometric_representation_ptr =
655 Handle(BRep_GCurve)::DownCast(second_iterator.Value());
656 if (! geometric_representation_ptr.IsNull() &&
657 curve_index != curve_on_surface_index) {
658 has_closed_curve =
659 has_curve = Standard_False ;
660 // first = geometric_representation_ptr->First();
661 // last = geometric_representation_ptr->Last();
662 local_location = geometric_representation_ptr->Location() ;
663 if (geometric_representation_ptr->IsCurveOnSurface()) {
664 curve2d_ptr = geometric_representation_ptr->PCurve() ;
665 has_curve = Standard_True ;
666 }
667 if (geometric_representation_ptr->IsCurveOnClosedSurface()) {
668 curve2d_ptr = geometric_representation_ptr->PCurve2() ;
669 has_closed_curve = Standard_True ;
670 }
671
672 if (has_curve ||
673 has_closed_curve) {
674 if (! local_location.IsIdentity() ) {
675 surface_ptr = Handle(Geom_Surface)::
676 DownCast( geometric_representation_ptr->Surface()->
677 Transformed(local_location.Transformation()) ) ;
678 }
679 else {
680 surface_ptr =
681 geometric_representation_ptr->Surface() ;
682 }
683 Geom2dAdaptor_Curve an_adaptor_curve2d (curve2d_ptr) ;
684 GeomAdaptor_Surface an_adaptor_surface(surface_ptr) ;
685 Handle(Geom2dAdaptor_Curve) an_adaptor_curve2d_ptr =
686 new Geom2dAdaptor_Curve(an_adaptor_curve2d) ;
687 Handle(GeomAdaptor_Surface) an_adaptor_surface_ptr =
688 new GeomAdaptor_Surface (an_adaptor_surface) ;
689 Adaptor3d_CurveOnSurface a_curve_on_surface(an_adaptor_curve2d_ptr,
690 an_adaptor_surface_ptr) ;
691
692 if (BRep_Tool::SameParameter(AnEdge)) {
693
694 GeomLib::EvalMaxParametricDistance(a_curve_on_surface,
695 geom_reference_curve,
696 MinToleranceRequested,
697 parameters_ptr->Array1(),
698 max_distance) ;
699 }
700 else if (geom_reference_curve_flag) {
701 GeomLib::EvalMaxDistanceAlongParameter(a_curve_on_surface,
702 geom_reference_curve,
703 MinToleranceRequested,
704 parameters_ptr->Array1(),
705 max_distance) ;
706 }
707 else {
708
709 GeomLib::EvalMaxDistanceAlongParameter(a_curve_on_surface,
710 curve_on_surface_reference,
711 MinToleranceRequested,
712 parameters_ptr->Array1(),
713 max_distance) ;
714 }
715 max_distance *= safe_factor ;
716 edge_tolerance = Max(max_distance, edge_tolerance) ;
717 }
718
719
720 }
721 curve_index += 1 ;
722 second_iterator.Next() ;
723 }
724
725 TE->Tolerance(edge_tolerance);
726 return Standard_True ;
727
728 }
729 //=======================================================================
730 //function : UpdateEdgeTolerance
731 //purpose :
732 //=======================================================================
UpdateEdgeTolerance(const TopoDS_Shape & S,const Standard_Real MinToleranceRequested,const Standard_Real MaxToleranceToCheck)733 Standard_Boolean BRepLib::UpdateEdgeTolerance(const TopoDS_Shape& S,
734 const Standard_Real MinToleranceRequested,
735 const Standard_Real MaxToleranceToCheck)
736 {
737 TopExp_Explorer ex(S,TopAbs_EDGE);
738 TopTools_MapOfShape a_counter ;
739
740 Standard_Boolean return_status = Standard_False,
741 local_flag ;
742
743 while (ex.More()) {
744 if (a_counter.Add(ex.Current())) {
745 local_flag =
746 BRepLib::UpdateEdgeTol(TopoDS::Edge(ex.Current()),
747 MinToleranceRequested,
748 MaxToleranceToCheck) ;
749 if (local_flag && ! return_status) {
750 return_status = Standard_True ;
751 }
752 }
753 ex.Next();
754 }
755 return return_status ;
756 }
757
758 //=======================================================================
759 //function : GetEdgeTol
760 //purpose :
761 //=======================================================================
GetEdgeTol(const TopoDS_Edge & theEdge,const TopoDS_Face & theFace,Standard_Real & theEdTol)762 static void GetEdgeTol(const TopoDS_Edge& theEdge,
763 const TopoDS_Face& theFace, Standard_Real& theEdTol)
764 {
765 TopLoc_Location L;
766 const Handle(Geom_Surface)& S = BRep_Tool::Surface(theFace,L);
767 TopLoc_Location l = L.Predivided(theEdge.Location());
768
769 const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&theEdge.TShape());
770 BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
771
772 while (itcr.More()) {
773 const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
774 if(cr->IsCurveOnSurface(S,l)) return;
775 itcr.Next();
776 }
777
778 Handle(Geom_Plane) GP;
779 Handle(Geom_RectangularTrimmedSurface) GRTS;
780 GRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
781 if(!GRTS.IsNull())
782 GP = Handle(Geom_Plane)::DownCast(GRTS->BasisSurface());
783 else
784 GP = Handle(Geom_Plane)::DownCast(S);
785
786 Handle(GeomAdaptor_Curve) HC = new GeomAdaptor_Curve();
787 Handle(GeomAdaptor_Surface) HS = new GeomAdaptor_Surface();
788
789 TopLoc_Location LC;
790 Standard_Real First, Last;
791 HC->Load(BRep_Tool::Curve(theEdge,LC,First,Last));
792 LC = L.Predivided(LC);
793
794 if (!LC.IsIdentity()) {
795 GP = Handle(Geom_Plane)::DownCast(
796 GP->Transformed(LC.Transformation()));
797 }
798 GeomAdaptor_Surface& GAS = *HS;
799 GAS.Load(GP);
800
801 ProjLib_ProjectedCurve Proj(HS,HC);
802 Handle(Geom2d_Curve) pc = Geom2dAdaptor::MakeCurve(Proj);
803
804 gp_Pln pln = GAS.Plane();
805 Standard_Real d2 = 0.;
806 Standard_Integer nn = 23;
807 Standard_Real unsurnn = 1./nn;
808 for(Standard_Integer i = 0; i <= nn; i++){
809 Standard_Real t = unsurnn*i;
810 Standard_Real u = First*(1.-t) + Last*t;
811 gp_Pnt Pc3d = HC->Value(u);
812 gp_Pnt2d p2d = pc->Value(u);
813 gp_Pnt Pcons = ElSLib::Value(p2d.X(),p2d.Y(),pln);
814 Standard_Real eps = Max(Pc3d.XYZ().SquareModulus(), Pcons.XYZ().SquareModulus());
815 eps = Epsilon(eps);
816 Standard_Real temp = Pc3d.SquareDistance(Pcons);
817 if(temp <= eps)
818 {
819 temp = 0.;
820 }
821 if(temp > d2) d2 = temp;
822 }
823 d2 = 1.5*sqrt(d2);
824 theEdTol = d2;
825 }
826
827 //=======================================================================
828 //function : UpdTolMap
829 //purpose : Update map ShToTol (shape to tolerance)
830 //=======================================================================
UpdTolMap(const TopoDS_Shape & theSh,Standard_Real theNewTol,TopTools_DataMapOfShapeReal & theShToTol)831 static void UpdTolMap(const TopoDS_Shape& theSh, Standard_Real theNewTol,
832 TopTools_DataMapOfShapeReal& theShToTol)
833 {
834 TopAbs_ShapeEnum aSt = theSh.ShapeType();
835 Standard_Real aShTol;
836 if (aSt == TopAbs_VERTEX)
837 aShTol = BRep_Tool::Tolerance(TopoDS::Vertex(theSh));
838 else if (aSt == TopAbs_EDGE)
839 aShTol = BRep_Tool::Tolerance(TopoDS::Edge(theSh));
840 else
841 return;
842 //
843 if (theNewTol > aShTol)
844 {
845 const Standard_Real* anOldtol = theShToTol.Seek(theSh);
846 if (!anOldtol)
847 theShToTol.Bind(theSh, theNewTol);
848 else
849 theShToTol(theSh) = Max(*anOldtol, theNewTol);
850 }
851 }
852
853 //=======================================================================
854 //function : UpdShTol
855 //purpose : Update vertices/edges/faces according to ShToTol map (create copies of necessary)
856 //=======================================================================
UpdShTol(const TopTools_DataMapOfShapeReal & theShToTol,const Standard_Boolean IsMutableInput,BRepTools_ReShape & theReshaper,Standard_Boolean theVForceUpdate)857 static void UpdShTol(const TopTools_DataMapOfShapeReal& theShToTol,
858 const Standard_Boolean IsMutableInput, BRepTools_ReShape& theReshaper,
859 Standard_Boolean theVForceUpdate)
860 {
861 BRep_Builder aB;
862 TopTools_DataMapIteratorOfDataMapOfShapeReal SHToTolit(theShToTol);
863 for (;SHToTolit.More();SHToTolit.Next())
864 {
865 const TopoDS_Shape& aSh = SHToTolit.Key();
866 Standard_Real aTol = SHToTolit.Value();
867 //
868 TopoDS_Shape aNsh;
869 const TopoDS_Shape& aVsh = theReshaper.Value(aSh);
870 Standard_Boolean UseOldSh = IsMutableInput || theReshaper.IsNewShape(aSh) || !aVsh.IsSame(aSh);
871 if (UseOldSh)
872 aNsh = aVsh;
873 else
874 {
875 aNsh = aSh.EmptyCopied();
876 //add subshapes from the original shape
877 TopoDS_Iterator sit(aSh);
878 for (;sit.More();sit.Next())
879 aB.Add(aNsh, sit.Value());
880 //
881 aNsh.Free(aSh.Free());
882 aNsh.Checked(aSh.Checked());
883 aNsh.Orientable(aSh.Orientable());
884 aNsh.Closed(aSh.Closed());
885 aNsh.Infinite(aSh.Infinite());
886 aNsh.Convex(aSh.Convex());
887 //
888 }
889 //
890 switch (aSh.ShapeType())
891 {
892 case TopAbs_FACE:
893 {
894 aB.UpdateFace(TopoDS::Face(aNsh), aTol);
895 break;
896 }
897 case TopAbs_EDGE:
898 {
899 aB.UpdateEdge(TopoDS::Edge(aNsh), aTol);
900 break;
901 }
902 case TopAbs_VERTEX:
903 {
904 const Handle(BRep_TVertex)& aTV = *((Handle(BRep_TVertex)*)&aNsh.TShape());
905 //
906 if(aTV->Locked())
907 throw TopoDS_LockedShape("BRep_Builder::UpdateVertex");
908 //
909 if (theVForceUpdate)
910 aTV->Tolerance(aTol);
911 else
912 aTV->UpdateTolerance(aTol);
913 aTV->Modified(Standard_True);
914 break;
915 }
916 default:
917 break;
918 }
919 //
920 if (!UseOldSh)
921 theReshaper.Replace(aSh, aNsh);
922 }
923 }
924
925 //=======================================================================
926 //function : InternalSameParameter
927 //purpose :
928 //=======================================================================
InternalSameParameter(const TopoDS_Shape & theSh,BRepTools_ReShape & theReshaper,const Standard_Real theTol,const Standard_Boolean IsForced,const Standard_Boolean IsMutableInput)929 static void InternalSameParameter(const TopoDS_Shape& theSh, BRepTools_ReShape& theReshaper,
930 const Standard_Real theTol, const Standard_Boolean IsForced, const Standard_Boolean IsMutableInput )
931 {
932 TopExp_Explorer ex(theSh,TopAbs_EDGE);
933 TopTools_MapOfShape Done;
934 BRep_Builder aB;
935 TopTools_DataMapOfShapeReal aShToTol;
936
937 while (ex.More())
938 {
939 const TopoDS_Edge& aCE = TopoDS::Edge(ex.Current());
940 if (Done.Add(aCE))
941 {
942 TopoDS_Edge aNE = TopoDS::Edge(theReshaper.Value(aCE));
943 Standard_Boolean UseOldEdge = IsMutableInput || theReshaper.IsNewShape(aCE) || !aNE.IsSame(aCE);
944 if (IsForced && (BRep_Tool::SameRange(aCE) || BRep_Tool::SameParameter(aCE)))
945 {
946 if (!UseOldEdge)
947 {
948 aNE = TopoDS::Edge(aCE.EmptyCopied());
949 TopoDS_Iterator sit(aCE);
950 for (;sit.More();sit.Next())
951 aB.Add(aNE, sit.Value());
952 theReshaper.Replace(aCE, aNE);
953 UseOldEdge = Standard_True;
954 }
955 aB.SameRange(aNE, Standard_False);
956 aB.SameParameter(aNE, Standard_False);
957 }
958 Standard_Real aNewTol = -1;
959 TopoDS_Edge aResEdge = BRepLib::SameParameter(aNE, theTol, aNewTol, UseOldEdge);
960 if (!UseOldEdge && !aResEdge.IsNull())
961 //NE have been empty-copied
962 theReshaper.Replace(aNE, aResEdge);
963 if (aNewTol > 0)
964 {
965 TopoDS_Vertex aV1, aV2;
966 TopExp::Vertices(aCE,aV1,aV2);
967 if (!aV1.IsNull())
968 UpdTolMap(aV1, aNewTol, aShToTol);
969 if (!aV2.IsNull())
970 UpdTolMap(aV2, aNewTol, aShToTol);
971 }
972 }
973 ex.Next();
974 }
975
976 Done.Clear();
977 BRepAdaptor_Surface BS;
978 for(ex.Init(theSh,TopAbs_FACE); ex.More(); ex.Next()){
979 const TopoDS_Face& curface = TopoDS::Face(ex.Current());
980 if(!Done.Add(curface)) continue;
981 BS.Initialize(curface);
982 if(BS.GetType() != GeomAbs_Plane) continue;
983 TopExp_Explorer ex2;
984 for(ex2.Init(curface,TopAbs_EDGE); ex2.More(); ex2.Next()){
985 const TopoDS_Edge& E = TopoDS::Edge(ex2.Current());
986 TopoDS_Shape aNe = theReshaper.Value(E);
987 Standard_Real aNewEtol = -1;
988 GetEdgeTol(TopoDS::Edge(aNe), curface, aNewEtol);
989 if (aNewEtol >= 0) //not equal to -1
990 UpdTolMap(E, aNewEtol, aShToTol);
991 }
992 }
993
994 //
995 UpdShTol(aShToTol, IsMutableInput, theReshaper, Standard_False );
996
997 InternalUpdateTolerances(theSh, Standard_False, IsMutableInput, theReshaper );
998 }
999
1000 //================================================================
1001 //function : SameParameter
1002 //WARNING : New spec DUB LBO 9/9/97.
1003 // Recode in the edge the best tolerance found,
1004 // for vertex extremities it is required to find something else
1005 //================================================================
SameParameter(const TopoDS_Shape & S,const Standard_Real Tolerance,const Standard_Boolean forced)1006 void BRepLib::SameParameter(const TopoDS_Shape& S,
1007 const Standard_Real Tolerance,
1008 const Standard_Boolean forced)
1009 {
1010 BRepTools_ReShape reshaper;
1011 InternalSameParameter( S, reshaper, Tolerance, forced, Standard_True);
1012 }
1013
1014 //=======================================================================
1015 //function : SameParameter
1016 //purpose :
1017 //=======================================================================
SameParameter(const TopoDS_Shape & S,BRepTools_ReShape & theReshaper,const Standard_Real Tolerance,const Standard_Boolean forced)1018 void BRepLib::SameParameter(const TopoDS_Shape& S, BRepTools_ReShape& theReshaper,
1019 const Standard_Real Tolerance, const Standard_Boolean forced )
1020 {
1021 InternalSameParameter( S, theReshaper, Tolerance, forced, Standard_False);
1022 }
1023
1024 //=======================================================================
1025 //function : EvalTol
1026 //purpose :
1027 //=======================================================================
EvalTol(const Handle (Geom2d_Curve)& pc,const Handle (Geom_Surface)& s,const GeomAdaptor_Curve & gac,const Standard_Real tol,Standard_Real & tolbail)1028 static Standard_Boolean EvalTol(const Handle(Geom2d_Curve)& pc,
1029 const Handle(Geom_Surface)& s,
1030 const GeomAdaptor_Curve& gac,
1031 const Standard_Real tol,
1032 Standard_Real& tolbail)
1033 {
1034 Standard_Integer ok = 0;
1035 Standard_Real f = gac.FirstParameter();
1036 Standard_Real l = gac.LastParameter();
1037 Extrema_LocateExtPC Projector;
1038 Projector.Initialize(gac,f,l,tol);
1039 Standard_Real u,v;
1040 gp_Pnt p;
1041 tolbail = tol;
1042 for(Standard_Integer i = 1; i <= 5; i++){
1043 Standard_Real t = i/6.;
1044 t = (1.-t) * f + t * l;
1045 pc->Value(t).Coord(u,v);
1046 p = s->Value(u,v);
1047 Projector.Perform(p,t);
1048 if (Projector.IsDone()) {
1049 Standard_Real dist2 = Projector.SquareDistance();
1050 if(dist2 > tolbail * tolbail) tolbail = sqrt (dist2);
1051 ok++;
1052 }
1053 }
1054 return (ok > 2);
1055 }
1056
1057 //=======================================================================
1058 //function : ComputeTol
1059 //purpose :
1060 //=======================================================================
ComputeTol(const Handle (Adaptor3d_Curve)& c3d,const Handle (Adaptor2d_Curve2d)& c2d,const Handle (Adaptor3d_Surface)& surf,const Standard_Integer nbp)1061 static Standard_Real ComputeTol(const Handle(Adaptor3d_Curve)& c3d,
1062 const Handle(Adaptor2d_Curve2d)& c2d,
1063 const Handle(Adaptor3d_Surface)& surf,
1064 const Standard_Integer nbp)
1065
1066 {
1067
1068 TColStd_Array1OfReal dist(1,nbp+10);
1069 dist.Init(-1.);
1070
1071 //Adaptor3d_CurveOnSurface cons(c2d,surf);
1072 Standard_Real uf = surf->FirstUParameter(), ul = surf->LastUParameter(),
1073 vf = surf->FirstVParameter(), vl = surf->LastVParameter();
1074 Standard_Real du = 0.01 * (ul - uf), dv = 0.01 * (vl - vf);
1075 Standard_Boolean isUPeriodic = surf->IsUPeriodic(), isVPeriodic = surf->IsVPeriodic();
1076 Standard_Real DSdu = 1./surf->UResolution(1.), DSdv = 1./surf->VResolution(1.);
1077 Standard_Real d2 = 0.;
1078 Standard_Real first = c3d->FirstParameter();
1079 Standard_Real last = c3d->LastParameter();
1080 Standard_Real dapp = -1.;
1081 for (Standard_Integer i = 0; i <= nbp; ++i)
1082 {
1083 const Standard_Real t = IntToReal(i)/IntToReal(nbp);
1084 const Standard_Real u = first*(1.-t) + last*t;
1085 gp_Pnt Pc3d = c3d->Value(u);
1086 gp_Pnt2d Puv = c2d->Value(u);
1087 if(!isUPeriodic)
1088 {
1089 if(Puv.X() < uf - du)
1090 {
1091 dapp = Max(dapp, DSdu * (uf - Puv.X()));
1092 continue;
1093 }
1094 else if(Puv.X() > ul + du)
1095 {
1096 dapp = Max(dapp, DSdu * (Puv.X() - ul));
1097 continue;
1098 }
1099 }
1100 if(!isVPeriodic)
1101 {
1102 if(Puv.Y() < vf - dv)
1103 {
1104 dapp = Max(dapp, DSdv * (vf - Puv.Y()));
1105 continue;
1106 }
1107 else if(Puv.Y() > vl + dv)
1108 {
1109 dapp = Max(dapp, DSdv * (Puv.Y() - vl));
1110 continue;
1111 }
1112 }
1113 gp_Pnt Pcons = surf->Value(Puv.X(), Puv.Y());
1114 if (Precision::IsInfinite(Pcons.X()) ||
1115 Precision::IsInfinite(Pcons.Y()) ||
1116 Precision::IsInfinite(Pcons.Z()))
1117 {
1118 d2 = Precision::Infinite();
1119 break;
1120 }
1121 Standard_Real temp = Pc3d.SquareDistance(Pcons);
1122
1123 dist(i+1) = temp;
1124
1125 d2 = Max (d2, temp);
1126 }
1127
1128 if(Precision::IsInfinite(d2))
1129 {
1130 return d2;
1131 }
1132
1133 d2 = Sqrt(d2);
1134 if(dapp > d2)
1135 {
1136 return dapp;
1137 }
1138
1139 Standard_Boolean ana = Standard_False;
1140 Standard_Real D2 = 0;
1141 Standard_Integer N1 = 0;
1142 Standard_Integer N2 = 0;
1143 Standard_Integer N3 = 0;
1144
1145 for (Standard_Integer i = 1; i<= nbp+10; ++i)
1146 {
1147 if (dist(i) > 0)
1148 {
1149 if (dist(i) < 1.0)
1150 {
1151 ++N1;
1152 }
1153 else
1154 {
1155 ++N2;
1156 }
1157 }
1158 }
1159
1160 if (N1 > N2 && N2 != 0)
1161 {
1162 N3 = 100*N2/(N1+N2);
1163 }
1164 if (N3 < 10 && N3 != 0)
1165 {
1166 ana = Standard_True;
1167 for (Standard_Integer i = 1; i <= nbp+10; ++i)
1168 {
1169 if (dist(i) > 0 && dist(i) < 1.0)
1170 {
1171 D2 = Max (D2, dist(i));
1172 }
1173 }
1174 }
1175
1176 //d2 = 1.5*sqrt(d2);
1177 d2 = (!ana) ? 1.5 * d2 : 1.5*sqrt(D2);
1178 d2 = Max (d2, 1.e-7);
1179 return d2;
1180 }
1181
1182 //=======================================================================
1183 //function : GetCurve3d
1184 //purpose :
1185 //=======================================================================
GetCurve3d(const TopoDS_Edge & theEdge,Handle (Geom_Curve)& theC3d,Standard_Real & theF3d,Standard_Real & theL3d,TopLoc_Location & theLoc3d,BRep_ListOfCurveRepresentation & theCList)1186 static void GetCurve3d(const TopoDS_Edge& theEdge, Handle(Geom_Curve)& theC3d, Standard_Real& theF3d,
1187 Standard_Real& theL3d, TopLoc_Location& theLoc3d, BRep_ListOfCurveRepresentation& theCList)
1188 {
1189 const Handle(BRep_TEdge)& aTE = *((Handle(BRep_TEdge)*) &theEdge.TShape());
1190 theCList = aTE->ChangeCurves(); // current function (i.e. GetCurve3d()) will not change any of this curves
1191 BRep_ListIteratorOfListOfCurveRepresentation anIt(theCList);
1192 Standard_Boolean NotDone = Standard_True;
1193 while (NotDone && anIt.More()) {
1194 Handle(BRep_GCurve) GCurve = Handle(BRep_GCurve)::DownCast(anIt.Value());
1195 if (!GCurve.IsNull() && GCurve->IsCurve3D()) {
1196 theC3d = GCurve->Curve3D() ;
1197 theF3d = GCurve->First();
1198 theL3d = GCurve->Last();
1199 theLoc3d = GCurve->Location() ;
1200 NotDone = Standard_False;
1201 }
1202 anIt.Next() ;
1203 }
1204 }
1205
1206 //=======================================================================
1207 //function : UpdateVTol
1208 //purpose :
1209 //=======================================================================
UpdateVTol(const TopoDS_Vertex theV1,const TopoDS_Vertex & theV2,Standard_Real theTol)1210 void UpdateVTol(const TopoDS_Vertex theV1, const TopoDS_Vertex& theV2, Standard_Real theTol)
1211 {
1212 BRep_Builder aB;
1213 if (!theV1.IsNull())
1214 aB.UpdateVertex(theV1,theTol);
1215 if (!theV2.IsNull())
1216 aB.UpdateVertex(theV2,theTol);
1217 }
1218
1219 //=======================================================================
1220 //function : SameParameter
1221 //purpose :
1222 //=======================================================================
SameParameter(const TopoDS_Edge & theEdge,const Standard_Real theTolerance)1223 void BRepLib::SameParameter(const TopoDS_Edge& theEdge,
1224 const Standard_Real theTolerance)
1225 {
1226 Standard_Real aNewTol = -1;
1227 SameParameter(theEdge, theTolerance, aNewTol, Standard_True);
1228 if (aNewTol > 0)
1229 {
1230 TopoDS_Vertex aV1, aV2;
1231 TopExp::Vertices(theEdge,aV1,aV2);
1232 UpdateVTol(aV1, aV2, aNewTol);
1233 }
1234 }
1235
1236 //=======================================================================
1237 //function : SameParameter
1238 //purpose :
1239 //=======================================================================
SameParameter(const TopoDS_Edge & theEdge,const Standard_Real theTolerance,Standard_Real & theNewTol,Standard_Boolean IsUseOldEdge)1240 TopoDS_Edge BRepLib::SameParameter(const TopoDS_Edge& theEdge,
1241 const Standard_Real theTolerance, Standard_Real& theNewTol, Standard_Boolean IsUseOldEdge)
1242 {
1243 if (BRep_Tool::SameParameter(theEdge))
1244 return TopoDS_Edge();
1245 Standard_Real f3d =0.,l3d =0.;
1246 TopLoc_Location L3d;
1247 Handle(Geom_Curve) C3d;
1248 BRep_ListOfCurveRepresentation CList;
1249 GetCurve3d(theEdge, C3d, f3d, l3d, L3d, CList);
1250 if(C3d.IsNull())
1251 return TopoDS_Edge();
1252
1253 BRep_Builder B;
1254 TopoDS_Edge aNE;
1255 Handle(BRep_TEdge) aNTE;
1256 if (IsUseOldEdge)
1257 {
1258 aNE = theEdge;
1259 aNTE = *((Handle(BRep_TEdge)*) &theEdge.TShape());
1260 }
1261 else
1262 {
1263 aNE = TopoDS::Edge(theEdge.EmptyCopied()); //will be modified a little bit later, so copy anyway
1264 GetCurve3d(aNE, C3d, f3d, l3d, L3d, CList); //C3d pointer and CList will be differ after copying
1265 aNTE = *((Handle(BRep_TEdge)*) &aNE.TShape());
1266 TopoDS_Iterator sit(theEdge);
1267 for (;sit.More();sit.Next()) //add vertices from old edge to the new ones
1268 B.Add(aNE, sit.Value());
1269 }
1270
1271 BRep_ListIteratorOfListOfCurveRepresentation It(CList);
1272
1273 const Standard_Integer NCONTROL = 22;
1274
1275 Handle(GeomAdaptor_Curve) HC = new GeomAdaptor_Curve();
1276 Handle(Geom2dAdaptor_Curve) HC2d = new Geom2dAdaptor_Curve();
1277 Handle(GeomAdaptor_Surface) HS = new GeomAdaptor_Surface();
1278 GeomAdaptor_Curve& GAC = *HC;
1279 Geom2dAdaptor_Curve& GAC2d = *HC2d;
1280 GeomAdaptor_Surface& GAS = *HS;
1281
1282 // modified by NIZHNY-OCC486 Tue Aug 27 17:15:13 2002 :
1283 Standard_Boolean m_TrimmedPeriodical = Standard_False;
1284 Handle(Standard_Type) TheType = C3d->DynamicType();
1285 if( TheType == STANDARD_TYPE(Geom_TrimmedCurve))
1286 {
1287 Handle(Geom_Curve) gtC (Handle(Geom_TrimmedCurve)::DownCast (C3d)->BasisCurve());
1288 m_TrimmedPeriodical = gtC->IsPeriodic();
1289 }
1290 // modified by NIZHNY-OCC486 Tue Aug 27 17:15:17 2002 .
1291
1292
1293 if(!C3d->IsPeriodic()) {
1294 Standard_Real Udeb = C3d->FirstParameter();
1295 Standard_Real Ufin = C3d->LastParameter();
1296 // modified by NIZHNY-OCC486 Tue Aug 27 17:17:14 2002 :
1297 //if (Udeb > f3d) f3d = Udeb;
1298 //if (l3d > Ufin) l3d = Ufin;
1299 if(!m_TrimmedPeriodical)
1300 {
1301 if (Udeb > f3d) f3d = Udeb;
1302 if (l3d > Ufin) l3d = Ufin;
1303 }
1304 // modified by NIZHNY-OCC486 Tue Aug 27 17:17:55 2002 .
1305 }
1306 if(!L3d.IsIdentity()){
1307 C3d = Handle(Geom_Curve)::DownCast(C3d->Transformed(L3d.Transformation()));
1308 }
1309 GAC.Load(C3d,f3d,l3d);
1310
1311 Standard_Real Prec_C3d = BRepCheck::PrecCurve(GAC);
1312
1313 Standard_Boolean IsSameP = 1;
1314 Standard_Real maxdist = 0.;
1315
1316 // Modified by skv - Thu Jun 3 12:39:19 2004 OCC5898 Begin
1317 Standard_Real anEdgeTol = BRep_Tool::Tolerance(aNE);
1318 // Modified by skv - Thu Jun 3 12:39:20 2004 OCC5898 End
1319 Standard_Boolean SameRange = BRep_Tool::SameRange(aNE);
1320 Standard_Boolean YaPCu = Standard_False;
1321 const Standard_Real BigError = 1.e10;
1322 It.Initialize(CList);
1323
1324 while (It.More()) {
1325
1326 Standard_Boolean isANA = Standard_False;
1327 Standard_Boolean isBSP = Standard_False;
1328 Handle(BRep_GCurve) GCurve = Handle(BRep_GCurve)::DownCast(It.Value());
1329 Handle(Geom2d_Curve) PC[2];
1330 Handle(Geom_Surface) S;
1331 if (!GCurve.IsNull() && GCurve->IsCurveOnSurface()) {
1332 YaPCu = Standard_True;
1333 PC[0] = GCurve->PCurve();
1334 TopLoc_Location PCLoc = GCurve->Location();
1335 S = GCurve->Surface();
1336 if (!PCLoc.IsIdentity() ) {
1337 S = Handle(Geom_Surface)::DownCast(S->Transformed(PCLoc.Transformation()));
1338 }
1339
1340 GAS.Load(S);
1341 if (GCurve->IsCurveOnClosedSurface()) {
1342 PC[1] = GCurve->PCurve2();
1343 }
1344
1345 // Eval tol2d to compute SameRange
1346 Standard_Real TolSameRange = Max(GAC.Resolution(theTolerance), Precision::PConfusion());
1347 for(Standard_Integer i = 0; i < 2; i++){
1348 Handle(Geom2d_Curve) curPC = PC[i];
1349 Standard_Boolean updatepc = 0;
1350 if(curPC.IsNull()) break;
1351 if(!SameRange){
1352 GeomLib::SameRange(TolSameRange,
1353 PC[i],GCurve->First(),GCurve->Last(),
1354 f3d,l3d,curPC);
1355
1356 updatepc = (curPC != PC[i]);
1357
1358 }
1359 Standard_Boolean goodpc = 1;
1360 GAC2d.Load(curPC,f3d,l3d);
1361
1362 Standard_Real error = ComputeTol(HC, HC2d, HS, NCONTROL);
1363
1364 if(error > BigError)
1365 {
1366 maxdist = error;
1367 break;
1368 }
1369
1370 if(GAC2d.GetType() == GeomAbs_BSplineCurve &&
1371 GAC2d.Continuity() == GeomAbs_C0) {
1372 Standard_Real UResol = GAS.UResolution(theTolerance);
1373 Standard_Real VResol = GAS.VResolution(theTolerance);
1374 Standard_Real TolConf2d = Min(UResol, VResol);
1375 TolConf2d = Max(TolConf2d, Precision::PConfusion());
1376 Handle(Geom2d_BSplineCurve) bs2d = GAC2d.BSpline();
1377 Handle(Geom2d_BSplineCurve) bs2dsov = bs2d;
1378 Standard_Real fC0 = bs2d->FirstParameter(), lC0 = bs2d->LastParameter();
1379 Standard_Boolean repar = Standard_True;
1380 gp_Pnt2d OriginPoint;
1381 bs2d->D0(fC0, OriginPoint);
1382 Geom2dConvert::C0BSplineToC1BSplineCurve(bs2d, TolConf2d);
1383 isBSP = Standard_True;
1384
1385 if(bs2d->IsPeriodic()) { // -------- IFV, Jan 2000
1386 gp_Pnt2d NewOriginPoint;
1387 bs2d->D0(bs2d->FirstParameter(), NewOriginPoint);
1388 if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1389 Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion() ) {
1390
1391 TColStd_Array1OfReal Knotbs2d (1, bs2d->NbKnots());
1392 bs2d->Knots(Knotbs2d);
1393
1394 for(Standard_Integer Index = 1; Index <= bs2d->NbKnots(); Index++) {
1395 bs2d->D0(Knotbs2d(Index), NewOriginPoint);
1396 if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1397 Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion() ) continue;
1398
1399 bs2d->SetOrigin(Index);
1400 break;
1401 }
1402 }
1403 }
1404
1405 if(bs2d->Continuity() == GeomAbs_C0) {
1406 Standard_Real tolbail;
1407 if(EvalTol(curPC,S,GAC,theTolerance,tolbail)){
1408 bs2d = bs2dsov;
1409 Standard_Real UResbail = GAS.UResolution(tolbail);
1410 Standard_Real VResbail = GAS.VResolution(tolbail);
1411 Standard_Real Tol2dbail = Min(UResbail,VResbail);
1412 bs2d->D0(bs2d->FirstParameter(), OriginPoint);
1413
1414 Standard_Integer nbp = bs2d->NbPoles();
1415 TColgp_Array1OfPnt2d poles(1,nbp);
1416 bs2d->Poles(poles);
1417 gp_Pnt2d p = poles(1), p1;
1418 Standard_Real d = Precision::Infinite();
1419 for(Standard_Integer ip = 2; ip <= nbp; ip++) {
1420 p1 = poles(ip);
1421 d = Min(d,p.SquareDistance(p1));
1422 p = p1;
1423 }
1424 d = sqrt(d)*.1;
1425
1426 Tol2dbail = Max(Min(Tol2dbail,d), TolConf2d);
1427
1428 Geom2dConvert::C0BSplineToC1BSplineCurve(bs2d,Tol2dbail);
1429
1430 if(bs2d->IsPeriodic()) { // -------- IFV, Jan 2000
1431 gp_Pnt2d NewOriginPoint;
1432 bs2d->D0(bs2d->FirstParameter(), NewOriginPoint);
1433 if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1434 Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion() ) {
1435
1436 TColStd_Array1OfReal Knotbs2d (1, bs2d->NbKnots());
1437 bs2d->Knots(Knotbs2d);
1438
1439 for(Standard_Integer Index = 1; Index <= bs2d->NbKnots(); Index++) {
1440 bs2d->D0(Knotbs2d(Index), NewOriginPoint);
1441 if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
1442 Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion() ) continue;
1443
1444 bs2d->SetOrigin(Index);
1445 break;
1446 }
1447 }
1448 }
1449
1450
1451 if(bs2d->Continuity() == GeomAbs_C0) {
1452 goodpc = 1;
1453 bs2d = bs2dsov;
1454 repar = Standard_False;
1455 }
1456 }
1457 else goodpc = 0;
1458 }
1459
1460 if(goodpc){
1461 if(repar) {
1462 Standard_Integer NbKnots = bs2d->NbKnots();
1463 TColStd_Array1OfReal Knots(1,NbKnots);
1464 bs2d->Knots(Knots);
1465 // BSplCLib::Reparametrize(f3d,l3d,Knots);
1466 BSplCLib::Reparametrize(fC0,lC0,Knots);
1467 bs2d->SetKnots(Knots);
1468 GAC2d.Load(bs2d,f3d,l3d);
1469 curPC = bs2d;
1470 Standard_Boolean updatepcsov = updatepc;
1471 updatepc = Standard_True;
1472
1473 Standard_Real error1 = ComputeTol(HC, HC2d, HS, NCONTROL);
1474 if(error1 > error) {
1475 bs2d = bs2dsov;
1476 GAC2d.Load(bs2d,f3d,l3d);
1477 curPC = bs2d;
1478 updatepc = updatepcsov;
1479 isANA = Standard_True;
1480 }
1481 else {
1482 error = error1;
1483 }
1484 }
1485
1486 //check, if new BSpline "good" or not --------- IFV, Jan of 2000
1487 GeomAbs_Shape cont = bs2d->Continuity();
1488 Standard_Boolean IsBad = Standard_False;
1489
1490 if(cont > GeomAbs_C0 && error > Max(1.e-3,theTolerance)) {
1491 Standard_Integer NbKnots = bs2d->NbKnots();
1492 TColStd_Array1OfReal Knots(1,NbKnots);
1493 bs2d->Knots(Knots);
1494 Standard_Real critratio = 10.;
1495 Standard_Real dtprev = Knots(2) - Knots(1), dtratio = 1.;
1496 Standard_Real dtmin = dtprev;
1497 Standard_Real dtcur;
1498 for(Standard_Integer j = 2; j < NbKnots; j++) {
1499 dtcur = Knots(j+1) - Knots(j);
1500 dtmin = Min(dtmin, dtcur);
1501
1502 if(IsBad) continue;
1503
1504 if(dtcur > dtprev) dtratio = dtcur/dtprev;
1505 else dtratio = dtprev/dtcur;
1506 if(dtratio > critratio) {IsBad = Standard_True;}
1507 dtprev = dtcur;
1508
1509 }
1510 if(IsBad) {
1511 // To avoid failures in Approx_CurvilinearParameter
1512 bs2d->Resolution(Max(1.e-3,theTolerance), dtcur);
1513 if(dtmin < dtcur) IsBad = Standard_False;
1514 }
1515 }
1516
1517
1518 if(IsBad ) { //if BSpline "bad", try to reparametrize it
1519 // by its curve length
1520
1521 // GeomAbs_Shape cont = bs2d->Continuity();
1522 if(cont > GeomAbs_C2) cont = GeomAbs_C2;
1523 Standard_Integer maxdeg = bs2d->Degree();
1524 if(maxdeg == 1) maxdeg = 14;
1525 Approx_CurvilinearParameter AppCurPar(HC2d, HS, Max(1.e-3,theTolerance),
1526 cont, maxdeg, 10);
1527 if(AppCurPar.IsDone() || AppCurPar.HasResult()) {
1528 bs2d = AppCurPar.Curve2d1();
1529 GAC2d.Load(bs2d,f3d,l3d);
1530 curPC = bs2d;
1531
1532 if(Abs(bs2d->FirstParameter() - fC0) > TolSameRange ||
1533 Abs(bs2d->LastParameter() - lC0) > TolSameRange) {
1534 Standard_Integer NbKnots = bs2d->NbKnots();
1535 TColStd_Array1OfReal Knots(1,NbKnots);
1536 bs2d->Knots(Knots);
1537 // BSplCLib::Reparametrize(f3d,l3d,Knots);
1538 BSplCLib::Reparametrize(fC0,lC0,Knots);
1539 bs2d->SetKnots(Knots);
1540 GAC2d.Load(bs2d,f3d,l3d);
1541 curPC = bs2d;
1542
1543 }
1544 }
1545 }
1546
1547
1548 }
1549 }
1550
1551
1552 if(goodpc){
1553 // Approx_SameParameter SameP(HC,HC2d,HS,Tolerance);
1554 Standard_Real aTol = (isANA && isBSP) ? 1.e-7 : theTolerance;
1555 const Handle(Adaptor3d_Curve)& aHCurv = HC; // to avoid ambiguity
1556 const Handle(Adaptor2d_Curve2d)& aHCurv2d = HC2d; // to avoid ambiguity
1557 Approx_SameParameter SameP(aHCurv,aHCurv2d,HS,aTol);
1558
1559 if (SameP.IsSameParameter()) {
1560 maxdist = Max(maxdist,SameP.TolReached());
1561 if(updatepc){
1562 if (i == 0) GCurve->PCurve(curPC);
1563 else GCurve->PCurve2(curPC);
1564 }
1565 }
1566 else if (SameP.IsDone()) {
1567 Standard_Real tolreached = SameP.TolReached();
1568 if(tolreached <= error) {
1569 curPC = SameP.Curve2d();
1570 updatepc = Standard_True;
1571 maxdist = Max(maxdist,tolreached);
1572 }
1573 else {
1574 maxdist = Max(maxdist, error);
1575 }
1576 if(updatepc){
1577 if (i == 0) GCurve->PCurve(curPC);
1578 else GCurve->PCurve2(curPC);
1579 }
1580 }
1581 else
1582 {
1583 //Approx_SameParameter has failed.
1584 //Consequently, the situation might be,
1585 //when 3D and 2D-curve do not have same-range.
1586 GeomLib::SameRange( TolSameRange, PC[i],
1587 GCurve->First(), GCurve->Last(),
1588 f3d,l3d,curPC);
1589
1590 if (i == 0) GCurve->PCurve(curPC);
1591 else GCurve->PCurve2(curPC);
1592
1593 IsSameP = 0;
1594 }
1595
1596 }
1597 else IsSameP = 0;
1598
1599 // Modified by skv - Thu Jun 3 12:39:19 2004 OCC5898 Begin
1600 if (!IsSameP) {
1601 Standard_Real Prec_Surf = BRepCheck::PrecSurface(HS);
1602 Standard_Real CurTol = anEdgeTol + Max(Prec_C3d, Prec_Surf);
1603 if (CurTol >= error) {
1604 maxdist = Max(maxdist, anEdgeTol);
1605 IsSameP = Standard_True;
1606 }
1607 }
1608 // Modified by skv - Thu Jun 3 12:39:20 2004 OCC5898 End
1609 }
1610 }
1611 It.Next() ;
1612 }
1613 B.Range(aNE,f3d,l3d);
1614 B.SameRange(aNE,Standard_True);
1615 if ( IsSameP) {
1616 // Reduce eventually the tolerance of the edge, as
1617 // all its representations are processed (except for some associated
1618 // to planes and not stored in the edge !)
1619 // The same cannot be done with vertices that cannot be enlarged
1620 // or left as is.
1621 if (YaPCu) {
1622 // Avoid setting too small tolerances.
1623 maxdist = Max(maxdist,Precision::Confusion());
1624 theNewTol = maxdist;
1625 aNTE->Modified(Standard_True);
1626 aNTE->Tolerance(maxdist);
1627 }
1628 B.SameParameter(aNE,Standard_True);
1629 }
1630
1631 return aNE;
1632 }
1633
1634 //=======================================================================
1635 //function : InternalUpdateTolerances
1636 //purpose :
1637 //=======================================================================
InternalUpdateTolerances(const TopoDS_Shape & theOldShape,const Standard_Boolean IsVerifyTolerance,const Standard_Boolean IsMutableInput,BRepTools_ReShape & theReshaper)1638 static void InternalUpdateTolerances(const TopoDS_Shape& theOldShape,
1639 const Standard_Boolean IsVerifyTolerance, const Standard_Boolean IsMutableInput, BRepTools_ReShape& theReshaper)
1640 {
1641 TopTools_DataMapOfShapeReal aShToTol;
1642 // Harmonize tolerances
1643 // with rule Tolerance(VERTEX)>=Tolerance(EDGE)>=Tolerance(FACE)
1644 Standard_Real tol=0;
1645 if (IsVerifyTolerance) {
1646 // Set tolerance to its minimum value
1647 Handle(Geom_Surface) S;
1648 TopLoc_Location l;
1649 TopExp_Explorer ex;
1650 Bnd_Box aB;
1651 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dMax;
1652 for (ex.Init(theOldShape, TopAbs_FACE); ex.More(); ex.Next()) {
1653 const TopoDS_Face& curf=TopoDS::Face(ex.Current());
1654 S = BRep_Tool::Surface(curf, l);
1655 if (!S.IsNull()) {
1656 aB.SetVoid();
1657 BRepBndLib::Add(curf,aB);
1658 if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1659 S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
1660 }
1661 GeomAdaptor_Surface AS(S);
1662 switch (AS.GetType()) {
1663 case GeomAbs_Plane:
1664 case GeomAbs_Cylinder:
1665 case GeomAbs_Cone:
1666 {
1667 tol=Precision::Confusion();
1668 break;
1669 }
1670 case GeomAbs_Sphere:
1671 case GeomAbs_Torus:
1672 {
1673 tol=Precision::Confusion()*2;
1674 break;
1675 }
1676 default:
1677 tol=Precision::Confusion()*4;
1678 }
1679 if (!aB.IsWhole()) {
1680 aB.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
1681 dMax=1.;
1682 if (!aB.IsOpenXmin() && !aB.IsOpenXmax()) dMax=aXmax-aXmin;
1683 if (!aB.IsOpenYmin() && !aB.IsOpenYmax()) aYmin=aYmax-aYmin;
1684 if (!aB.IsOpenZmin() && !aB.IsOpenZmax()) aZmin=aZmax-aZmin;
1685 if (aYmin>dMax) dMax=aYmin;
1686 if (aZmin>dMax) dMax=aZmin;
1687 tol=tol*dMax;
1688 // Do not process tolerances > 1.
1689 if (tol>1.) tol=0.99;
1690 }
1691 aShToTol.Bind(curf, tol);
1692 }
1693 }
1694 }
1695
1696 //Process edges
1697 TopTools_IndexedDataMapOfShapeListOfShape parents;
1698 TopExp::MapShapesAndAncestors(theOldShape, TopAbs_EDGE, TopAbs_FACE, parents);
1699 TopTools_ListIteratorOfListOfShape lConx;
1700 Standard_Integer iCur;
1701 for (iCur=1; iCur<=parents.Extent(); iCur++) {
1702 tol=0;
1703 for (lConx.Initialize(parents(iCur)); lConx.More(); lConx.Next())
1704 {
1705 const TopoDS_Face& FF = TopoDS::Face(lConx.Value());
1706 Standard_Real Ftol;
1707 if (IsVerifyTolerance && aShToTol.IsBound(FF)) //first condition for speed-up
1708 Ftol = aShToTol(FF);
1709 else
1710 Ftol = BRep_Tool::Tolerance(FF); //tolerance have not been updated
1711 tol=Max(tol, Ftol);
1712 }
1713 // Update can only increase tolerance, so if the edge has a greater
1714 // tolerance than its faces it is not concerned
1715 const TopoDS_Edge& EK = TopoDS::Edge(parents.FindKey(iCur));
1716 if (tol > BRep_Tool::Tolerance(EK))
1717 aShToTol.Bind(EK, tol);
1718 }
1719
1720 //Vertices are processed
1721 const Standard_Real BigTol = 1.e10;
1722 parents.Clear();
1723
1724 TopExp::MapShapesAndUniqueAncestors(theOldShape, TopAbs_VERTEX, TopAbs_EDGE, parents);
1725 TColStd_MapOfTransient Initialized;
1726 Standard_Integer nbV = parents.Extent();
1727 for (iCur=1; iCur<=nbV; iCur++) {
1728 tol=0;
1729 const TopoDS_Vertex& V = TopoDS::Vertex(parents.FindKey(iCur));
1730 Bnd_Box box;
1731 box.Add(BRep_Tool::Pnt(V));
1732 gp_Pnt p3d;
1733 for (lConx.Initialize(parents(iCur)); lConx.More(); lConx.Next()) {
1734 const TopoDS_Edge& E = TopoDS::Edge(lConx.Value());
1735 const Standard_Real* aNtol = aShToTol.Seek(E);
1736 tol=Max(tol, aNtol ? *aNtol : BRep_Tool::Tolerance(E));
1737 if(tol > BigTol) continue;
1738 if(!BRep_Tool::SameRange(E)) continue;
1739 Standard_Real par = BRep_Tool::Parameter(V,E);
1740 Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&E.TShape());
1741 BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
1742 const TopLoc_Location& Eloc = E.Location();
1743 while (itcr.More()) {
1744 // For each CurveRepresentation, check the provided parameter
1745 const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
1746 const TopLoc_Location& loc = cr->Location();
1747 TopLoc_Location L = (Eloc * loc);
1748 if (cr->IsCurve3D()) {
1749 const Handle(Geom_Curve)& C = cr->Curve3D();
1750 if (!C.IsNull()) { // edge non degenerated
1751 p3d = C->Value(par);
1752 p3d.Transform(L.Transformation());
1753 box.Add(p3d);
1754 }
1755 }
1756 else if (cr->IsCurveOnSurface()) {
1757 const Handle(Geom_Surface)& Su = cr->Surface();
1758 const Handle(Geom2d_Curve)& PC = cr->PCurve();
1759 Handle(Geom2d_Curve) PC2;
1760 if (cr->IsCurveOnClosedSurface()) {
1761 PC2 = cr->PCurve2();
1762 }
1763 gp_Pnt2d p2d = PC->Value(par);
1764 p3d = Su->Value(p2d.X(),p2d.Y());
1765 p3d.Transform(L.Transformation());
1766 box.Add(p3d);
1767 if (!PC2.IsNull()) {
1768 p2d = PC2->Value(par);
1769 p3d = Su->Value(p2d.X(),p2d.Y());
1770 p3d.Transform(L.Transformation());
1771 box.Add(p3d);
1772 }
1773 }
1774 itcr.Next();
1775 }
1776 }
1777 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
1778 box.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
1779 aXmax -= aXmin; aYmax -= aYmin; aZmax -= aZmin;
1780 tol = Max(tol,sqrt(aXmax*aXmax+aYmax*aYmax+aZmax*aZmax));
1781 tol += 2.*Epsilon(tol);
1782 //
1783 Standard_Real aVTol = BRep_Tool::Tolerance(V);
1784 Standard_Boolean anUpdTol = tol > aVTol;
1785 const Handle(BRep_TVertex)& aTV = *((Handle(BRep_TVertex)*)&V.TShape());
1786 Standard_Boolean toAdd = Standard_False;
1787 if (IsVerifyTolerance)
1788 {
1789 // ASet minimum value of the tolerance
1790 // Attention to sharing of the vertex by other shapes
1791 toAdd = Initialized.Add(aTV) && aVTol != tol; //if Vtol == tol => no need to update toler
1792 }
1793 //'Initialized' map is not used anywhere outside this block
1794 if (anUpdTol || toAdd)
1795 aShToTol.Bind(V, tol);
1796 }
1797
1798 UpdShTol(aShToTol, IsMutableInput, theReshaper, Standard_True);
1799 }
1800
1801 //=======================================================================
1802 //function : UpdateTolerances
1803 //purpose :
1804 //=======================================================================
UpdateTolerances(const TopoDS_Shape & S,const Standard_Boolean verifyFaceTolerance)1805 void BRepLib::UpdateTolerances (const TopoDS_Shape& S, const Standard_Boolean verifyFaceTolerance)
1806 {
1807 BRepTools_ReShape aReshaper;
1808 InternalUpdateTolerances(S, verifyFaceTolerance, Standard_True, aReshaper);
1809 }
1810
1811 //=======================================================================
1812 //function : UpdateTolerances
1813 //purpose :
1814 //=======================================================================
UpdateTolerances(const TopoDS_Shape & S,BRepTools_ReShape & theReshaper,const Standard_Boolean verifyFaceTolerance)1815 void BRepLib::UpdateTolerances (const TopoDS_Shape& S, BRepTools_ReShape& theReshaper, const Standard_Boolean verifyFaceTolerance )
1816 {
1817 InternalUpdateTolerances(S, verifyFaceTolerance, Standard_False, theReshaper);
1818 }
1819
1820 //=======================================================================
1821 //function : UpdateInnerTolerances
1822 //purpose :
1823 //=======================================================================
UpdateInnerTolerances(const TopoDS_Shape & aShape)1824 void BRepLib::UpdateInnerTolerances(const TopoDS_Shape& aShape)
1825 {
1826 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
1827 TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, EFmap);
1828 BRep_Builder BB;
1829 for (Standard_Integer i = 1; i <= EFmap.Extent(); i++)
1830 {
1831 TopoDS_Edge anEdge = TopoDS::Edge(EFmap.FindKey(i));
1832
1833 if (!BRep_Tool::IsGeometric(anEdge))
1834 {
1835 continue;
1836 }
1837
1838 TopoDS_Vertex V1, V2;
1839 TopExp::Vertices(anEdge, V1, V2);
1840 Standard_Real fpar, lpar;
1841 BRep_Tool::Range(anEdge, fpar, lpar);
1842 Standard_Real TolEdge = BRep_Tool::Tolerance(anEdge);
1843 gp_Pnt Pnt1, Pnt2;
1844 Handle(BRepAdaptor_Curve) anHCurve = new BRepAdaptor_Curve();
1845 anHCurve->Initialize(anEdge);
1846 if (!V1.IsNull())
1847 Pnt1 = BRep_Tool::Pnt(V1);
1848 if (!V2.IsNull())
1849 Pnt2 = BRep_Tool::Pnt(V2);
1850
1851 if (!BRep_Tool::Degenerated(anEdge) &&
1852 EFmap(i).Extent() > 0)
1853 {
1854 NCollection_Sequence<Handle(Adaptor3d_Curve)> theRep;
1855 theRep.Append(anHCurve);
1856 TopTools_ListIteratorOfListOfShape itl(EFmap(i));
1857 for (; itl.More(); itl.Next())
1858 {
1859 const TopoDS_Face& aFace = TopoDS::Face(itl.Value());
1860 Handle(BRepAdaptor_Curve) anHCurvOnSurf = new BRepAdaptor_Curve();
1861 anHCurvOnSurf->Initialize(anEdge, aFace);
1862 theRep.Append(anHCurvOnSurf);
1863 }
1864
1865 const Standard_Integer NbSamples = (BRep_Tool::SameParameter(anEdge))? 23 : 2;
1866 Standard_Real delta = (lpar - fpar)/(NbSamples-1);
1867 Standard_Real MaxDist = 0.;
1868 for (Standard_Integer j = 2; j <= theRep.Length(); j++)
1869 {
1870 for (Standard_Integer k = 0; k <= NbSamples; k++)
1871 {
1872 Standard_Real ParamOnCenter = (k == NbSamples)? lpar :
1873 fpar + k*delta;
1874 gp_Pnt Center = theRep(1)->Value(ParamOnCenter);
1875 Standard_Real ParamOnCurve = (BRep_Tool::SameParameter(anEdge))? ParamOnCenter
1876 : ((k == 0)? theRep(j)->FirstParameter() : theRep(j)->LastParameter());
1877 gp_Pnt aPoint = theRep(j)->Value(ParamOnCurve);
1878 Standard_Real aDist = Center.Distance(aPoint);
1879 //aDist *= 1.1;
1880 aDist += 2.*Epsilon(aDist);
1881 if (aDist > MaxDist)
1882 MaxDist = aDist;
1883
1884 //Update tolerances of vertices
1885 if (k == 0 && !V1.IsNull())
1886 {
1887 Standard_Real aDist1 = Pnt1.Distance(aPoint);
1888 aDist1 += 2.*Epsilon(aDist1);
1889 BB.UpdateVertex(V1, aDist1);
1890 }
1891 if (k == NbSamples && !V2.IsNull())
1892 {
1893 Standard_Real aDist2 = Pnt2.Distance(aPoint);
1894 aDist2 += 2.*Epsilon(aDist2);
1895 BB.UpdateVertex(V2, aDist2);
1896 }
1897 }
1898 }
1899 BB.UpdateEdge(anEdge, MaxDist);
1900 }
1901 TolEdge = BRep_Tool::Tolerance(anEdge);
1902 if (!V1.IsNull())
1903 {
1904 gp_Pnt End1 = anHCurve->Value(fpar);
1905 Standard_Real dist1 = Pnt1.Distance(End1);
1906 dist1 += 2.*Epsilon(dist1);
1907 BB.UpdateVertex(V1, Max(dist1, TolEdge));
1908 }
1909 if (!V2.IsNull())
1910 {
1911 gp_Pnt End2 = anHCurve->Value(lpar);
1912 Standard_Real dist2 = Pnt2.Distance(End2);
1913 dist2 += 2.*Epsilon(dist2);
1914 BB.UpdateVertex(V2, Max(dist2, TolEdge));
1915 }
1916 }
1917 }
1918
1919 //=======================================================================
1920 //function : OrientClosedSolid
1921 //purpose :
1922 //=======================================================================
OrientClosedSolid(TopoDS_Solid & solid)1923 Standard_Boolean BRepLib::OrientClosedSolid(TopoDS_Solid& solid)
1924 {
1925 // Set material inside the solid
1926 BRepClass3d_SolidClassifier where(solid);
1927 where.PerformInfinitePoint(Precision::Confusion());
1928 if (where.State()==TopAbs_IN) {
1929 solid.Reverse();
1930 }
1931 else if (where.State()==TopAbs_ON || where.State()==TopAbs_UNKNOWN)
1932 return Standard_False;
1933
1934 return Standard_True;
1935 }
1936
1937 // Structure for calculation of properties, necessary for decision about continuity
1938 class SurfaceProperties
1939 {
1940 public:
SurfaceProperties(const Handle (Geom_Surface)& theSurface,const gp_Trsf & theSurfaceTrsf,const Handle (Geom2d_Curve)& theCurve2D,const Standard_Boolean theReversed)1941 SurfaceProperties(const Handle(Geom_Surface)& theSurface,
1942 const gp_Trsf& theSurfaceTrsf,
1943 const Handle(Geom2d_Curve)& theCurve2D,
1944 const Standard_Boolean theReversed)
1945 : mySurfaceProps(theSurface, 2, Precision::Confusion()),
1946 mySurfaceTrsf(theSurfaceTrsf),
1947 myCurve2d(theCurve2D),
1948 myIsReversed(theReversed)
1949 {}
1950
1951 // Calculate derivatives on surface related to the point on curve
Calculate(const Standard_Real theParamOnCurve)1952 void Calculate(const Standard_Real theParamOnCurve)
1953 {
1954 gp_Pnt2d aUV;
1955 myCurve2d->D1(theParamOnCurve, aUV, myCurveTangent);
1956 mySurfaceProps.SetParameters(aUV.X(), aUV.Y());
1957 }
1958
1959 // Returns point just calculated
Value()1960 gp_Pnt Value()
1961 { return mySurfaceProps.Value().Transformed(mySurfaceTrsf); }
1962
1963 // Calculate a derivative orthogonal to curve's tangent vector
Derivative()1964 gp_Vec Derivative()
1965 {
1966 gp_Vec aDeriv;
1967 // direction orthogonal to tangent vector of the curve
1968 gp_Vec2d anOrtho(-myCurveTangent.Y(), myCurveTangent.X());
1969 Standard_Real aLen = anOrtho.Magnitude();
1970 if (aLen < Precision::Confusion())
1971 return aDeriv;
1972 anOrtho /= aLen;
1973 if (myIsReversed)
1974 anOrtho.Reverse();
1975
1976 aDeriv.SetLinearForm(anOrtho.X(), mySurfaceProps.D1U(),
1977 anOrtho.Y(), mySurfaceProps.D1V());
1978 return aDeriv.Transformed(mySurfaceTrsf);
1979 }
1980
1981 // Calculate principal curvatures, which consist of minimal and maximal normal curvatures and
1982 // the directions on the tangent plane (principal direction) where the extremums are reached
Curvature(gp_Dir & thePrincipalDir1,Standard_Real & theCurvature1,gp_Dir & thePrincipalDir2,Standard_Real & theCurvature2)1983 void Curvature(gp_Dir& thePrincipalDir1, Standard_Real& theCurvature1,
1984 gp_Dir& thePrincipalDir2, Standard_Real& theCurvature2)
1985 {
1986 mySurfaceProps.CurvatureDirections(thePrincipalDir1, thePrincipalDir2);
1987 theCurvature1 = mySurfaceProps.MaxCurvature();
1988 theCurvature2 = mySurfaceProps.MinCurvature();
1989 if (myIsReversed)
1990 {
1991 theCurvature1 = -theCurvature1;
1992 theCurvature2 = -theCurvature2;
1993 }
1994 if (mySurfaceTrsf.IsNegative())
1995 {
1996 theCurvature1 = -theCurvature1;
1997 theCurvature2 = -theCurvature2;
1998 }
1999
2000 thePrincipalDir1.Transform(mySurfaceTrsf);
2001 thePrincipalDir2.Transform(mySurfaceTrsf);
2002 }
2003
2004 private:
2005 GeomLProp_SLProps mySurfaceProps; // properties calculator
2006 gp_Trsf mySurfaceTrsf;
2007 Handle(Geom2d_Curve) myCurve2d;
2008 Standard_Boolean myIsReversed; // the face based on the surface is reversed
2009
2010 // tangent vector to Pcurve in UV
2011 gp_Vec2d myCurveTangent;
2012 };
2013
2014 //=======================================================================
2015 //function : tgtfaces
2016 //purpose : check the angle at the border between two squares.
2017 // Two shares should have a shared front edge.
2018 //=======================================================================
tgtfaces(const TopoDS_Edge & Ed,const TopoDS_Face & F1,const TopoDS_Face & F2,const Standard_Real theAngleTol)2019 static GeomAbs_Shape tgtfaces(const TopoDS_Edge& Ed,
2020 const TopoDS_Face& F1,
2021 const TopoDS_Face& F2,
2022 const Standard_Real theAngleTol)
2023 {
2024 Standard_Boolean isSeam = F1.IsEqual(F2);
2025
2026 TopoDS_Edge E = Ed;
2027
2028 // Check if pcurves exist on both faces of edge
2029 Standard_Real aFirst,aLast;
2030 E.Orientation(TopAbs_FORWARD);
2031 Handle(Geom2d_Curve) aCurve1 = BRep_Tool::CurveOnSurface(E, F1, aFirst, aLast);
2032 if(aCurve1.IsNull())
2033 return GeomAbs_C0;
2034
2035 if (isSeam)
2036 E.Orientation(TopAbs_REVERSED);
2037 Handle(Geom2d_Curve) aCurve2 = BRep_Tool::CurveOnSurface(E, F2, aFirst, aLast);
2038 if(aCurve2.IsNull())
2039 return GeomAbs_C0;
2040
2041 TopLoc_Location aLoc1, aLoc2;
2042 Handle(Geom_Surface) aSurface1 = BRep_Tool::Surface(F1, aLoc1);
2043 const gp_Trsf& aSurf1Trsf = aLoc1.Transformation();
2044 Handle(Geom_Surface) aSurface2 = BRep_Tool::Surface(F2, aLoc2);
2045 const gp_Trsf& aSurf2Trsf = aLoc2.Transformation();
2046
2047 if (aSurface1->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
2048 aSurface1 = Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface1)->BasisSurface();
2049 if (aSurface2->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
2050 aSurface2 = Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface2)->BasisSurface();
2051
2052 // seam edge on elementary surface is always CN
2053 Standard_Boolean isElementary =
2054 (aSurface1->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) &&
2055 aSurface2->IsKind(STANDARD_TYPE(Geom_ElementarySurface)));
2056 if (isSeam && isElementary)
2057 {
2058 return GeomAbs_CN;
2059 }
2060
2061 SurfaceProperties aSP1(aSurface1, aSurf1Trsf, aCurve1, F1.Orientation() == TopAbs_REVERSED);
2062 SurfaceProperties aSP2(aSurface2, aSurf2Trsf, aCurve2, F2.Orientation() == TopAbs_REVERSED);
2063
2064 Standard_Real f, l, eps;
2065 BRep_Tool::Range(E,f,l);
2066 Extrema_LocateExtPC ext;
2067 Handle(BRepAdaptor_Curve) aHC2;
2068
2069 eps = (l - f)/100.;
2070 f += eps; // to avoid calculations on
2071 l -= eps; // points of pointed squares.
2072
2073 const Standard_Real anAngleTol2 = theAngleTol * theAngleTol;
2074
2075 gp_Vec aDer1, aDer2;
2076 gp_Vec aNorm1;
2077 Standard_Real aSqLen1, aSqLen2;
2078 gp_Dir aCrvDir1[2], aCrvDir2[2];
2079 Standard_Real aCrvLen1[2], aCrvLen2[2];
2080
2081 GeomAbs_Shape aCont = (isElementary ? GeomAbs_CN : GeomAbs_C2);
2082 GeomAbs_Shape aCurCont;
2083 Standard_Real u;
2084 for (Standard_Integer i = 0; i <= 20 && aCont > GeomAbs_C0; i++)
2085 {
2086 // First suppose that this is sameParameter
2087 u = f + (l-f)*i/20;
2088
2089 // Check conditions for G1 and C1 continuity:
2090 // * calculate a derivative in tangent plane of each surface
2091 // orthogonal to curve's tangent vector
2092 // * continuity is C1 if the vectors are equal
2093 // * continuity is G1 if the vectors are just parallel
2094 aCurCont = GeomAbs_C0;
2095
2096 aSP1.Calculate(u);
2097 aSP2.Calculate(u);
2098
2099 aDer1 = aSP1.Derivative();
2100 aSqLen1 = aDer1.SquareMagnitude();
2101 aDer2 = aSP2.Derivative();
2102 aSqLen2 = aDer2.SquareMagnitude();
2103 Standard_Boolean isSmoothSuspect = (aDer1.CrossSquareMagnitude(aDer2) <= anAngleTol2 * aSqLen1 * aSqLen2);
2104 if (!isSmoothSuspect)
2105 {
2106 // Refine by projection
2107 if (aHC2.IsNull())
2108 {
2109 // adaptor for pcurve on the second surface
2110 aHC2 = new BRepAdaptor_Curve (E, F2);
2111 ext.Initialize(*aHC2, f, l, Precision::PConfusion());
2112 }
2113 ext.Perform(aSP1.Value(), u);
2114 if (ext.IsDone() && ext.IsMin())
2115 {
2116 const Extrema_POnCurv& poc = ext.Point();
2117 aSP2.Calculate(poc.Parameter());
2118 aDer2 = aSP2.Derivative();
2119 aSqLen2 = aDer2.SquareMagnitude();
2120 }
2121 isSmoothSuspect = (aDer1.CrossSquareMagnitude(aDer2) <= anAngleTol2 * aSqLen1 * aSqLen2);
2122 }
2123 if (isSmoothSuspect)
2124 {
2125 aCurCont = GeomAbs_G1;
2126 if (Abs(Sqrt(aSqLen1) - Sqrt(aSqLen2)) < Precision::Confusion() &&
2127 aDer1.Dot(aDer2) > Precision::SquareConfusion()) // <= check vectors are codirectional
2128 aCurCont = GeomAbs_C1;
2129 }
2130 else
2131 return GeomAbs_C0;
2132
2133 if (aCont < GeomAbs_G2)
2134 continue; // no need further processing, because maximal continuity is less than G2
2135
2136 // Check conditions for G2 and C2 continuity:
2137 // * calculate principal curvatures on each surface
2138 // * continuity is C2 if directions of principal curvatures are equal on different surfaces
2139 // * continuity is G2 if directions of principal curvatures are just parallel
2140 // and values of curvatures are the same
2141 aSP1.Curvature(aCrvDir1[0], aCrvLen1[0], aCrvDir1[1], aCrvLen1[1]);
2142 aSP2.Curvature(aCrvDir2[0], aCrvLen2[0], aCrvDir2[1], aCrvLen2[1]);
2143 for (Standard_Integer aStep = 0; aStep <= 1; ++aStep)
2144 {
2145 if (aCrvDir1[0].XYZ().CrossSquareMagnitude(aCrvDir2[aStep].XYZ()) <= Precision::SquareConfusion() &&
2146 Abs(aCrvLen1[0] - aCrvLen2[aStep]) < Precision::Confusion() &&
2147 aCrvDir1[1].XYZ().CrossSquareMagnitude(aCrvDir2[1 - aStep].XYZ()) <= Precision::SquareConfusion() &&
2148 Abs(aCrvLen1[1] - aCrvLen2[1 - aStep]) < Precision::Confusion())
2149 {
2150 if (aCurCont == GeomAbs_C1 &&
2151 aCrvDir1[0].Dot(aCrvDir2[aStep]) > Precision::Confusion() &&
2152 aCrvDir1[1].Dot(aCrvDir2[1 - aStep]) > Precision::Confusion())
2153 aCurCont = GeomAbs_C2;
2154 else
2155 aCurCont = GeomAbs_G2;
2156 break;
2157 }
2158 }
2159
2160 if (aCurCont < aCont)
2161 aCont = aCurCont;
2162 }
2163
2164 // according to the list of supported elementary surfaces,
2165 // if the continuity is C2, than it is totally CN
2166 if (isElementary && aCont == GeomAbs_C2)
2167 aCont = GeomAbs_CN;
2168 return aCont;
2169 }
2170
2171 //=======================================================================
2172 // function : EncodeRegularity
2173 // purpose : Code the regularities on all edges of the shape, boundary of
2174 // two faces that do not have it.
2175 // Takes into account that compound may consists of same solid
2176 // placed with different transformations
2177 //=======================================================================
EncodeRegularity(const TopoDS_Shape & theShape,const Standard_Real theTolAng,TopTools_MapOfShape & theMap,const TopTools_MapOfShape & theEdgesToEncode=TopTools_MapOfShape ())2178 static void EncodeRegularity(const TopoDS_Shape& theShape,
2179 const Standard_Real theTolAng,
2180 TopTools_MapOfShape& theMap,
2181 const TopTools_MapOfShape& theEdgesToEncode = TopTools_MapOfShape())
2182 {
2183 TopoDS_Shape aShape = theShape;
2184 TopLoc_Location aNullLoc;
2185 aShape.Location(aNullLoc); // nullify location
2186 if (!theMap.Add(aShape))
2187 return; // do not need to process shape twice
2188
2189 if (aShape.ShapeType() == TopAbs_COMPOUND ||
2190 aShape.ShapeType() == TopAbs_COMPSOLID)
2191 {
2192 for (TopoDS_Iterator it(aShape); it.More(); it.Next())
2193 EncodeRegularity(it.Value(), theTolAng, theMap, theEdgesToEncode);
2194 return;
2195 }
2196
2197 try {
2198 OCC_CATCH_SIGNALS
2199
2200 TopTools_IndexedDataMapOfShapeListOfShape M;
2201 TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, M);
2202 TopTools_ListIteratorOfListOfShape It;
2203 TopExp_Explorer Ex;
2204 TopoDS_Face F1,F2;
2205 Standard_Boolean found;
2206 for (Standard_Integer i = 1; i <= M.Extent(); i++){
2207 TopoDS_Edge E = TopoDS::Edge(M.FindKey(i));
2208 if (!theEdgesToEncode.IsEmpty())
2209 {
2210 // process only the edges from the list to update their regularity
2211 TopoDS_Shape aPureEdge = E.Located(aNullLoc);
2212 aPureEdge.Orientation(TopAbs_FORWARD);
2213 if (!theEdgesToEncode.Contains(aPureEdge))
2214 continue;
2215 }
2216
2217 found = Standard_False;
2218 F1.Nullify();
2219 for (It.Initialize(M.FindFromIndex(i)); It.More() && !found; It.Next()){
2220 if (F1.IsNull()) { F1 = TopoDS::Face(It.Value()); }
2221 else {
2222 const TopoDS_Face& aTmpF2 = TopoDS::Face(It.Value());
2223 if (!F1.IsSame(aTmpF2)){
2224 found = Standard_True;
2225 F2 = aTmpF2;
2226 }
2227 }
2228 }
2229 if (!found && !F1.IsNull()){//is it a sewing edge?
2230 TopAbs_Orientation orE = E.Orientation();
2231 TopoDS_Edge curE;
2232 for (Ex.Init(F1, TopAbs_EDGE); Ex.More() && !found; Ex.Next()){
2233 curE = TopoDS::Edge(Ex.Current());
2234 if (E.IsSame(curE) && orE != curE.Orientation()) {
2235 found = Standard_True;
2236 F2 = F1;
2237 }
2238 }
2239 }
2240 if (found)
2241 BRepLib::EncodeRegularity(E, F1, F2, theTolAng);
2242 }
2243 }
2244 catch (Standard_Failure const& anException) {
2245 #ifdef OCCT_DEBUG
2246 std::cout << "Warning: Exception in BRepLib::EncodeRegularity(): ";
2247 anException.Print(std::cout);
2248 std::cout << std::endl;
2249 #endif
2250 (void)anException;
2251 }
2252 }
2253
2254 //=======================================================================
2255 // function : EncodeRegularity
2256 // purpose : code the regularities on all edges of the shape, boundary of
2257 // two faces that do not have it.
2258 //=======================================================================
2259
EncodeRegularity(const TopoDS_Shape & S,const Standard_Real TolAng)2260 void BRepLib::EncodeRegularity(const TopoDS_Shape& S,
2261 const Standard_Real TolAng)
2262 {
2263 TopTools_MapOfShape aMap;
2264 ::EncodeRegularity(S, TolAng, aMap);
2265 }
2266
2267 //=======================================================================
2268 // function : EncodeRegularity
2269 // purpose : code the regularities on all edges in the list that do not
2270 // have it, and which are boundary of two faces on the shape.
2271 //=======================================================================
2272
EncodeRegularity(const TopoDS_Shape & S,const TopTools_ListOfShape & LE,const Standard_Real TolAng)2273 void BRepLib::EncodeRegularity(const TopoDS_Shape& S,
2274 const TopTools_ListOfShape& LE,
2275 const Standard_Real TolAng)
2276 {
2277 // Collect edges without location and orientation
2278 TopTools_MapOfShape aPureEdges;
2279 TopLoc_Location aNullLoc;
2280 TopTools_ListIteratorOfListOfShape anEdgeIt(LE);
2281 for (; anEdgeIt.More(); anEdgeIt.Next())
2282 {
2283 TopoDS_Shape anEdge = anEdgeIt.Value();
2284 anEdge.Location(aNullLoc);
2285 anEdge.Orientation(TopAbs_FORWARD);
2286 aPureEdges.Add(anEdge);
2287 }
2288
2289 TopTools_MapOfShape aMap;
2290 ::EncodeRegularity(S, TolAng, aMap, aPureEdges);
2291 }
2292
2293 //=======================================================================
2294 // function : EncodeRegularity
2295 // purpose : code the regularity between 2 faces connected by edge
2296 //=======================================================================
2297
EncodeRegularity(TopoDS_Edge & E,const TopoDS_Face & F1,const TopoDS_Face & F2,const Standard_Real TolAng)2298 void BRepLib::EncodeRegularity(TopoDS_Edge& E,
2299 const TopoDS_Face& F1,
2300 const TopoDS_Face& F2,
2301 const Standard_Real TolAng)
2302 {
2303 BRep_Builder B;
2304 if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0){
2305 try {
2306 GeomAbs_Shape aCont = tgtfaces(E, F1, F2, TolAng);
2307 B.Continuity(E,F1,F2,aCont);
2308
2309 }
2310 catch(Standard_Failure const&)
2311 {
2312 #ifdef OCCT_DEBUG
2313 std::cout << "Failure: Exception in BRepLib::EncodeRegularity" << std::endl;
2314 #endif
2315 }
2316 }
2317 }
2318
2319 //=======================================================================
2320 // function : EnsureNormalConsistency
2321 // purpose : Corrects the normals in Poly_Triangulation of faces.
2322 // Returns TRUE if any correction is done.
2323 //=======================================================================
2324 Standard_Boolean BRepLib::
EnsureNormalConsistency(const TopoDS_Shape & theShape,const Standard_Real theAngTol,const Standard_Boolean theForceComputeNormals)2325 EnsureNormalConsistency(const TopoDS_Shape& theShape,
2326 const Standard_Real theAngTol,
2327 const Standard_Boolean theForceComputeNormals)
2328 {
2329 const Standard_Real aThresDot = cos(theAngTol);
2330
2331 Standard_Boolean aRetVal = Standard_False, isNormalsFound = Standard_False;
2332
2333 // compute normals if they are absent
2334 TopExp_Explorer anExpFace(theShape,TopAbs_FACE);
2335 for (; anExpFace.More(); anExpFace.Next())
2336 {
2337 const TopoDS_Face& aFace = TopoDS::Face(anExpFace.Current());
2338 const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2339 if(aSurf.IsNull())
2340 continue;
2341 TopLoc_Location aLoc;
2342 const Handle(Poly_Triangulation)& aPT = BRep_Tool::Triangulation(aFace, aLoc);
2343 if(aPT.IsNull())
2344 continue;
2345 if (!theForceComputeNormals && aPT->HasNormals())
2346 {
2347 isNormalsFound = Standard_True;
2348 continue;
2349 }
2350
2351 aPT->AddNormals();
2352 GeomLProp_SLProps aSLP(aSurf, 2, Precision::Confusion());
2353 for (Standard_Integer i = 1; i <= aPT->NbNodes(); i++)
2354 {
2355 const gp_Pnt2d aP2d = aPT->UVNode (i);
2356 aSLP.SetParameters(aP2d.X(), aP2d.Y());
2357
2358 if(!aSLP.IsNormalDefined())
2359 {
2360 #ifdef OCCT_DEBUG
2361 std::cout << "BRepLib::EnsureNormalConsistency(): Cannot find normal!" << std::endl;
2362 #endif
2363 aPT->SetNormal (i, gp_Vec3f (0.0f));
2364 }
2365 else
2366 {
2367 gp_Dir aNorm = aSLP.Normal();
2368 if (aFace.Orientation() == TopAbs_REVERSED)
2369 {
2370 aNorm.Reverse();
2371 }
2372 aPT->SetNormal (i, aNorm);
2373 }
2374 }
2375
2376 aRetVal = Standard_True;
2377 isNormalsFound = Standard_True;
2378 }
2379
2380 if(!isNormalsFound)
2381 {
2382 return aRetVal;
2383 }
2384
2385 // loop by edges
2386 TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
2387 TopExp::MapShapesAndAncestors(theShape,TopAbs_EDGE,TopAbs_FACE,aMapEF);
2388 for(Standard_Integer anInd = 1; anInd <= aMapEF.Extent(); anInd++)
2389 {
2390 const TopoDS_Edge& anEdg = TopoDS::Edge(aMapEF.FindKey(anInd));
2391 const TopTools_ListOfShape& anEdgList = aMapEF.FindFromIndex(anInd);
2392 if (anEdgList.Extent() != 2)
2393 continue;
2394 TopTools_ListIteratorOfListOfShape anItF(anEdgList);
2395 const TopoDS_Face aFace1 = TopoDS::Face(anItF.Value());
2396 anItF.Next();
2397 const TopoDS_Face aFace2 = TopoDS::Face(anItF.Value());
2398 TopLoc_Location aLoc1, aLoc2;
2399 const Handle(Poly_Triangulation)& aPT1 = BRep_Tool::Triangulation(aFace1, aLoc1);
2400 const Handle(Poly_Triangulation)& aPT2 = BRep_Tool::Triangulation(aFace2, aLoc2);
2401
2402 if(aPT1.IsNull() || aPT2.IsNull())
2403 continue;
2404
2405 if(!aPT1->HasNormals() || !aPT2->HasNormals())
2406 continue;
2407
2408 const Handle(Poly_PolygonOnTriangulation)& aPTEF1 =
2409 BRep_Tool::PolygonOnTriangulation(anEdg, aPT1, aLoc1);
2410 const Handle(Poly_PolygonOnTriangulation)& aPTEF2 =
2411 BRep_Tool::PolygonOnTriangulation(anEdg, aPT2, aLoc2);
2412
2413 if (aPTEF1->Nodes().Lower() != aPTEF2->Nodes().Lower() ||
2414 aPTEF1->Nodes().Upper() != aPTEF2->Nodes().Upper())
2415 continue;
2416
2417 for(Standard_Integer anEdgNode = aPTEF1->Nodes().Lower();
2418 anEdgNode <= aPTEF1->Nodes().Upper(); anEdgNode++)
2419 {
2420 //Number of node
2421 const Standard_Integer aFNodF1 = aPTEF1->Nodes().Value(anEdgNode);
2422 const Standard_Integer aFNodF2 = aPTEF2->Nodes().Value(anEdgNode);
2423
2424 gp_Vec3f aNorm1f, aNorm2f;
2425 aPT1->Normal (aFNodF1, aNorm1f);
2426 aPT1->Normal (aFNodF2, aNorm2f);
2427 const gp_XYZ aNorm1 (aNorm1f.x(), aNorm1f.y(), aNorm1f.z());
2428 const gp_XYZ aNorm2 (aNorm2f.x(), aNorm2f.y(), aNorm2f.z());
2429 const Standard_Real aDot = aNorm1 * aNorm2;
2430 if (aDot > aThresDot)
2431 {
2432 gp_XYZ aNewNorm = (aNorm1 + aNorm2).Normalized();
2433 aPT1->SetNormal (aFNodF1, aNewNorm);
2434 aPT2->SetNormal (aFNodF2, aNewNorm);
2435 aRetVal = Standard_True;
2436 }
2437 }
2438 }
2439
2440 return aRetVal;
2441 }
2442
2443 //=======================================================================
2444 //function : UpdateDeflection
2445 //purpose :
2446 //=======================================================================
2447 namespace
2448 {
2449 //! Tool to estimate deflection of the given UV point
2450 //! with regard to its representation in 3D space.
2451 struct EvalDeflection
2452 {
2453 BRepAdaptor_Surface Surface;
2454
2455 //! Initializes tool with the given face.
EvalDeflection__anon4a4e77d80111::EvalDeflection2456 EvalDeflection (const TopoDS_Face& theFace)
2457 : Surface (theFace)
2458 {
2459 }
2460
2461 //! Evaluates deflection of the given 2d point from its 3d representation.
Eval__anon4a4e77d80111::EvalDeflection2462 Standard_Real Eval (const gp_Pnt2d& thePoint2d, const gp_Pnt& thePoint3d)
2463 {
2464 gp_Pnt aPnt;
2465 Surface.D0 (thePoint2d.X (), thePoint2d.Y (), aPnt);
2466 return (thePoint3d.XYZ () - aPnt.XYZ ()).SquareModulus ();
2467 }
2468 };
2469
2470 //! Represents link of triangulation.
2471 struct Link
2472 {
2473 Standard_Integer Node[2];
2474
2475 //! Constructor
Link__anon4a4e77d80111::Link2476 Link (const Standard_Integer theNode1, const Standard_Integer theNode2)
2477 {
2478 Node[0] = theNode1;
2479 Node[1] = theNode2;
2480 }
2481
2482 //! Computes a hash code for the this link
HashCode__anon4a4e77d80111::Link2483 Standard_Integer HashCode (const Standard_Integer theUpperBound) const
2484 {
2485 return ::HashCode (Node[0] + Node[1], theUpperBound);
2486 }
2487
2488 //! Returns true if this link has the same nodes as the other.
IsEqual__anon4a4e77d80111::Link2489 Standard_Boolean IsEqual (const Link& theOther) const
2490 {
2491 return ((Node[0] == theOther.Node[0] && Node[1] == theOther.Node[1]) ||
2492 (Node[0] == theOther.Node[1] && Node[1] == theOther.Node[0]));
2493 }
2494
2495 //! Alias for IsEqual.
operator ==__anon4a4e77d80111::Link2496 Standard_Boolean operator ==(const Link& theOther) const
2497 {
2498 return IsEqual (theOther);
2499 }
2500 };
2501
2502 //! Computes a hash code for the given link
HashCode(const Link & theLink,const Standard_Integer theUpperBound)2503 inline Standard_Integer HashCode (const Link& theLink, const Standard_Integer theUpperBound)
2504 {
2505 return theLink.HashCode (theUpperBound);
2506 }
2507 }
2508
UpdateDeflection(const TopoDS_Shape & theShape)2509 void BRepLib::UpdateDeflection (const TopoDS_Shape& theShape)
2510 {
2511 TopExp_Explorer anExpFace (theShape, TopAbs_FACE);
2512 for (; anExpFace.More(); anExpFace.Next())
2513 {
2514 const TopoDS_Face& aFace = TopoDS::Face (anExpFace.Current());
2515 const Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aFace);
2516 if (aSurf.IsNull())
2517 {
2518 continue;
2519 }
2520
2521 TopLoc_Location aLoc;
2522 const Handle(Poly_Triangulation)& aPT = BRep_Tool::Triangulation (aFace, aLoc);
2523 if (aPT.IsNull() || !aPT->HasUVNodes())
2524 {
2525 continue;
2526 }
2527
2528 // Collect all nodes of degenerative edges and skip elements
2529 // build upon them due to huge distortions introduced by passage
2530 // from UV space to 3D.
2531 NCollection_Map<Standard_Integer> aDegNodes;
2532 TopExp_Explorer anExpEdge (aFace, TopAbs_EDGE);
2533 for (; anExpEdge.More(); anExpEdge.Next())
2534 {
2535 const TopoDS_Edge& aEdge = TopoDS::Edge (anExpEdge.Current());
2536 if (BRep_Tool::Degenerated (aEdge))
2537 {
2538 const Handle(Poly_PolygonOnTriangulation)& aPolygon = BRep_Tool::PolygonOnTriangulation (aEdge, aPT, aLoc);
2539 if (aPolygon.IsNull ())
2540 {
2541 continue;
2542 }
2543
2544 for (Standard_Integer aNodeIt = aPolygon->Nodes().Lower(); aNodeIt <= aPolygon->Nodes().Upper(); ++aNodeIt)
2545 {
2546 aDegNodes.Add (aPolygon->Node (aNodeIt));
2547 }
2548 }
2549 }
2550
2551 EvalDeflection aTool (aFace);
2552 NCollection_Map<Link> aLinks;
2553 Standard_Real aSqDeflection = 0.;
2554 const gp_Trsf& aTrsf = aLoc.Transformation();
2555 for (Standard_Integer aTriIt = 1; aTriIt <= aPT->NbTriangles(); ++aTriIt)
2556 {
2557 const Poly_Triangle& aTriangle = aPT->Triangle (aTriIt);
2558
2559 int aNode[3];
2560 aTriangle.Get (aNode[0], aNode[1], aNode[2]);
2561 if (aDegNodes.Contains (aNode[0]) ||
2562 aDegNodes.Contains (aNode[1]) ||
2563 aDegNodes.Contains (aNode[2]))
2564 {
2565 continue;
2566 }
2567
2568 const gp_Pnt aP3d[3] = {
2569 aPT->Node (aNode[0]).Transformed (aTrsf),
2570 aPT->Node (aNode[1]).Transformed (aTrsf),
2571 aPT->Node (aNode[2]).Transformed (aTrsf)
2572 };
2573
2574 const gp_Pnt2d aP2d[3] = {
2575 aPT->UVNode (aNode[0]),
2576 aPT->UVNode (aNode[1]),
2577 aPT->UVNode (aNode[2])
2578 };
2579
2580 // Check midpoint of triangle.
2581 const gp_Pnt aMid3d_t = (aP3d[0].XYZ() + aP3d[1].XYZ() + aP3d[2].XYZ()) / 3.;
2582 const gp_Pnt2d aMid2d_t = (aP2d[0].XY () + aP2d[1].XY () + aP2d[2].XY ()) / 3.;
2583
2584 aSqDeflection = Max (aSqDeflection, aTool.Eval (aMid2d_t, aMid3d_t));
2585
2586 for (Standard_Integer i = 0; i < 3; ++i)
2587 {
2588 const Standard_Integer j = (i + 1) % 3;
2589 const Link aLink (aNode[i], aNode[j]);
2590 if (!aLinks.Add (aLink))
2591 {
2592 // Do not estimate boundary links due to high distortions at the edge.
2593 const gp_Pnt& aP3d1 = aP3d[i];
2594 const gp_Pnt& aP3d2 = aP3d[j];
2595
2596 const gp_Pnt2d& aP2d1 = aP2d[i];
2597 const gp_Pnt2d& aP2d2 = aP2d[j];
2598
2599 const gp_Pnt aMid3d_l = (aP3d1.XYZ() + aP3d2.XYZ()) / 2.;
2600 const gp_Pnt2d aMid2d_l = (aP2d1.XY () + aP2d2.XY ()) / 2.;
2601
2602 aSqDeflection = Max (aSqDeflection, aTool.Eval (aMid2d_l, aMid3d_l));
2603 }
2604 }
2605 }
2606
2607 aPT->Deflection (Sqrt (aSqDeflection));
2608 }
2609 }
2610
2611 //=======================================================================
2612 //function : SortFaces
2613 //purpose :
2614 //=======================================================================
2615
SortFaces(const TopoDS_Shape & Sh,TopTools_ListOfShape & LF)2616 void BRepLib::SortFaces (const TopoDS_Shape& Sh,
2617 TopTools_ListOfShape& LF)
2618 {
2619 LF.Clear();
2620 TopTools_ListOfShape LTri,LPlan,LCyl,LCon,LSphere,LTor,LOther;
2621 TopExp_Explorer exp(Sh,TopAbs_FACE);
2622 TopLoc_Location l;
2623 Handle(Geom_Surface) S;
2624
2625 for (; exp.More(); exp.Next()) {
2626 const TopoDS_Face& F = TopoDS::Face(exp.Current());
2627 S = BRep_Tool::Surface(F, l);
2628 if (!S.IsNull()) {
2629 if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
2630 S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
2631 }
2632 GeomAdaptor_Surface AS(S);
2633 switch (AS.GetType()) {
2634 case GeomAbs_Plane:
2635 {
2636 LPlan.Append(F);
2637 break;
2638 }
2639 case GeomAbs_Cylinder:
2640 {
2641 LCyl.Append(F);
2642 break;
2643 }
2644 case GeomAbs_Cone:
2645 {
2646 LCon.Append(F);
2647 break;
2648 }
2649 case GeomAbs_Sphere:
2650 {
2651 LSphere.Append(F);
2652 break;
2653 }
2654 case GeomAbs_Torus:
2655 {
2656 LTor.Append(F);
2657 break;
2658 }
2659 default:
2660 LOther.Append(F);
2661 }
2662 }
2663 else LTri.Append(F);
2664 }
2665 LF.Append(LPlan); LF.Append(LCyl ); LF.Append(LCon); LF.Append(LSphere);
2666 LF.Append(LTor ); LF.Append(LOther); LF.Append(LTri);
2667 }
2668
2669 //=======================================================================
2670 //function : ReverseSortFaces
2671 //purpose :
2672 //=======================================================================
2673
ReverseSortFaces(const TopoDS_Shape & Sh,TopTools_ListOfShape & LF)2674 void BRepLib::ReverseSortFaces (const TopoDS_Shape& Sh,
2675 TopTools_ListOfShape& LF)
2676 {
2677 LF.Clear();
2678 // Use the allocator of the result LF for intermediate results
2679 TopTools_ListOfShape LTri(LF.Allocator()), LPlan(LF.Allocator()),
2680 LCyl(LF.Allocator()), LCon(LF.Allocator()), LSphere(LF.Allocator()),
2681 LTor(LF.Allocator()), LOther(LF.Allocator());
2682 TopExp_Explorer exp(Sh,TopAbs_FACE);
2683 TopLoc_Location l;
2684
2685 for (; exp.More(); exp.Next()) {
2686 const TopoDS_Face& F = TopoDS::Face(exp.Current());
2687 const Handle(Geom_Surface)& S = BRep_Tool::Surface(F, l);
2688 if (!S.IsNull()) {
2689 GeomAdaptor_Surface AS(S);
2690 switch (AS.GetType()) {
2691 case GeomAbs_Plane:
2692 {
2693 LPlan.Append(F);
2694 break;
2695 }
2696 case GeomAbs_Cylinder:
2697 {
2698 LCyl.Append(F);
2699 break;
2700 }
2701 case GeomAbs_Cone:
2702 {
2703 LCon.Append(F);
2704 break;
2705 }
2706 case GeomAbs_Sphere:
2707 {
2708 LSphere.Append(F);
2709 break;
2710 }
2711 case GeomAbs_Torus:
2712 {
2713 LTor.Append(F);
2714 break;
2715 }
2716 default:
2717 LOther.Append(F);
2718 }
2719 }
2720 else LTri.Append(F);
2721 }
2722 LF.Append(LTri); LF.Append(LOther); LF.Append(LTor ); LF.Append(LSphere);
2723 LF.Append(LCon); LF.Append(LCyl ); LF.Append(LPlan);
2724
2725 }
2726
2727 //=======================================================================
2728 // function: BoundingVertex
2729 // purpose :
2730 //=======================================================================
BoundingVertex(const NCollection_List<TopoDS_Shape> & theLV,gp_Pnt & theNewCenter,Standard_Real & theNewTol)2731 void BRepLib::BoundingVertex(const NCollection_List<TopoDS_Shape>& theLV,
2732 gp_Pnt& theNewCenter, Standard_Real& theNewTol)
2733 {
2734 Standard_Integer aNb;
2735 //
2736 aNb=theLV.Extent();
2737 if (aNb < 2) {
2738 return;
2739 }
2740 //
2741 else if (aNb==2) {
2742 Standard_Integer m, n;
2743 Standard_Real aR[2], dR, aD, aEps;
2744 TopoDS_Vertex aV[2];
2745 gp_Pnt aP[2];
2746 //
2747 aEps=RealEpsilon();
2748 for (m=0; m<aNb; ++m) {
2749 aV[m]=(!m)?
2750 *((TopoDS_Vertex*)(&theLV.First())):
2751 *((TopoDS_Vertex*)(&theLV.Last()));
2752 aP[m]=BRep_Tool::Pnt(aV[m]);
2753 aR[m]=BRep_Tool::Tolerance(aV[m]);
2754 }
2755 //
2756 m=0; // max R
2757 n=1; // min R
2758 if (aR[0]<aR[1]) {
2759 m=1;
2760 n=0;
2761 }
2762 //
2763 dR=aR[m]-aR[n]; // dR >= 0.
2764 gp_Vec aVD(aP[m], aP[n]);
2765 aD=aVD.Magnitude();
2766 //
2767 if (aD<=dR || aD<aEps) {
2768 theNewCenter = aP[m];
2769 theNewTol = aR[m];
2770 }
2771 else {
2772 Standard_Real aRr;
2773 gp_XYZ aXYZr;
2774 gp_Pnt aPr;
2775 //
2776 aRr=0.5*(aR[m]+aR[n]+aD);
2777 aXYZr=0.5*(aP[m].XYZ()+aP[n].XYZ()-aVD.XYZ()*(dR/aD));
2778 aPr.SetXYZ(aXYZr);
2779 //
2780 theNewCenter = aPr;
2781 theNewTol = aRr;
2782 //aBB.MakeVertex (aVnew, aPr, aRr);
2783 }
2784 return;
2785 }// else if (aNb==2) {
2786 //
2787 else { // if (aNb>2)
2788 // compute the point
2789 //
2790 // issue 0027540 - sum of doubles may depend on the order
2791 // of addition, thus sort the coordinates for stable result
2792 Standard_Integer i;
2793 NCollection_Array1<gp_Pnt> aPoints(0, aNb-1);
2794 NCollection_List<TopoDS_Edge>::Iterator aIt(theLV);
2795 for (i = 0; aIt.More(); aIt.Next(), ++i) {
2796 const TopoDS_Vertex& aVi = *((TopoDS_Vertex*)(&aIt.Value()));
2797 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
2798 aPoints(i) = aPi;
2799 }
2800 //
2801 std::sort(aPoints.begin(), aPoints.end(), BRepLib_ComparePoints());
2802 //
2803 gp_XYZ aXYZ(0., 0., 0.);
2804 for (i = 0; i < aNb; ++i) {
2805 aXYZ += aPoints(i).XYZ();
2806 }
2807 aXYZ.Divide((Standard_Real)aNb);
2808 //
2809 gp_Pnt aP(aXYZ);
2810 //
2811 // compute the tolerance for the new vertex
2812 Standard_Real aTi, aDi, aDmax;
2813 //
2814 aDmax=-1.;
2815 aIt.Initialize(theLV);
2816 for (; aIt.More(); aIt.Next()) {
2817 TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
2818 gp_Pnt aPi=BRep_Tool::Pnt(aVi);
2819 aTi=BRep_Tool::Tolerance(aVi);
2820 aDi=aP.SquareDistance(aPi);
2821 aDi=sqrt(aDi);
2822 aDi=aDi+aTi;
2823 if (aDi > aDmax) {
2824 aDmax=aDi;
2825 }
2826 }
2827 //
2828 theNewCenter = aP;
2829 theNewTol = aDmax;
2830 }
2831 }
2832
2833 //=======================================================================
2834 //function : ExtendFace
2835 //purpose :
2836 //=======================================================================
ExtendFace(const TopoDS_Face & theF,const Standard_Real theExtVal,const Standard_Boolean theExtUMin,const Standard_Boolean theExtUMax,const Standard_Boolean theExtVMin,const Standard_Boolean theExtVMax,TopoDS_Face & theFExtended)2837 void BRepLib::ExtendFace(const TopoDS_Face& theF,
2838 const Standard_Real theExtVal,
2839 const Standard_Boolean theExtUMin,
2840 const Standard_Boolean theExtUMax,
2841 const Standard_Boolean theExtVMin,
2842 const Standard_Boolean theExtVMax,
2843 TopoDS_Face& theFExtended)
2844 {
2845 // Get face bounds
2846 BRepAdaptor_Surface aBAS(theF);
2847 Standard_Real aFUMin = aBAS.FirstUParameter(),
2848 aFUMax = aBAS.LastUParameter(),
2849 aFVMin = aBAS.FirstVParameter(),
2850 aFVMax = aBAS.LastVParameter();
2851 const Standard_Real aTol = BRep_Tool::Tolerance(theF);
2852
2853 // Surface to build the face
2854 Handle(Geom_Surface) aS;
2855
2856 const GeomAbs_SurfaceType aType = aBAS.GetType();
2857 // treat analytical surfaces first
2858 if (aType == GeomAbs_Plane ||
2859 aType == GeomAbs_Sphere ||
2860 aType == GeomAbs_Cylinder ||
2861 aType == GeomAbs_Torus ||
2862 aType == GeomAbs_Cone)
2863 {
2864 // Get basis transformed basis surface
2865 Handle(Geom_Surface) aSurf = Handle(Geom_Surface)::
2866 DownCast(aBAS.Surface().Surface()->Transformed(aBAS.Trsf()));
2867
2868 // Get bounds of the basis surface
2869 Standard_Real aSUMin, aSUMax, aSVMin, aSVMax;
2870 aSurf->Bounds(aSUMin, aSUMax, aSVMin, aSVMax);
2871
2872 Standard_Boolean isUPeriodic = aBAS.IsUPeriodic();
2873 Standard_Real anUPeriod = isUPeriodic ? aBAS.UPeriod() : 0.0;
2874 if (isUPeriodic)
2875 {
2876 // Adjust face bounds to first period
2877 Standard_Real aDelta = aFUMax - aFUMin;
2878 aFUMin = Max(aSUMin, aFUMin + anUPeriod*Ceiling((aSUMin - aFUMin) / anUPeriod));
2879 aFUMax = aFUMin + aDelta;
2880 }
2881
2882 Standard_Boolean isVPeriodic = aBAS.IsVPeriodic();
2883 Standard_Real aVPeriod = isVPeriodic ? aBAS.VPeriod() : 0.0;
2884 if (isVPeriodic)
2885 {
2886 // Adjust face bounds to first period
2887 Standard_Real aDelta = aFVMax - aFVMin;
2888 aFVMin = Max(aSVMin, aFVMin + aVPeriod*Ceiling((aSVMin - aFVMin) / aVPeriod));
2889 aFVMax = aFVMin + aDelta;
2890 }
2891
2892 // Enlarge the face
2893 Standard_Real anURes = 0., aVRes = 0.;
2894 if (theExtUMin || theExtUMax)
2895 anURes = aBAS.UResolution(theExtVal);
2896 if (theExtVMin || theExtVMax)
2897 aVRes = aBAS.VResolution(theExtVal);
2898
2899 if (theExtUMin) aFUMin = Max(aSUMin, aFUMin - anURes);
2900 if (theExtUMax) aFUMax = Min(isUPeriodic ? aFUMin + anUPeriod : aSUMax, aFUMax + anURes);
2901 if (theExtVMin) aFVMin = Max(aSVMin, aFVMin - aVRes);
2902 if (theExtVMax) aFVMax = Min(isVPeriodic ? aFVMin + aVPeriod : aSVMax, aFVMax + aVRes);
2903
2904 // Check if the periodic surface should become closed.
2905 // In this case, use the basis surface with basis bounds.
2906 const Standard_Real anEps = Precision::PConfusion();
2907 if (isUPeriodic && Abs(aFUMax - aFUMin - anUPeriod) < anEps)
2908 {
2909 aFUMin = aSUMin;
2910 aFUMax = aSUMax;
2911 }
2912 if (isVPeriodic && Abs(aFVMax - aFVMin - aVPeriod) < anEps)
2913 {
2914 aFVMin = aSVMin;
2915 aFVMax = aSVMax;
2916 }
2917
2918 aS = aSurf;
2919 }
2920 else
2921 {
2922 // General case
2923
2924 Handle(Geom_BoundedSurface) aSB =
2925 Handle(Geom_BoundedSurface)::DownCast(BRep_Tool::Surface(theF));
2926 if (aSB.IsNull())
2927 {
2928 theFExtended = theF;
2929 return;
2930 }
2931
2932 // Get surfaces bounds
2933 Standard_Real aSUMin, aSUMax, aSVMin, aSVMax;
2934 aSB->Bounds(aSUMin, aSUMax, aSVMin, aSVMax);
2935
2936 Standard_Boolean isUClosed = aSB->IsUClosed();
2937 Standard_Boolean isVClosed = aSB->IsVClosed();
2938
2939 // Check if the extension in necessary directions is done
2940 Standard_Boolean isExtUMin = Standard_False,
2941 isExtUMax = Standard_False,
2942 isExtVMin = Standard_False,
2943 isExtVMax = Standard_False;
2944
2945 // UMin
2946 if (theExtUMin && !isUClosed && !Precision::IsInfinite(aSUMin)) {
2947 GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_True, Standard_False);
2948 isExtUMin = Standard_True;
2949 }
2950 // UMax
2951 if (theExtUMax && !isUClosed && !Precision::IsInfinite(aSUMax)) {
2952 GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_True, Standard_True);
2953 isExtUMax = Standard_True;
2954 }
2955 // VMin
2956 if (theExtVMin && !isVClosed && !Precision::IsInfinite(aSVMax)) {
2957 GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_False, Standard_False);
2958 isExtVMin = Standard_True;
2959 }
2960 // VMax
2961 if (theExtVMax && !isVClosed && !Precision::IsInfinite(aSVMax)) {
2962 GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_False, Standard_True);
2963 isExtVMax = Standard_True;
2964 }
2965
2966 aS = aSB;
2967
2968 // Get new bounds
2969 aS->Bounds(aSUMin, aSUMax, aSVMin, aSVMax);
2970 if (isExtUMin) aFUMin = aSUMin;
2971 if (isExtUMax) aFUMax = aSUMax;
2972 if (isExtVMin) aFVMin = aSVMin;
2973 if (isExtVMax) aFVMax = aSVMax;
2974 }
2975
2976 BRepLib_MakeFace aMF(aS, aFUMin, aFUMax, aFVMin, aFVMax, aTol);
2977 theFExtended = *(TopoDS_Face*)&aMF.Shape();
2978 if (theF.Orientation() == TopAbs_REVERSED)
2979 theFExtended.Reverse();
2980 }
2981