OCC22311 A regression was found: face obtained from 2D offset of a wire is invalid
[occt.git] / src / BRepFill / BRepFill_TrimEdgeTool.cxx
CommitLineData
7fd59977 1// File: BRepFill_TrimEdgeTool.cxx
2// Created: Mon Apr 24 16:40:33 1995
3// Author: Bruno DUMORTIER
4// <dub@fuegox>
5
6
7#include <BRepFill_TrimEdgeTool.ixx>
8#include <BRep_Tool.hxx>
9#include <Bisector_BisecAna.hxx>
10#include <Geom2d_Curve.hxx>
11#include <Geom2d_TrimmedCurve.hxx>
12#include <Geom2d_CartesianPoint.hxx>
13#include <Geom_Curve.hxx>
14#include <GeomProjLib.hxx>
15#include <Geom_TrimmedCurve.hxx>
16#include <Geom2dAPI_ProjectPointOnCurve.hxx>
17#include <Geom2dInt_GInter.hxx>
18#include <gp_Pnt.hxx>
19#include <TopLoc_Location.hxx>
20#include <TopoDS.hxx>
21#include <Precision.hxx>
22#include <IntRes2d_IntersectionPoint.hxx>
23#include <IntRes2d_IntersectionSegment.hxx>
24
25#include <StdFail_NotDone.hxx>
26
27#ifdef DRAW
28#include <DrawTrSurf.hxx>
29#include <DBRep.hxx>
30static Standard_Boolean Affich = Standard_False;
31#endif
32
33
34//=======================================================================
35//function : SimpleExpression
36//purpose :
37//=======================================================================
38
39static void SimpleExpression (const Bisector_Bisec& B,
40 Handle(Geom2d_Curve)& Bis)
41{
42 Bis = B.Value();
43
44 Handle(Standard_Type) BT = Bis->DynamicType();
45 if (BT == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
46 Handle(Geom2d_TrimmedCurve) TrBis
47 = Handle(Geom2d_TrimmedCurve)::DownCast(Bis);
48 Handle(Geom2d_Curve) BasBis = TrBis->BasisCurve();
49 BT = BasBis->DynamicType();
50 if (BT == STANDARD_TYPE(Bisector_BisecAna)) {
51 Bis = Handle(Bisector_BisecAna)::DownCast(BasBis)->Geom2dCurve();
52 Bis = new Geom2d_TrimmedCurve (Bis,
53 TrBis->FirstParameter(),
54 TrBis->LastParameter());
55 }
56 }
57}
58
59
60//=======================================================================
61//function : BRepFill_TrimEdgeTool
62//purpose :
63//=======================================================================
64
65BRepFill_TrimEdgeTool::BRepFill_TrimEdgeTool()
66{
67}
68
69
70//=======================================================================
71//function : BRepFill_TrimEdgeTool
72//purpose :
73//=======================================================================
74
75BRepFill_TrimEdgeTool::BRepFill_TrimEdgeTool
76(const Bisector_Bisec& Bisec,
77 const Handle(Geom2d_Geometry)& S1,
78 const Handle(Geom2d_Geometry)& S2,
79 const Standard_Real Offset) :
80myOffset(Offset),
81myBisec(Bisec)
82{
83 isPoint1 = (S1->DynamicType() == STANDARD_TYPE(Geom2d_CartesianPoint));
84 isPoint2 = (S2->DynamicType() == STANDARD_TYPE(Geom2d_CartesianPoint));
85
86 // recuperation des geometries des shapes.
87// Standard_Real f,l;
88 if (isPoint1) {
89 myP1 = Handle(Geom2d_Point)::DownCast(S1)->Pnt2d();
90 }
91 else {
92 myC1 = Handle(Geom2d_Curve)::DownCast(S1);
93#ifdef DRAW
94 if ( Affich) {
95//POP pour NT
96 char* myC1name = "myC1";
97 DrawTrSurf::Set(myC1name,myC1);
98// DrawTrSurf::Set("myC1",myC1);
99 }
100#endif
101 }
102 if (isPoint2) {
103 myP2 = Handle(Geom2d_Point)::DownCast(S2)->Pnt2d();
104 }
105 else {
106 myC2 = Handle(Geom2d_Curve)::DownCast(S2);
107#ifdef DRAW
108 if ( Affich) {
109 char* myC2name = "myC2";
110 DrawTrSurf::Set(myC2name,myC2);
111// DrawTrSurf::Set("myC2",myC2);
112 }
113#endif
114 }
115 // recuperer l expression simple de la bisectrice
116 Handle(Geom2d_Curve) Bis;
117 SimpleExpression(myBisec, Bis);
118 myBis = Geom2dAdaptor_Curve(Bis);
119#ifdef DRAW
120 if ( Affich) {
121 char* myBisname = "myBis";
122 DrawTrSurf::Set(myBisname,Bis);
123 }
124#endif
125
126}
127
128//=======================================================================
129//function : Bubble
130//purpose : Ordonne la sequence de point en x croissant.
131//=======================================================================
132
133static void Bubble(TColgp_SequenceOfPnt& Seq)
134{
135 Standard_Boolean Invert = Standard_True;
136 Standard_Integer NbPoints = Seq.Length();
137 while (Invert) {
138 Invert = Standard_False;
139 for ( Standard_Integer i = 1; i < NbPoints; i++) {
140 gp_Pnt P1 = Seq.Value(i);
141 gp_Pnt P2 = Seq.Value(i+1);
142 if (P2.X()<P1.X()) {
143 Seq.Exchange(i,i+1);
144 Invert = Standard_True;
145 }
146 }
147 }
148}
149
150
151//=======================================================================
152//function : EvalParameters (lbr le 8 juillet, je duplique pour modifier)
153//purpose :
154//=======================================================================
155
156static void EvalParameters(const Geom2dAdaptor_Curve& Bis,
157 const Geom2dAdaptor_Curve& AC,
158 TColgp_SequenceOfPnt& Params)
159{
160 Geom2dInt_GInter Intersector;
161 Standard_Real Tol = Precision::Intersection();
162// Standard_Real TolC = 1.e-9;
163
164 Geom2dAdaptor_Curve CBis(Bis);
165 Geom2dAdaptor_Curve CAC (AC);
166
167 if(AC.GetType() != GeomAbs_Circle || AC.GetType() != GeomAbs_Line) {
168 Tol *= 100.;
169 }
170
171 //Intersector = Geom2dInt_GInter(CBis, CAC, TolC, Tol);
172 Intersector = Geom2dInt_GInter(CAC, CBis, Tol, Tol);
173
174 Standard_Integer NbPoints, NbSegments;
175 Standard_Real U1, U2;
176 gp_Pnt P;
177
178 if ( !Intersector.IsDone()) {
179 StdFail_NotDone::Raise("BRepFill_TrimSurfaceTool::IntersectWith");
180 }
181
182 NbPoints = Intersector.NbPoints();
183
184 if (NbPoints > 0) {
185 for ( Standard_Integer i = 1; i <= NbPoints; i++) {
186 U1 = Intersector.Point(i).ParamOnSecond();
187 U2 = Intersector.Point(i).ParamOnFirst();
188 P = gp_Pnt(U1,U2,0.);
189 Params.Append(P);
190 }
191
192 }
193
194 NbSegments = Intersector.NbSegments();
195
196 if (NbSegments > 0) {
197 IntRes2d_IntersectionSegment Seg;
198 for ( Standard_Integer i = 1; i <= NbSegments; i++) {
199 Seg = Intersector.Segment(i);
200 U1 = Seg.FirstPoint().ParamOnSecond();
201 Standard_Real Ulast = Seg.LastPoint().ParamOnSecond();
202 if ( Abs(U1 - CBis.FirstParameter()) <= Tol &&
203 Abs(Ulast - CBis.LastParameter()) <= Tol ) {
204 P = gp_Pnt(U1,Seg.FirstPoint().ParamOnFirst(),0.);
205 Params.Append(P);
206 P = gp_Pnt(Ulast,Seg.LastPoint().ParamOnFirst(),0.);
207 Params.Append(P);
208 }
209 else {
210 U1 += Seg.LastPoint().ParamOnSecond();
211 U1 /= 2.;
212 U2 = Seg.FirstPoint().ParamOnFirst();
213 U2 += Seg.LastPoint().ParamOnFirst();
214 U2 /= 2.;
215 P = gp_Pnt(U1,U2,0.);
216 Params.Append(P);
217 }
218 }
219 }
220
221 // Ordonne la sequence en param croissant sur la bissectrice.
222 Bubble( Params);
223}
224
225static void EvalParametersBis(const Geom2dAdaptor_Curve& Bis,
226 const Geom2dAdaptor_Curve& AC,
227 TColgp_SequenceOfPnt& Params,
228 const Standard_Real Tol)
229{
230 Geom2dInt_GInter Intersector;
231 Standard_Real TolC = Tol;
232
233 Geom2dAdaptor_Curve CBis(Bis);
234 Geom2dAdaptor_Curve CAC (AC);
235
236 Intersector = Geom2dInt_GInter(CAC, CBis, TolC, Tol);
237
238 Standard_Integer NbPoints, NbSegments;
239 Standard_Real U1, U2;
240 gp_Pnt P;
241
242 if ( !Intersector.IsDone()) {
243 StdFail_NotDone::Raise("BRepFill_TrimSurfaceTool::IntersectWith");
244 }
245
246 NbPoints = Intersector.NbPoints();
247
248 if (NbPoints > 0) {
249 for ( Standard_Integer i = 1; i <= NbPoints; i++) {
250 U1 = Intersector.Point(i).ParamOnSecond();
251 U2 = Intersector.Point(i).ParamOnFirst();
252 P = gp_Pnt(U1,U2,0.);
253 Params.Append(P);
254 }
255
256 }
257
258 NbSegments = Intersector.NbSegments();
259
260 if (NbSegments > 0) {
261 IntRes2d_IntersectionSegment Seg;
262 for ( Standard_Integer i = 1; i <= NbSegments; i++) {
263 Seg = Intersector.Segment(i);
264 U1 = Seg.FirstPoint().ParamOnSecond();
265 Standard_Real Ulast = Seg.LastPoint().ParamOnSecond();
266 if ( Abs(U1 - CBis.FirstParameter()) <= Tol &&
267 Abs(Ulast - CBis.LastParameter()) <= Tol ) {
268 P = gp_Pnt(U1,Seg.FirstPoint().ParamOnFirst(),0.);
269 Params.Append(P);
270 P = gp_Pnt(Ulast,Seg.LastPoint().ParamOnFirst(),0.);
271 Params.Append(P);
272 }
273 else {
274 U1 += Seg.LastPoint().ParamOnSecond();
275 U1 /= 2.;
276 U2 = Seg.FirstPoint().ParamOnFirst();
277 U2 += Seg.LastPoint().ParamOnFirst();
278 U2 /= 2.;
279 P = gp_Pnt(U1,U2,0.);
280 Params.Append(P);
281 }
282 }
283 }
284
285 // Ordonne la sequence en param croissant sur la bissectrice.
286 Bubble( Params);
287}
288
289
290//=======================================================================
291//function : IntersectWith
292//purpose :
293//=======================================================================
294
295void BRepFill_TrimEdgeTool::IntersectWith(const TopoDS_Edge& Edge1,
296 const TopoDS_Edge& Edge2,
297 TColgp_SequenceOfPnt& Params)
298{
299 Params.Clear();
300
301 // recuperer les courbes associees aux edges.
302 TopLoc_Location L;
303 Standard_Real f,l;
304 Handle(Geom_Surface) Surf;
305
306 Handle(Geom2d_Curve) C1;
307 BRep_Tool::CurveOnSurface(Edge1,C1,Surf,L,f,l);
308 Geom2dAdaptor_Curve AC1(C1,f,l);
309
310 Handle(Geom2d_Curve) C2;
311 BRep_Tool::CurveOnSurface(Edge2,C2,Surf,L,f,l);
312 Geom2dAdaptor_Curve AC2(C2,f,l);
313
314#ifdef DRAW
315 if ( Affich) {
316 f = AC1.FirstParameter();
317 l = AC1.LastParameter();
318 char* CURVE1name = "CURVE1";
319 DrawTrSurf::Set(CURVE1name, new Geom2d_TrimmedCurve(C1,f,l));
320 f = AC2.FirstParameter();
321 l = AC2.LastParameter();
322 char* CURVE2name = "CURVE2";
323 DrawTrSurf::Set(CURVE2name, new Geom2d_TrimmedCurve(C2,f,l));
324 f = myBis.FirstParameter();
325 l = myBis.LastParameter();
326 char* bisname = "BIS";
327 DrawTrSurf::Set(bisname, new Geom2d_TrimmedCurve(myBis.Curve(),f,l));
328 char* Edge1name = "E1";
329 DBRep::Set(Edge1name, Edge1);
330 char* Edge2name = "E2";
331 DBRep::Set(Edge2name, Edge2);
332
333 }
334#endif
335
336 // Calcul intersection
337 TColgp_SequenceOfPnt Points2;
338 gp_Pnt PSeq;
339
340 EvalParameters (myBis,AC1,Params);
341 EvalParameters (myBis,AC2,Points2);
342
343
344 Standard_Integer SeanceDeRattrapage=0;
345 Standard_Real TolInit= 1.e-9;
346 Standard_Integer nn = 7;
347
348 if(AC1.GetType() != GeomAbs_Circle ||
349 AC1.GetType() != GeomAbs_Line ||
350 AC2.GetType() != GeomAbs_Circle ||
351 AC2.GetType() != GeomAbs_Line ) {
352
353 TolInit = 1.e-8;
354 nn = 6;
355 }
356
357 while ( SeanceDeRattrapage < nn // TolInit <= 0.01
358 && ( Points2.Length() != Params.Length() ||
359 (Points2.Length() == 0 && Params.Length() == 0) ) ) {
360
361#ifdef DEB
362 cout << "BRepFill_TrimEdgeTool: incoherent intersection. On essaie avec une tol plus grande" << endl;
363#endif
364
365 Params.Clear();
366 Points2.Clear();
367
368 TolInit*=10.0;
369
370 EvalParametersBis(myBis,AC1,Params,TolInit);
371 EvalParametersBis(myBis,AC2,Points2,TolInit);
372 SeanceDeRattrapage++;
373 }
374
375#ifdef DEB
376 if(SeanceDeRattrapage != 0) cout << "SeanceDeRattrapage = " << SeanceDeRattrapage << endl;
377 if(SeanceDeRattrapage == nn) {
378 cout << "BRepFill_TrimEdgeTool: incoherent intersection" << endl;
379 }
380#endif
381
382
383 if(Params.Length() == 0 && Points2.Length() == 1) {
384
385 //cout << "Params.Length() == 0 && Points2.Length() == 1" << endl;
386 Standard_Real dmin;
387 Standard_Real tBis = Points2(1).X();
388 gp_Pnt2d PBis = myBis.Value(tBis);
389
390 Standard_Real t = AC1.FirstParameter();
391 gp_Pnt2d PC = AC1.Value(t);
392 dmin = PC.SquareDistance(PBis);
393 gp_Pnt P(tBis, t, 0.);
394 Params.Append(P);
395
396 t = AC1.LastParameter();
397 PC = AC1.Value(t);
398 if(dmin > PC.SquareDistance(PBis)) {
399 P.SetY(t);
400 Params.SetValue(1,P);
401 }
402 }
403 else if(Params.Length() == 1 && Points2.Length() == 0) {
404
405 //cout << "Params.Length() == 1 && Points2.Length() == 0" << endl;
406 Standard_Real dmin;
407 Standard_Real tBis = Params(1).X();
408 gp_Pnt2d PBis = myBis.Value(tBis);
409
410 Standard_Real t = AC2.FirstParameter();
411 gp_Pnt2d PC = AC2.Value(t);
412 dmin = PC.SquareDistance(PBis);
413 gp_Pnt P(tBis, t, 0.);
414 Points2.Append(P);
415
416 t = AC2.LastParameter();
417 PC = AC2.Value(t);
418 if(dmin > PC.SquareDistance(PBis)) {
419 P.SetY(t);
420 Points2.SetValue(1,P);
421 }
422 }
423
424 // petite manip destinee a eliminer les intersections incoherentes:
425 // on ne renvoie que les intersections communes ( meme parametre sur
426 // la bissectrice.).
427 // La tolerance pourra eventuellement etre reglee.
428
429 gp_Pnt P1,P2;
430 Standard_Real Tol = 4 * 100 * Precision::PConfusion();
431 Standard_Integer i = 1;
432 Standard_Integer NbPoints = Params.Length();
433
434 if(NbPoints == 1 && Points2.Length() == 1) {
435 //cout << "NbPoints == 1 && Points2.Length() == 1" << endl;
436 for ( i = 1; i <= NbPoints; i++) {
437 PSeq = Params(i);
438 PSeq.SetZ((Points2.Value(i)).Y());
439 Params.SetValue(i,PSeq);
440 }
441 return;
442 }
443
444 i = 1;
445 while ( i <= Min( Params.Length(), Points2.Length())) {
446 P1 = Params(i);
447 P2 = Points2(i);
448 Standard_Real P1xP2x=Abs( P1.X() - P2.X());
449
450 if ( P1xP2x > Tol ) {
451#ifdef DEB
452 cout << "BRepFill_TrimEdgeTool: Pas le meme parametre sur la bissectrice" << endl;
453#endif
454 if(P1xP2x>TolInit) {
455#ifdef DEB
456 cout << "BRepFill_TrimEdgeTool: On continue quand meme" << endl;
457#endif
458 i++;
459 }
460 else {
461 if ( P1.X() < P2.X()) Params.Remove(i);
462 else Points2.Remove(i);
463 }
464 }
465 else i++;
466 }
467
468 if ( Params.Length() > Points2.Length()) {
469 Params.Remove(Points2.Length()+1, Params.Length());
470 }
471 else if ( Params.Length() < Points2.Length()) {
472 Points2.Remove(Params.Length()+1, Points2.Length());
473 }
474
475 NbPoints = Params.Length();
476 for ( i = 1; i <= NbPoints; i++) {
477 PSeq = Params(i);
478 PSeq.SetZ((Points2.Value(i)).Y());
479 Params.SetValue(i,PSeq);
480 }
481}
482
483//=======================================================================
484//function : AddOrConfuse
485//purpose : le premier ou le dernier point de la bissectrice est sur la
486// parallele si on ne l a pas trouve dans les intersections on
487// le projette sur les paralleles et on l ajoute dans les params
488//=======================================================================
489
490void BRepFill_TrimEdgeTool::AddOrConfuse(const Standard_Boolean Start,
491 const TopoDS_Edge& Edge1,
492 const TopoDS_Edge& Edge2,
493 TColgp_SequenceOfPnt& Params)
494const
495{
496 Standard_Boolean ToProj = Standard_True;
497 gp_Pnt2d PBis;
498 Standard_Real Tol = 10*Precision::Confusion();
499
500 // recuperer les courbes associees aux edges.
501 TopLoc_Location L;
502 Standard_Real f,l;
503 Handle(Geom_Surface) Surf;
504
505 Handle(Geom2d_Curve) C1;
506 BRep_Tool::CurveOnSurface(Edge1,C1,Surf,L,f,l);
507 Geom2dAdaptor_Curve AC1(C1,f,l);
508
509
510 if (Start) PBis = myBis.Value(myBis.FirstParameter());
511 else PBis = myBis.Value(myBis.LastParameter ());
512
513 // Test si le bout de la bissectrice est dans l ensemble des points d intersection.
514 if (!Params.IsEmpty()) {
515 gp_Pnt2d P;
516 if (Start) P = AC1.Value(Params.First().Y());
517 else P = AC1.Value(Params.Last ().Y());
518 ToProj = !PBis.IsEqual(P,Tol);
519 }
520
521 if (ToProj) {
522#ifdef DEB
523 cout << " projection extremite bissectrice sur parallele."<<endl;
524#endif
525
526 // Projection du point sur les paralleles et ajout dans Params
527
528 Standard_Real f2,l2;
529 Handle(Geom2d_Curve) C2;
530 BRep_Tool::CurveOnSurface(Edge2,C2,Surf,L,f2,l2);
531
532 Geom2dAPI_ProjectPointOnCurve Projector1(PBis,C1,f,l);
533 Geom2dAPI_ProjectPointOnCurve Projector2(PBis,C2,f2,l2);
534
535 if (Projector1.NbPoints() == 0) {
536#ifdef DEB
537 cout << "Echec projection dans BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
538#endif
539 return;
540 }
541 if (!Projector1.NearestPoint().IsEqual(PBis,Tol)) {
542#ifdef DEB
543 cout <<" Mauvaisesolution dans BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
544#endif
545 return;
546 }
547 if (Projector2.NbPoints() == 0) {
548#ifdef DEB
549 cout << "Echec projection dans BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
550#endif
551 return;
552 }
553 if (!Projector2.NearestPoint().IsEqual(PBis,Tol)) {
554#ifdef DEB
555 cout <<" Mauvaisesolution dans BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
556#endif
557 return;
558 }
559 gp_Pnt PInt (0,
560 Projector1.LowerDistanceParameter(),
561 Projector2.LowerDistanceParameter());
562 if (Start) {
563 PInt.SetX (myBis.FirstParameter());
564 Params.Prepend(PInt);
565 }
566 else {
567 PInt.SetX (myBis.LastParameter());
568 Params.Append(PInt);
569 }
570 }
571}
572
573//=======================================================================
574//function : IsInside
575//purpose :
576//=======================================================================
577
578Standard_Boolean BRepFill_TrimEdgeTool::IsInside(const gp_Pnt2d& P) const
579{
580// Modified by Sergey KHROMOV - Fri Sep 27 11:43:12 2002 Begin
581// Standard_Real Dist;
582 Standard_Real Dist = RealLast();
583// Modified by Sergey KHROMOV - Fri Sep 27 11:43:12 2002 End
584 if (isPoint1)
585 Dist = P.Distance(myP1);
586 else if (isPoint2)
587 Dist = P.Distance(myP2);
588 else {
589 Geom2dAPI_ProjectPointOnCurve Projector(P,myC1);
590 if (Projector.NbPoints() > 0) {
591 Dist = Projector.LowerDistance();
592 }
593// Modified by Sergey KHROMOV - Fri Sep 27 11:43:43 2002 Begin
594// else {
595// gp_Pnt2d PF = myC1->Value(myC1->FirstParameter());
596// gp_Pnt2d PL = myC1->Value(myC1->LastParameter());
597// Dist = Min (P.Distance(PF),P.Distance(PL));
598// }
599
600// Check of distances between P and first and last point of the first curve
601// should be performed in any case, despite of the results of projection.
602 gp_Pnt2d PF = myC1->Value(myC1->FirstParameter());
603 gp_Pnt2d PL = myC1->Value(myC1->LastParameter());
604 Standard_Real aDistMin = Min (P.Distance(PF),P.Distance(PL));
605
606 if (Dist > aDistMin)
607 Dist = aDistMin;
608// Modified by Sergey KHROMOV - Fri Sep 27 11:43:44 2002 End
609 }
610
611// return (Dist < Abs(myOffset);
612// return (Dist < Abs(myOffset) + Precision::Confusion());
613 return (Dist < Abs(myOffset) - Precision::Confusion());
614}
615