48afa9fd6e2dd5a16ab232f1374b013a85ec4467
[occt.git] / src / BRepFill / BRepFill_TrimEdgeTool.cxx
1 // Created on: 1995-04-24
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <BRepFill_TrimEdgeTool.ixx>
24 #include <BRep_Tool.hxx>
25 #include <Bisector_BisecAna.hxx>
26 #include <Geom2d_Curve.hxx>
27 #include <Geom2d_TrimmedCurve.hxx>
28 #include <Geom2d_CartesianPoint.hxx>
29 #include <Geom_Curve.hxx>
30 #include <GeomProjLib.hxx>
31 #include <Geom_TrimmedCurve.hxx>
32 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
33 #include <Geom2dInt_GInter.hxx>
34 #include <gp_Pnt.hxx>
35 #include <TopLoc_Location.hxx>
36 #include <TopoDS.hxx>
37 #include <Precision.hxx>
38 #include <IntRes2d_IntersectionPoint.hxx>
39 #include <IntRes2d_IntersectionSegment.hxx>
40
41 #include <StdFail_NotDone.hxx>
42
43 #ifdef DRAW
44 #include <DrawTrSurf.hxx>
45 #include <DBRep.hxx>
46 static Standard_Boolean Affich       = Standard_False;
47 #endif
48
49
50 //=======================================================================
51 //function : SimpleExpression
52 //purpose  : 
53 //=======================================================================
54
55 static void SimpleExpression (const Bisector_Bisec&        B, 
56                                     Handle(Geom2d_Curve)&  Bis)
57 {
58   Bis = B.Value();
59
60   Handle(Standard_Type) BT = Bis->DynamicType();
61   if (BT == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
62     Handle(Geom2d_TrimmedCurve) TrBis 
63       = Handle(Geom2d_TrimmedCurve)::DownCast(Bis);
64     Handle(Geom2d_Curve) BasBis = TrBis->BasisCurve();
65     BT = BasBis->DynamicType();
66     if (BT == STANDARD_TYPE(Bisector_BisecAna)) {
67       Bis = Handle(Bisector_BisecAna)::DownCast(BasBis)->Geom2dCurve();
68       Bis = new Geom2d_TrimmedCurve (Bis,
69                                      TrBis->FirstParameter(),
70                                      TrBis->LastParameter());
71     }
72   }
73 }
74
75
76 //=======================================================================
77 //function : BRepFill_TrimEdgeTool
78 //purpose  : 
79 //=======================================================================
80
81 BRepFill_TrimEdgeTool::BRepFill_TrimEdgeTool()
82 {
83 }
84
85
86 //=======================================================================
87 //function : BRepFill_TrimEdgeTool
88 //purpose  : 
89 //=======================================================================
90
91 BRepFill_TrimEdgeTool::BRepFill_TrimEdgeTool
92 (const Bisector_Bisec& Bisec,
93  const Handle(Geom2d_Geometry)& S1,
94  const Handle(Geom2d_Geometry)& S2,
95  const Standard_Real   Offset) :
96 myOffset(Offset),
97 myBisec(Bisec)
98 {
99   isPoint1 = (S1->DynamicType() == STANDARD_TYPE(Geom2d_CartesianPoint));
100   isPoint2 = (S2->DynamicType() == STANDARD_TYPE(Geom2d_CartesianPoint));
101
102 // return geometries of shapes.
103 //  Standard_Real f,l;
104   if (isPoint1) {
105     myP1 = Handle(Geom2d_Point)::DownCast(S1)->Pnt2d();
106   }
107   else {
108     myC1 = Handle(Geom2d_Curve)::DownCast(S1);
109 #ifdef DRAW
110     if ( Affich) {
111 //POP pour NT
112       char* myC1name = "myC1";
113       DrawTrSurf::Set(myC1name,myC1);
114 //      DrawTrSurf::Set("myC1",myC1);
115     }
116 #endif
117   }
118   if (isPoint2) {
119     myP2 = Handle(Geom2d_Point)::DownCast(S2)->Pnt2d();
120   }
121   else {
122     myC2 = Handle(Geom2d_Curve)::DownCast(S2);
123 #ifdef DRAW
124     if ( Affich) {
125       char* myC2name = "myC2";
126       DrawTrSurf::Set(myC2name,myC2);
127 //      DrawTrSurf::Set("myC2",myC2);
128     }
129 #endif
130   }
131   // return the simple expression of the bissectrice
132   Handle(Geom2d_Curve) Bis;
133   SimpleExpression(myBisec, Bis);
134   myBis = Geom2dAdaptor_Curve(Bis);
135 #ifdef DRAW
136   if ( Affich) {
137       char* myBisname = "myBis";
138       DrawTrSurf::Set(myBisname,Bis);
139   }
140 #endif
141
142 }
143
144 //=======================================================================
145 //function : Bubble
146 //purpose  : Order the sequence of points by increasing x. 
147 //=======================================================================
148
149 static void Bubble(TColgp_SequenceOfPnt& Seq) 
150 {
151   Standard_Boolean Invert = Standard_True;
152   Standard_Integer NbPoints = Seq.Length();
153   while (Invert) {
154     Invert = Standard_False;
155     for ( Standard_Integer i = 1; i < NbPoints; i++) {
156       gp_Pnt P1 = Seq.Value(i);
157       gp_Pnt P2 = Seq.Value(i+1);
158       if (P2.X()<P1.X())  {
159         Seq.Exchange(i,i+1);
160         Invert = Standard_True;
161       }
162     }
163   }
164 }
165
166
167 //=======================================================================
168 //function : EvalParameters  
169 //purpose  : 
170 //=======================================================================
171
172 static void EvalParameters(const Geom2dAdaptor_Curve& Bis,
173                            const Geom2dAdaptor_Curve& AC,
174                                  TColgp_SequenceOfPnt& Params)
175 {
176   Geom2dInt_GInter Intersector;
177   Standard_Real Tol = Precision::Intersection();
178 //  Standard_Real TolC = 1.e-9;
179
180   Geom2dAdaptor_Curve CBis(Bis);
181   Geom2dAdaptor_Curve CAC (AC);
182
183   if(AC.GetType() != GeomAbs_Circle || AC.GetType() != GeomAbs_Line) {
184     Tol *= 100.;
185   } 
186
187   //Intersector = Geom2dInt_GInter(CBis, CAC, TolC, Tol);
188   Intersector = Geom2dInt_GInter(CAC, CBis, Tol, Tol);
189
190   Standard_Integer NbPoints, NbSegments;
191   Standard_Real U1, U2;
192   gp_Pnt P;
193
194   if ( !Intersector.IsDone()) {
195     StdFail_NotDone::Raise("BRepFill_TrimSurfaceTool::IntersectWith");
196   }
197   
198   NbPoints = Intersector.NbPoints();
199   
200   if (NbPoints > 0) {
201     for ( Standard_Integer i = 1; i <= NbPoints; i++) {
202       U1 = Intersector.Point(i).ParamOnSecond();
203       U2 = Intersector.Point(i).ParamOnFirst();
204       P = gp_Pnt(U1,U2,0.);
205       Params.Append(P);
206     }
207     
208   }
209   
210   NbSegments = Intersector.NbSegments();
211   
212   if (NbSegments > 0) {
213     IntRes2d_IntersectionSegment Seg;
214     for ( Standard_Integer i = 1; i <= NbSegments; i++) {
215       Seg = Intersector.Segment(i);
216       U1  = Seg.FirstPoint().ParamOnSecond();
217       Standard_Real Ulast = Seg.LastPoint().ParamOnSecond();
218       if ( Abs(U1    - CBis.FirstParameter()) <= Tol &&
219            Abs(Ulast - CBis.LastParameter())  <= Tol    ) {
220         P = gp_Pnt(U1,Seg.FirstPoint().ParamOnFirst(),0.);
221         Params.Append(P);
222         P = gp_Pnt(Ulast,Seg.LastPoint().ParamOnFirst(),0.);
223         Params.Append(P);
224       }
225       else {
226         U1 += Seg.LastPoint().ParamOnSecond();
227         U1 /= 2.;
228         U2  = Seg.FirstPoint().ParamOnFirst();
229         U2 += Seg.LastPoint().ParamOnFirst();
230         U2 /= 2.;
231         P = gp_Pnt(U1,U2,0.);
232         Params.Append(P);
233       }
234     }
235   }
236
237   // Order the sequence by growing parameter on the bissectrice.
238   Bubble( Params);
239 }
240                            
241 static void EvalParametersBis(const Geom2dAdaptor_Curve& Bis,
242                               const Geom2dAdaptor_Curve& AC,
243                               TColgp_SequenceOfPnt& Params,
244                               const Standard_Real Tol)
245 {
246   Geom2dInt_GInter Intersector;
247   Standard_Real TolC = Tol;
248   
249   Geom2dAdaptor_Curve CBis(Bis);
250   Geom2dAdaptor_Curve CAC (AC);
251
252   Intersector = Geom2dInt_GInter(CAC, CBis, TolC, Tol);
253
254   Standard_Integer NbPoints, NbSegments;
255   Standard_Real U1, U2;
256   gp_Pnt P;
257
258   if ( !Intersector.IsDone()) {
259     StdFail_NotDone::Raise("BRepFill_TrimSurfaceTool::IntersectWith");
260   }
261   
262   NbPoints = Intersector.NbPoints();
263   
264   if (NbPoints > 0) {
265     for ( Standard_Integer i = 1; i <= NbPoints; i++) {
266       U1 = Intersector.Point(i).ParamOnSecond();
267       U2 = Intersector.Point(i).ParamOnFirst();
268       P = gp_Pnt(U1,U2,0.);
269       Params.Append(P);
270     }
271     
272   }
273   
274   NbSegments = Intersector.NbSegments();
275   
276   if (NbSegments > 0) {
277     IntRes2d_IntersectionSegment Seg;
278     for ( Standard_Integer i = 1; i <= NbSegments; i++) {
279       Seg = Intersector.Segment(i);
280       U1  = Seg.FirstPoint().ParamOnSecond();
281       Standard_Real Ulast = Seg.LastPoint().ParamOnSecond();
282       if ( Abs(U1    - CBis.FirstParameter()) <= Tol &&
283            Abs(Ulast - CBis.LastParameter())  <= Tol    ) {
284         P = gp_Pnt(U1,Seg.FirstPoint().ParamOnFirst(),0.);
285         Params.Append(P);
286         P = gp_Pnt(Ulast,Seg.LastPoint().ParamOnFirst(),0.);
287         Params.Append(P);
288       }
289       else {
290         U1 += Seg.LastPoint().ParamOnSecond();
291         U1 /= 2.;
292         U2  = Seg.FirstPoint().ParamOnFirst();
293         U2 += Seg.LastPoint().ParamOnFirst();
294         U2 /= 2.;
295         P = gp_Pnt(U1,U2,0.);
296         Params.Append(P);
297       }
298     }
299   }
300
301   // Order the sequence by parameter growing on the bissectrice.
302   Bubble( Params);
303 }
304
305
306 //=======================================================================
307 //function : IntersectWith
308 //purpose  : 
309 //=======================================================================
310
311 void BRepFill_TrimEdgeTool::IntersectWith(const TopoDS_Edge& Edge1,
312                                           const TopoDS_Edge& Edge2,
313                                                 TColgp_SequenceOfPnt& Params)
314 {
315   Params.Clear();
316
317   // return curves associated to edges.
318   TopLoc_Location L;
319   Standard_Real   f,l;
320   Handle(Geom_Surface) Surf;
321
322   Handle(Geom2d_Curve) C1;
323   BRep_Tool::CurveOnSurface(Edge1,C1,Surf,L,f,l);
324   Geom2dAdaptor_Curve AC1(C1,f,l);
325
326   Handle(Geom2d_Curve) C2;
327   BRep_Tool::CurveOnSurface(Edge2,C2,Surf,L,f,l);
328   Geom2dAdaptor_Curve AC2(C2,f,l);
329
330 #ifdef DRAW
331   if ( Affich) {
332     f = AC1.FirstParameter();
333     l = AC1.LastParameter();
334     char* CURVE1name = "CURVE1";
335     DrawTrSurf::Set(CURVE1name, new Geom2d_TrimmedCurve(C1,f,l));
336     f = AC2.FirstParameter();
337     l = AC2.LastParameter();
338     char* CURVE2name = "CURVE2";
339     DrawTrSurf::Set(CURVE2name, new Geom2d_TrimmedCurve(C2,f,l));
340     f = myBis.FirstParameter();
341     l = myBis.LastParameter();
342     char* bisname = "BIS";
343     DrawTrSurf::Set(bisname, new Geom2d_TrimmedCurve(myBis.Curve(),f,l));
344     char* Edge1name = "E1";
345     DBRep::Set(Edge1name, Edge1);
346     char* Edge2name = "E2";
347     DBRep::Set(Edge2name, Edge2);
348
349   }
350 #endif
351   
352   // Calculate intersection
353   TColgp_SequenceOfPnt Points2;
354   gp_Pnt PSeq;
355
356   EvalParameters (myBis,AC1,Params);
357   EvalParameters (myBis,AC2,Points2);
358
359
360   Standard_Integer SeanceDeRattrapage=0;
361   Standard_Real TolInit= 1.e-9;
362   Standard_Integer nn = 7;
363
364   if(AC1.GetType() != GeomAbs_Circle ||
365      AC1.GetType() != GeomAbs_Line   ||
366      AC2.GetType() != GeomAbs_Circle ||
367      AC2.GetType() != GeomAbs_Line     ) {
368
369     TolInit = 1.e-8;
370     nn = 6;
371   }
372   
373   while (     SeanceDeRattrapage < nn // TolInit <= 0.01
374          && ( Points2.Length() != Params.Length() || 
375              (Points2.Length() == 0 && Params.Length() == 0) ) ) {
376
377 #ifdef DEB
378     cout << "BRepFill_TrimEdgeTool: incoherent intersection. Try with a greater tolerance" << endl;
379 #endif
380
381     Params.Clear();
382     Points2.Clear();
383     
384     TolInit*=10.0;
385     
386     EvalParametersBis(myBis,AC1,Params,TolInit);
387     EvalParametersBis(myBis,AC2,Points2,TolInit); 
388     SeanceDeRattrapage++;
389   }
390
391 #ifdef DEB
392   if(SeanceDeRattrapage != 0) cout << "SeanceDeRattrapage = " << SeanceDeRattrapage << endl;
393   if(SeanceDeRattrapage == nn) { 
394     cout << "BRepFill_TrimEdgeTool: incoherent intersection" << endl;
395   }
396 #endif
397
398
399   if(Params.Length() == 0 && Points2.Length() == 1) {
400
401     //cout << "Params.Length() == 0 && Points2.Length() == 1" << endl;
402     Standard_Real dmin;
403     Standard_Real tBis = Points2(1).X();
404     gp_Pnt2d PBis = myBis.Value(tBis);
405
406     Standard_Real t = AC1.FirstParameter();
407     gp_Pnt2d PC = AC1.Value(t);
408     dmin = PC.SquareDistance(PBis);
409     gp_Pnt P(tBis, t, 0.);
410     Params.Append(P);
411
412     t = AC1.LastParameter();
413     PC = AC1.Value(t);
414     if(dmin > PC.SquareDistance(PBis)) {
415       P.SetY(t);
416       Params.SetValue(1,P);
417     }
418   }
419   else if(Params.Length() == 1 && Points2.Length() == 0) {
420
421     //cout << "Params.Length() == 1 && Points2.Length() == 0" << endl;
422     Standard_Real dmin;
423     Standard_Real tBis = Params(1).X();
424     gp_Pnt2d PBis = myBis.Value(tBis);
425
426     Standard_Real t = AC2.FirstParameter();
427     gp_Pnt2d PC = AC2.Value(t);
428     dmin = PC.SquareDistance(PBis);
429     gp_Pnt P(tBis, t, 0.);
430     Points2.Append(P);
431
432     t = AC2.LastParameter();
433     PC = AC2.Value(t);
434     if(dmin > PC.SquareDistance(PBis)) {
435       P.SetY(t);
436       Points2.SetValue(1,P);
437     }
438   }
439
440   // small manipulation to remove incorrect intersections:
441   // return only common intersections (same parameter
442   // on the bissectrice.).
443   // The tolerance can be eventually changed.
444
445   gp_Pnt P1,P2;
446   Standard_Real Tol = 4 * 100 * Precision::PConfusion();
447   Standard_Integer i = 1;
448   Standard_Integer NbPoints = Params.Length();
449
450   if(NbPoints == 1 && Points2.Length() == 1) {
451     //cout << "NbPoints == 1 && Points2.Length() == 1" << endl;
452     for ( i = 1; i <= NbPoints; i++) {
453       PSeq = Params(i);
454       PSeq.SetZ((Points2.Value(i)).Y());
455       Params.SetValue(i,PSeq);
456     }
457     return;
458   }    
459
460   i = 1;
461   while ( i <= Min( Params.Length(), Points2.Length())) {
462     P1 = Params(i);
463     P2 = Points2(i);
464     Standard_Real P1xP2x=Abs( P1.X() - P2.X());
465
466     if ( P1xP2x > Tol ) {
467 #ifdef DEB
468       cout << "BRepFill_TrimEdgeTool: no same parameter on the bissectrice" << endl;
469 #endif
470       if(P1xP2x>TolInit) { 
471 #ifdef DEB
472       cout << "BRepFill_TrimEdgeTool: Continue somehow" << endl;
473 #endif  
474       i++;
475       }
476       else { 
477         if ( P1.X() < P2.X()) Params.Remove(i);
478         else                  Points2.Remove(i);
479       }
480     }
481     else i++;
482   }
483
484   if ( Params.Length() > Points2.Length()) {
485     Params.Remove(Points2.Length()+1, Params.Length());
486   }
487   else if ( Params.Length() < Points2.Length()) {
488     Points2.Remove(Params.Length()+1, Points2.Length());
489   }
490
491   NbPoints = Params.Length();
492   for ( i = 1; i <= NbPoints; i++) {
493     PSeq = Params(i);
494     PSeq.SetZ((Points2.Value(i)).Y());
495     Params.SetValue(i,PSeq);
496   }
497 }
498
499 //=======================================================================
500 //function : AddOrConfuse
501 //purpose  : the first or the last point of the bissectrice is on the 
502 //           parallel if it was not found in the intersections, 
503 //           it is projected on parallel lines and added in the parameters 
504 //=======================================================================
505
506 void BRepFill_TrimEdgeTool::AddOrConfuse(const Standard_Boolean  Start,
507                                          const TopoDS_Edge&      Edge1,
508                                          const TopoDS_Edge&      Edge2,
509                                          TColgp_SequenceOfPnt&   Params) 
510 const 
511 {
512   Standard_Boolean  ToProj = Standard_True;
513   gp_Pnt2d          PBis;
514   Standard_Real     Tol = 10*Precision::Confusion(); 
515
516   // return curves associated to edges.
517   TopLoc_Location L;
518   Standard_Real   f,l;
519   Handle(Geom_Surface) Surf;
520
521   Handle(Geom2d_Curve) C1;
522   BRep_Tool::CurveOnSurface(Edge1,C1,Surf,L,f,l);
523   Geom2dAdaptor_Curve AC1(C1,f,l);
524
525
526   if (Start) PBis = myBis.Value(myBis.FirstParameter());
527   else       PBis = myBis.Value(myBis.LastParameter ()); 
528
529   // Test if the end of the bissectrice is in the set of intersection points.
530   if (!Params.IsEmpty()) {
531     gp_Pnt2d P;
532     if (Start) P = AC1.Value(Params.First().Y());
533     else       P = AC1.Value(Params.Last ().Y()); 
534     ToProj     = !PBis.IsEqual(P,Tol);
535   }
536   
537   if (ToProj) {
538 #ifdef DEB
539     cout << " project extremity bissectrice on parallel."<<endl;
540 #endif
541
542     // Project point on parallels and add in Params
543
544     Standard_Real f2,l2;
545     Handle(Geom2d_Curve) C2;
546     BRep_Tool::CurveOnSurface(Edge2,C2,Surf,L,f2,l2);
547
548     Geom2dAPI_ProjectPointOnCurve Projector1(PBis,C1,f,l);    
549     Geom2dAPI_ProjectPointOnCurve Projector2(PBis,C2,f2,l2);
550
551     if (Projector1.NbPoints() == 0) {
552 #ifdef DEB
553       cout << "Failed projection in BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
554 #endif
555       return;
556     }
557     if (!Projector1.NearestPoint().IsEqual(PBis,Tol)) {
558 #ifdef DEB
559       cout <<"Incorrect solution in BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
560 #endif
561       return;
562     }
563     if (Projector2.NbPoints() == 0) {
564 #ifdef DEB
565       cout << "Failed projection in BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
566 #endif
567       return;
568     }
569     if (!Projector2.NearestPoint().IsEqual(PBis,Tol)) {
570 #ifdef DEB
571       cout <<" Mauvaisesolution dans BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
572 #endif
573       return;
574     }
575     gp_Pnt PInt (0,
576                  Projector1.LowerDistanceParameter(),
577                  Projector2.LowerDistanceParameter());
578     if (Start) {
579       PInt.SetX (myBis.FirstParameter());
580       Params.Prepend(PInt);
581     }
582     else {
583       PInt.SetX (myBis.LastParameter());
584       Params.Append(PInt);
585     }
586   }
587 }
588
589 //=======================================================================
590 //function : IsInside
591 //purpose  : 
592 //=======================================================================
593
594 Standard_Boolean BRepFill_TrimEdgeTool::IsInside(const gp_Pnt2d& P) const 
595 {
596 //  Modified by Sergey KHROMOV - Fri Sep 27 11:43:12 2002 Begin
597 //   Standard_Real Dist;
598   Standard_Real Dist = RealLast();
599 //  Modified by Sergey KHROMOV - Fri Sep 27 11:43:12 2002 End
600   if (isPoint1) 
601     Dist = P.Distance(myP1);
602   else if (isPoint2) 
603     Dist = P.Distance(myP2);
604   else {
605     Geom2dAPI_ProjectPointOnCurve Projector(P,myC1);
606     if (Projector.NbPoints() > 0) {
607       Dist = Projector.LowerDistance();
608     }
609 //  Modified by Sergey KHROMOV - Fri Sep 27 11:43:43 2002 Begin
610 //     else {
611 //       gp_Pnt2d PF = myC1->Value(myC1->FirstParameter());
612 //       gp_Pnt2d PL = myC1->Value(myC1->LastParameter());
613 //       Dist = Min (P.Distance(PF),P.Distance(PL));
614 //     }
615
616 // Check of distances between P and first and last point of the first curve
617 // should be performed in any case, despite of the results of projection.
618     gp_Pnt2d      PF       = myC1->Value(myC1->FirstParameter());
619     gp_Pnt2d      PL       = myC1->Value(myC1->LastParameter());
620     Standard_Real aDistMin = Min (P.Distance(PF),P.Distance(PL));
621
622     if (Dist > aDistMin)
623       Dist = aDistMin;
624 //  Modified by Sergey KHROMOV - Fri Sep 27 11:43:44 2002 End
625   }
626   
627 //  return (Dist < Abs(myOffset);
628 // return (Dist < Abs(myOffset) + Precision::Confusion());
629   return (Dist < Abs(myOffset) - Precision::Confusion());
630 }
631