0023140: Suspicious if
[occt.git] / src / BRepFill / BRepFill_TrimEdgeTool.cxx
CommitLineData
b311480e 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
7fd59977 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>
46static Standard_Boolean Affich = Standard_False;
47#endif
48
49
50//=======================================================================
51//function : SimpleExpression
52//purpose :
53//=======================================================================
54
55static 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
81BRepFill_TrimEdgeTool::BRepFill_TrimEdgeTool()
82{
83}
84
85
86//=======================================================================
87//function : BRepFill_TrimEdgeTool
88//purpose :
89//=======================================================================
90
91BRepFill_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) :
96myOffset(Offset),
97myBisec(Bisec)
98{
99 isPoint1 = (S1->DynamicType() == STANDARD_TYPE(Geom2d_CartesianPoint));
100 isPoint2 = (S2->DynamicType() == STANDARD_TYPE(Geom2d_CartesianPoint));
101
0d969553 102// return geometries of shapes.
7fd59977 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 }
0d969553 131 // return the simple expression of the bissectrice
7fd59977 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
0d969553 146//purpose : Order the sequence of points by increasing x.
7fd59977 147//=======================================================================
148
149static 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//=======================================================================
0d969553 168//function : EvalParameters
7fd59977 169//purpose :
170//=======================================================================
171
172static void EvalParameters(const Geom2dAdaptor_Curve& Bis,
173 const Geom2dAdaptor_Curve& AC,
174 TColgp_SequenceOfPnt& Params)
175{
176 Geom2dInt_GInter Intersector;
5768cd55 177 Standard_Real Tol = Precision::Confusion();
7fd59977 178// Standard_Real TolC = 1.e-9;
179
180 Geom2dAdaptor_Curve CBis(Bis);
181 Geom2dAdaptor_Curve CAC (AC);
182
7fd59977 183 //Intersector = Geom2dInt_GInter(CBis, CAC, TolC, Tol);
184 Intersector = Geom2dInt_GInter(CAC, CBis, Tol, Tol);
185
186 Standard_Integer NbPoints, NbSegments;
187 Standard_Real U1, U2;
188 gp_Pnt P;
189
190 if ( !Intersector.IsDone()) {
191 StdFail_NotDone::Raise("BRepFill_TrimSurfaceTool::IntersectWith");
192 }
193
194 NbPoints = Intersector.NbPoints();
195
196 if (NbPoints > 0) {
197 for ( Standard_Integer i = 1; i <= NbPoints; i++) {
198 U1 = Intersector.Point(i).ParamOnSecond();
199 U2 = Intersector.Point(i).ParamOnFirst();
200 P = gp_Pnt(U1,U2,0.);
201 Params.Append(P);
202 }
203
204 }
205
206 NbSegments = Intersector.NbSegments();
207
208 if (NbSegments > 0) {
209 IntRes2d_IntersectionSegment Seg;
210 for ( Standard_Integer i = 1; i <= NbSegments; i++) {
211 Seg = Intersector.Segment(i);
212 U1 = Seg.FirstPoint().ParamOnSecond();
213 Standard_Real Ulast = Seg.LastPoint().ParamOnSecond();
214 if ( Abs(U1 - CBis.FirstParameter()) <= Tol &&
215 Abs(Ulast - CBis.LastParameter()) <= Tol ) {
216 P = gp_Pnt(U1,Seg.FirstPoint().ParamOnFirst(),0.);
217 Params.Append(P);
218 P = gp_Pnt(Ulast,Seg.LastPoint().ParamOnFirst(),0.);
219 Params.Append(P);
220 }
221 else {
222 U1 += Seg.LastPoint().ParamOnSecond();
223 U1 /= 2.;
224 U2 = Seg.FirstPoint().ParamOnFirst();
225 U2 += Seg.LastPoint().ParamOnFirst();
226 U2 /= 2.;
227 P = gp_Pnt(U1,U2,0.);
228 Params.Append(P);
229 }
230 }
231 }
232
0d969553 233 // Order the sequence by growing parameter on the bissectrice.
7fd59977 234 Bubble( Params);
235}
236
237static void EvalParametersBis(const Geom2dAdaptor_Curve& Bis,
238 const Geom2dAdaptor_Curve& AC,
239 TColgp_SequenceOfPnt& Params,
240 const Standard_Real Tol)
241{
242 Geom2dInt_GInter Intersector;
243 Standard_Real TolC = Tol;
244
245 Geom2dAdaptor_Curve CBis(Bis);
246 Geom2dAdaptor_Curve CAC (AC);
247
248 Intersector = Geom2dInt_GInter(CAC, CBis, TolC, Tol);
249
250 Standard_Integer NbPoints, NbSegments;
251 Standard_Real U1, U2;
252 gp_Pnt P;
253
254 if ( !Intersector.IsDone()) {
255 StdFail_NotDone::Raise("BRepFill_TrimSurfaceTool::IntersectWith");
256 }
257
258 NbPoints = Intersector.NbPoints();
259
260 if (NbPoints > 0) {
261 for ( Standard_Integer i = 1; i <= NbPoints; i++) {
262 U1 = Intersector.Point(i).ParamOnSecond();
263 U2 = Intersector.Point(i).ParamOnFirst();
264 P = gp_Pnt(U1,U2,0.);
265 Params.Append(P);
266 }
267
268 }
269
270 NbSegments = Intersector.NbSegments();
271
272 if (NbSegments > 0) {
273 IntRes2d_IntersectionSegment Seg;
274 for ( Standard_Integer i = 1; i <= NbSegments; i++) {
275 Seg = Intersector.Segment(i);
276 U1 = Seg.FirstPoint().ParamOnSecond();
277 Standard_Real Ulast = Seg.LastPoint().ParamOnSecond();
278 if ( Abs(U1 - CBis.FirstParameter()) <= Tol &&
279 Abs(Ulast - CBis.LastParameter()) <= Tol ) {
280 P = gp_Pnt(U1,Seg.FirstPoint().ParamOnFirst(),0.);
281 Params.Append(P);
282 P = gp_Pnt(Ulast,Seg.LastPoint().ParamOnFirst(),0.);
283 Params.Append(P);
284 }
285 else {
286 U1 += Seg.LastPoint().ParamOnSecond();
287 U1 /= 2.;
288 U2 = Seg.FirstPoint().ParamOnFirst();
289 U2 += Seg.LastPoint().ParamOnFirst();
290 U2 /= 2.;
291 P = gp_Pnt(U1,U2,0.);
292 Params.Append(P);
293 }
294 }
295 }
296
0d969553 297 // Order the sequence by parameter growing on the bissectrice.
7fd59977 298 Bubble( Params);
299}
300
301
302//=======================================================================
303//function : IntersectWith
304//purpose :
305//=======================================================================
306
307void BRepFill_TrimEdgeTool::IntersectWith(const TopoDS_Edge& Edge1,
308 const TopoDS_Edge& Edge2,
309 TColgp_SequenceOfPnt& Params)
310{
311 Params.Clear();
312
0d969553 313 // return curves associated to edges.
7fd59977 314 TopLoc_Location L;
315 Standard_Real f,l;
316 Handle(Geom_Surface) Surf;
317
318 Handle(Geom2d_Curve) C1;
319 BRep_Tool::CurveOnSurface(Edge1,C1,Surf,L,f,l);
320 Geom2dAdaptor_Curve AC1(C1,f,l);
321
322 Handle(Geom2d_Curve) C2;
323 BRep_Tool::CurveOnSurface(Edge2,C2,Surf,L,f,l);
324 Geom2dAdaptor_Curve AC2(C2,f,l);
325
326#ifdef DRAW
327 if ( Affich) {
328 f = AC1.FirstParameter();
329 l = AC1.LastParameter();
330 char* CURVE1name = "CURVE1";
331 DrawTrSurf::Set(CURVE1name, new Geom2d_TrimmedCurve(C1,f,l));
332 f = AC2.FirstParameter();
333 l = AC2.LastParameter();
334 char* CURVE2name = "CURVE2";
335 DrawTrSurf::Set(CURVE2name, new Geom2d_TrimmedCurve(C2,f,l));
336 f = myBis.FirstParameter();
337 l = myBis.LastParameter();
338 char* bisname = "BIS";
339 DrawTrSurf::Set(bisname, new Geom2d_TrimmedCurve(myBis.Curve(),f,l));
340 char* Edge1name = "E1";
341 DBRep::Set(Edge1name, Edge1);
342 char* Edge2name = "E2";
343 DBRep::Set(Edge2name, Edge2);
344
345 }
346#endif
347
0d969553 348 // Calculate intersection
7fd59977 349 TColgp_SequenceOfPnt Points2;
350 gp_Pnt PSeq;
351
352 EvalParameters (myBis,AC1,Params);
353 EvalParameters (myBis,AC2,Points2);
354
355
356 Standard_Integer SeanceDeRattrapage=0;
357 Standard_Real TolInit= 1.e-9;
358 Standard_Integer nn = 7;
359
360 if(AC1.GetType() != GeomAbs_Circle ||
361 AC1.GetType() != GeomAbs_Line ||
362 AC2.GetType() != GeomAbs_Circle ||
363 AC2.GetType() != GeomAbs_Line ) {
364
365 TolInit = 1.e-8;
366 nn = 6;
367 }
368
369 while ( SeanceDeRattrapage < nn // TolInit <= 0.01
370 && ( Points2.Length() != Params.Length() ||
371 (Points2.Length() == 0 && Params.Length() == 0) ) ) {
372
373#ifdef DEB
0d969553 374 cout << "BRepFill_TrimEdgeTool: incoherent intersection. Try with a greater tolerance" << endl;
7fd59977 375#endif
376
377 Params.Clear();
378 Points2.Clear();
379
380 TolInit*=10.0;
381
382 EvalParametersBis(myBis,AC1,Params,TolInit);
383 EvalParametersBis(myBis,AC2,Points2,TolInit);
384 SeanceDeRattrapage++;
385 }
386
387#ifdef DEB
388 if(SeanceDeRattrapage != 0) cout << "SeanceDeRattrapage = " << SeanceDeRattrapage << endl;
389 if(SeanceDeRattrapage == nn) {
390 cout << "BRepFill_TrimEdgeTool: incoherent intersection" << endl;
391 }
392#endif
393
394
395 if(Params.Length() == 0 && Points2.Length() == 1) {
396
397 //cout << "Params.Length() == 0 && Points2.Length() == 1" << endl;
398 Standard_Real dmin;
399 Standard_Real tBis = Points2(1).X();
400 gp_Pnt2d PBis = myBis.Value(tBis);
401
402 Standard_Real t = AC1.FirstParameter();
403 gp_Pnt2d PC = AC1.Value(t);
404 dmin = PC.SquareDistance(PBis);
405 gp_Pnt P(tBis, t, 0.);
406 Params.Append(P);
407
408 t = AC1.LastParameter();
409 PC = AC1.Value(t);
410 if(dmin > PC.SquareDistance(PBis)) {
411 P.SetY(t);
412 Params.SetValue(1,P);
413 }
414 }
415 else if(Params.Length() == 1 && Points2.Length() == 0) {
416
417 //cout << "Params.Length() == 1 && Points2.Length() == 0" << endl;
418 Standard_Real dmin;
419 Standard_Real tBis = Params(1).X();
420 gp_Pnt2d PBis = myBis.Value(tBis);
421
422 Standard_Real t = AC2.FirstParameter();
423 gp_Pnt2d PC = AC2.Value(t);
424 dmin = PC.SquareDistance(PBis);
425 gp_Pnt P(tBis, t, 0.);
426 Points2.Append(P);
427
428 t = AC2.LastParameter();
429 PC = AC2.Value(t);
430 if(dmin > PC.SquareDistance(PBis)) {
431 P.SetY(t);
432 Points2.SetValue(1,P);
433 }
434 }
435
0d969553
Y
436 // small manipulation to remove incorrect intersections:
437 // return only common intersections (same parameter
438 // on the bissectrice.).
439 // The tolerance can be eventually changed.
7fd59977 440
441 gp_Pnt P1,P2;
442 Standard_Real Tol = 4 * 100 * Precision::PConfusion();
443 Standard_Integer i = 1;
444 Standard_Integer NbPoints = Params.Length();
445
446 if(NbPoints == 1 && Points2.Length() == 1) {
447 //cout << "NbPoints == 1 && Points2.Length() == 1" << endl;
448 for ( i = 1; i <= NbPoints; i++) {
449 PSeq = Params(i);
450 PSeq.SetZ((Points2.Value(i)).Y());
451 Params.SetValue(i,PSeq);
452 }
453 return;
454 }
455
456 i = 1;
457 while ( i <= Min( Params.Length(), Points2.Length())) {
458 P1 = Params(i);
459 P2 = Points2(i);
460 Standard_Real P1xP2x=Abs( P1.X() - P2.X());
461
462 if ( P1xP2x > Tol ) {
463#ifdef DEB
0d969553 464 cout << "BRepFill_TrimEdgeTool: no same parameter on the bissectrice" << endl;
7fd59977 465#endif
466 if(P1xP2x>TolInit) {
467#ifdef DEB
0d969553 468 cout << "BRepFill_TrimEdgeTool: Continue somehow" << endl;
7fd59977 469#endif
470 i++;
471 }
472 else {
473 if ( P1.X() < P2.X()) Params.Remove(i);
474 else Points2.Remove(i);
475 }
476 }
477 else i++;
478 }
479
480 if ( Params.Length() > Points2.Length()) {
481 Params.Remove(Points2.Length()+1, Params.Length());
482 }
483 else if ( Params.Length() < Points2.Length()) {
484 Points2.Remove(Params.Length()+1, Points2.Length());
485 }
486
487 NbPoints = Params.Length();
488 for ( i = 1; i <= NbPoints; i++) {
489 PSeq = Params(i);
490 PSeq.SetZ((Points2.Value(i)).Y());
491 Params.SetValue(i,PSeq);
492 }
493}
494
495//=======================================================================
496//function : AddOrConfuse
0d969553
Y
497//purpose : the first or the last point of the bissectrice is on the
498// parallel if it was not found in the intersections,
499// it is projected on parallel lines and added in the parameters
7fd59977 500//=======================================================================
501
502void BRepFill_TrimEdgeTool::AddOrConfuse(const Standard_Boolean Start,
503 const TopoDS_Edge& Edge1,
504 const TopoDS_Edge& Edge2,
505 TColgp_SequenceOfPnt& Params)
506const
507{
508 Standard_Boolean ToProj = Standard_True;
509 gp_Pnt2d PBis;
510 Standard_Real Tol = 10*Precision::Confusion();
511
0d969553 512 // return curves associated to edges.
7fd59977 513 TopLoc_Location L;
514 Standard_Real f,l;
515 Handle(Geom_Surface) Surf;
516
517 Handle(Geom2d_Curve) C1;
518 BRep_Tool::CurveOnSurface(Edge1,C1,Surf,L,f,l);
519 Geom2dAdaptor_Curve AC1(C1,f,l);
520
521
522 if (Start) PBis = myBis.Value(myBis.FirstParameter());
523 else PBis = myBis.Value(myBis.LastParameter ());
524
0d969553 525 // Test if the end of the bissectrice is in the set of intersection points.
7fd59977 526 if (!Params.IsEmpty()) {
527 gp_Pnt2d P;
528 if (Start) P = AC1.Value(Params.First().Y());
529 else P = AC1.Value(Params.Last ().Y());
530 ToProj = !PBis.IsEqual(P,Tol);
531 }
532
533 if (ToProj) {
534#ifdef DEB
0d969553 535 cout << " project extremity bissectrice on parallel."<<endl;
7fd59977 536#endif
537
0d969553 538 // Project point on parallels and add in Params
7fd59977 539
540 Standard_Real f2,l2;
541 Handle(Geom2d_Curve) C2;
542 BRep_Tool::CurveOnSurface(Edge2,C2,Surf,L,f2,l2);
543
544 Geom2dAPI_ProjectPointOnCurve Projector1(PBis,C1,f,l);
545 Geom2dAPI_ProjectPointOnCurve Projector2(PBis,C2,f2,l2);
546
547 if (Projector1.NbPoints() == 0) {
548#ifdef DEB
0d969553 549 cout << "Failed projection in BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
7fd59977 550#endif
551 return;
552 }
553 if (!Projector1.NearestPoint().IsEqual(PBis,Tol)) {
554#ifdef DEB
0d969553 555 cout <<"Incorrect solution in BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
7fd59977 556#endif
557 return;
558 }
559 if (Projector2.NbPoints() == 0) {
560#ifdef DEB
0d969553 561 cout << "Failed projection in BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
7fd59977 562#endif
563 return;
564 }
565 if (!Projector2.NearestPoint().IsEqual(PBis,Tol)) {
566#ifdef DEB
567 cout <<" Mauvaisesolution dans BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
568#endif
569 return;
570 }
571 gp_Pnt PInt (0,
572 Projector1.LowerDistanceParameter(),
573 Projector2.LowerDistanceParameter());
574 if (Start) {
575 PInt.SetX (myBis.FirstParameter());
576 Params.Prepend(PInt);
577 }
578 else {
579 PInt.SetX (myBis.LastParameter());
580 Params.Append(PInt);
581 }
582 }
583}
584
585//=======================================================================
586//function : IsInside
587//purpose :
588//=======================================================================
589
590Standard_Boolean BRepFill_TrimEdgeTool::IsInside(const gp_Pnt2d& P) const
591{
592// Modified by Sergey KHROMOV - Fri Sep 27 11:43:12 2002 Begin
593// Standard_Real Dist;
594 Standard_Real Dist = RealLast();
595// Modified by Sergey KHROMOV - Fri Sep 27 11:43:12 2002 End
596 if (isPoint1)
597 Dist = P.Distance(myP1);
598 else if (isPoint2)
599 Dist = P.Distance(myP2);
600 else {
601 Geom2dAPI_ProjectPointOnCurve Projector(P,myC1);
602 if (Projector.NbPoints() > 0) {
603 Dist = Projector.LowerDistance();
604 }
605// Modified by Sergey KHROMOV - Fri Sep 27 11:43:43 2002 Begin
606// else {
607// gp_Pnt2d PF = myC1->Value(myC1->FirstParameter());
608// gp_Pnt2d PL = myC1->Value(myC1->LastParameter());
609// Dist = Min (P.Distance(PF),P.Distance(PL));
610// }
611
612// Check of distances between P and first and last point of the first curve
613// should be performed in any case, despite of the results of projection.
614 gp_Pnt2d PF = myC1->Value(myC1->FirstParameter());
615 gp_Pnt2d PL = myC1->Value(myC1->LastParameter());
616 Standard_Real aDistMin = Min (P.Distance(PF),P.Distance(PL));
617
618 if (Dist > aDistMin)
619 Dist = aDistMin;
620// Modified by Sergey KHROMOV - Fri Sep 27 11:43:44 2002 End
621 }
622
623// return (Dist < Abs(myOffset);
624// return (Dist < Abs(myOffset) + Precision::Confusion());
625 return (Dist < Abs(myOffset) - Precision::Confusion());
626}
627