1 // Created on: 1995-04-24
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <Bisector_Bisec.hxx>
19 #include <Bisector_BisecAna.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepFill_TrimEdgeTool.hxx>
23 #include <Geom2d_CartesianPoint.hxx>
24 #include <Geom2d_Curve.hxx>
25 #include <Geom2d_Geometry.hxx>
26 #include <Geom2d_TrimmedCurve.hxx>
27 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
28 #include <Geom2dInt_GInter.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom_TrimmedCurve.hxx>
31 #include <GeomProjLib.hxx>
33 #include <gp_Pnt2d.hxx>
34 #include <IntRes2d_IntersectionPoint.hxx>
35 #include <IntRes2d_IntersectionSegment.hxx>
36 #include <Precision.hxx>
37 #include <StdFail_NotDone.hxx>
38 #include <TopLoc_Location.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Vertex.hxx>
43 #include <BRepAdaptor_Curve.hxx>
48 #include <DrawTrSurf.hxx>
50 #include <Geom2d_Point.hxx>
51 static Standard_Boolean Affich = Standard_False;
52 static Standard_Boolean AffichInt = Standard_False;
53 static Standard_Integer intind = 0;
58 //=======================================================================
59 //function : SimpleExpression
61 //=======================================================================
63 static void SimpleExpression (const Bisector_Bisec& B,
64 Handle(Geom2d_Curve)& Bis)
68 Handle(Standard_Type) BT = Bis->DynamicType();
69 if (BT == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
70 Handle(Geom2d_TrimmedCurve) TrBis
71 = Handle(Geom2d_TrimmedCurve)::DownCast(Bis);
72 Handle(Geom2d_Curve) BasBis = TrBis->BasisCurve();
73 BT = BasBis->DynamicType();
74 if (BT == STANDARD_TYPE(Bisector_BisecAna)) {
75 Bis = Handle(Bisector_BisecAna)::DownCast(BasBis)->Geom2dCurve();
76 Bis = new Geom2d_TrimmedCurve (Bis,
77 TrBis->FirstParameter(),
78 TrBis->LastParameter());
84 //=======================================================================
85 //function : BRepFill_TrimEdgeTool
87 //=======================================================================
89 BRepFill_TrimEdgeTool::BRepFill_TrimEdgeTool()
94 //=======================================================================
95 //function : BRepFill_TrimEdgeTool
97 //=======================================================================
99 BRepFill_TrimEdgeTool::BRepFill_TrimEdgeTool
100 (const Bisector_Bisec& Bisec,
101 const Handle(Geom2d_Geometry)& S1,
102 const Handle(Geom2d_Geometry)& S2,
103 const Standard_Real Offset) :
107 isPoint1 = (S1->DynamicType() == STANDARD_TYPE(Geom2d_CartesianPoint));
108 isPoint2 = (S2->DynamicType() == STANDARD_TYPE(Geom2d_CartesianPoint));
110 // return geometries of shapes.
111 // Standard_Real f,l;
113 myP1 = Handle(Geom2d_Point)::DownCast(S1)->Pnt2d();
116 myC1 = Handle(Geom2d_Curve)::DownCast(S1);
120 char* myC1name = "myC1";
121 DrawTrSurf::Set(myC1name,myC1);
122 // DrawTrSurf::Set("myC1",myC1);
127 myP2 = Handle(Geom2d_Point)::DownCast(S2)->Pnt2d();
130 myC2 = Handle(Geom2d_Curve)::DownCast(S2);
133 char* myC2name = "myC2";
134 DrawTrSurf::Set(myC2name,myC2);
135 // DrawTrSurf::Set("myC2",myC2);
139 // return the simple expression of the bissectrice
140 Handle(Geom2d_Curve) Bis;
141 SimpleExpression(myBisec, Bis);
142 myBis = Geom2dAdaptor_Curve(Bis);
145 char* myBisname = "myBis";
146 DrawTrSurf::Set(myBisname,Bis);
152 //=======================================================================
154 //purpose : Order the sequence of points by increasing x.
155 //=======================================================================
157 static void Bubble(TColgp_SequenceOfPnt& Seq)
159 Standard_Boolean Invert = Standard_True;
160 Standard_Integer NbPoints = Seq.Length();
162 Invert = Standard_False;
163 for ( Standard_Integer i = 1; i < NbPoints; i++) {
164 gp_Pnt P1 = Seq.Value(i);
165 gp_Pnt P2 = Seq.Value(i+1);
168 Invert = Standard_True;
175 //=======================================================================
176 //function : EvalParameters
178 //=======================================================================
180 static void EvalParameters(const Geom2dAdaptor_Curve& Bis,
181 const Geom2dAdaptor_Curve& AC,
182 TColgp_SequenceOfPnt& Params)
184 Geom2dInt_GInter Intersector;
185 Standard_Real Tol = Precision::Confusion();
186 // Standard_Real TolC = 1.e-9;
188 Geom2dAdaptor_Curve CBis(Bis);
189 Geom2dAdaptor_Curve CAC (AC);
191 //Intersector = Geom2dInt_GInter(CBis, CAC, TolC, Tol);
192 Intersector = Geom2dInt_GInter(CAC, CBis, Tol, Tol);
194 Standard_Integer NbPoints, NbSegments;
195 Standard_Real U1, U2;
198 if ( !Intersector.IsDone()) {
199 StdFail_NotDone::Raise("BRepFill_TrimSurfaceTool::IntersectWith");
202 NbPoints = Intersector.NbPoints();
205 for ( Standard_Integer i = 1; i <= NbPoints; i++) {
206 U1 = Intersector.Point(i).ParamOnSecond();
207 U2 = Intersector.Point(i).ParamOnFirst();
208 P = gp_Pnt(U1,U2,0.);
214 NbSegments = Intersector.NbSegments();
216 if (NbSegments > 0) {
217 IntRes2d_IntersectionSegment Seg;
218 for ( Standard_Integer i = 1; i <= NbSegments; i++) {
219 Seg = Intersector.Segment(i);
220 U1 = Seg.FirstPoint().ParamOnSecond();
221 Standard_Real Ulast = Seg.LastPoint().ParamOnSecond();
222 if ( Abs(U1 - CBis.FirstParameter()) <= Tol &&
223 Abs(Ulast - CBis.LastParameter()) <= Tol ) {
224 P = gp_Pnt(U1,Seg.FirstPoint().ParamOnFirst(),0.);
226 P = gp_Pnt(Ulast,Seg.LastPoint().ParamOnFirst(),0.);
230 U1 += Seg.LastPoint().ParamOnSecond();
232 U2 = Seg.FirstPoint().ParamOnFirst();
233 U2 += Seg.LastPoint().ParamOnFirst();
235 P = gp_Pnt(U1,U2,0.);
241 // Order the sequence by growing parameter on the bissectrice.
245 static void EvalParametersBis(const Geom2dAdaptor_Curve& Bis,
246 const Geom2dAdaptor_Curve& AC,
247 TColgp_SequenceOfPnt& Params,
248 const Standard_Real Tol)
250 Geom2dInt_GInter Intersector;
251 Standard_Real TolC = Tol;
253 Geom2dAdaptor_Curve CBis(Bis);
254 Geom2dAdaptor_Curve CAC (AC);
256 Intersector = Geom2dInt_GInter(CAC, CBis, TolC, Tol);
258 Standard_Integer NbPoints, NbSegments;
259 Standard_Real U1, U2;
262 if ( !Intersector.IsDone()) {
263 StdFail_NotDone::Raise("BRepFill_TrimSurfaceTool::IntersectWith");
266 NbPoints = Intersector.NbPoints();
269 for ( Standard_Integer i = 1; i <= NbPoints; i++) {
270 U1 = Intersector.Point(i).ParamOnSecond();
271 U2 = Intersector.Point(i).ParamOnFirst();
272 P = gp_Pnt(U1,U2,0.);
278 NbSegments = Intersector.NbSegments();
280 if (NbSegments > 0) {
281 IntRes2d_IntersectionSegment Seg;
282 for ( Standard_Integer i = 1; i <= NbSegments; i++) {
283 Seg = Intersector.Segment(i);
284 U1 = Seg.FirstPoint().ParamOnSecond();
285 Standard_Real Ulast = Seg.LastPoint().ParamOnSecond();
286 if ( Abs(U1 - CBis.FirstParameter()) <= Tol &&
287 Abs(Ulast - CBis.LastParameter()) <= Tol ) {
288 P = gp_Pnt(U1,Seg.FirstPoint().ParamOnFirst(),0.);
290 P = gp_Pnt(Ulast,Seg.LastPoint().ParamOnFirst(),0.);
294 U1 += Seg.LastPoint().ParamOnSecond();
296 U2 = Seg.FirstPoint().ParamOnFirst();
297 U2 += Seg.LastPoint().ParamOnFirst();
299 P = gp_Pnt(U1,U2,0.);
305 // Order the sequence by parameter growing on the bissectrice.
310 //=======================================================================
311 //function : IntersectWith
313 //=======================================================================
315 void BRepFill_TrimEdgeTool::IntersectWith(const TopoDS_Edge& Edge1,
316 const TopoDS_Edge& Edge2,
317 const TopoDS_Shape& InitShape1,
318 const TopoDS_Shape& InitShape2,
319 const TopoDS_Vertex& End1,
320 const TopoDS_Vertex& End2,
321 const GeomAbs_JoinType theJoinType,
322 const Standard_Boolean IsOpenResult,
323 TColgp_SequenceOfPnt& Params)
327 // return curves associated to edges.
330 Handle(Geom_Surface) Surf;
332 Handle(Geom2d_Curve) C1;
333 BRep_Tool::CurveOnSurface(Edge1,C1,Surf,L,f,l);
334 Geom2dAdaptor_Curve AC1(C1,f,l);
336 Handle(Geom2d_Curve) C2;
337 BRep_Tool::CurveOnSurface(Edge2,C2,Surf,L,f,l);
338 Geom2dAdaptor_Curve AC2(C2,f,l);
342 f = AC1.FirstParameter();
343 l = AC1.LastParameter();
345 sprintf(name,"C1_%d", ++intind);
346 DrawTrSurf::Set(name, new Geom2d_TrimmedCurve(C1,f,l));
347 f = AC2.FirstParameter();
348 l = AC2.LastParameter();
349 sprintf(name,"C2_%d", intind);
350 DrawTrSurf::Set(name, new Geom2d_TrimmedCurve(C2,f,l));
351 f = myBis.FirstParameter();
352 l = myBis.LastParameter();
353 sprintf(name,"BIS%d", intind);
354 DrawTrSurf::Set(name, new Geom2d_TrimmedCurve(myBis.Curve(),f,l));
355 sprintf(name,"E1_%d", intind);
356 DBRep::Set(name, Edge1);
357 sprintf(name,"E2_%d", intind);
358 DBRep::Set(name, Edge2);
363 // Calculate intersection
364 TColgp_SequenceOfPnt Points2;
367 EvalParameters (myBis,AC1,Params);
368 EvalParameters (myBis,AC2,Points2);
372 Standard_Integer SeanceDeRattrapage=0;
373 Standard_Real TolInit= 1.e-9;
374 Standard_Integer nn = 7;
376 if((AC1.GetType() != GeomAbs_Circle && AC1.GetType() != GeomAbs_Line) ||
377 (AC2.GetType() != GeomAbs_Circle && AC2.GetType() != GeomAbs_Line)) {
383 if(Params.IsEmpty() && Points2.IsEmpty())
385 //Check, may be there are no intersections at all
386 // for case myBis == Line
387 if(myBis.GetType() == GeomAbs_Line)
389 Standard_Real dmax = TolInit;
390 Standard_Integer n = 0;
398 gp_Lin2d anL = myBis.Line();
399 Standard_Boolean isFar1 = Standard_True;
400 Standard_Boolean isFar2 = Standard_True;
403 Standard_Real d = RealLast();
404 AC1.D0(AC1.FirstParameter(), aP);
405 Standard_Real par = ElCLib::Parameter(anL, aP);
406 if(par >= myBis.FirstParameter() && par <= myBis.LastParameter())
408 d = anL.SquareDistance(aP);
410 AC1.D0(AC1.LastParameter(), aP);
411 par = ElCLib::Parameter(anL, aP);
412 if(par >= myBis.FirstParameter() && par <= myBis.LastParameter())
414 d = Min(anL.SquareDistance(aP), d);
419 AC2.D0(AC2.FirstParameter(), aP);
420 par = ElCLib::Parameter(anL, aP);
421 if(par >= myBis.FirstParameter() && par <= myBis.LastParameter())
423 d = anL.SquareDistance(aP);
425 AC2.D0(AC2.LastParameter(), aP);
426 par = ElCLib::Parameter(anL, aP);
427 if(par >= myBis.FirstParameter() && par <= myBis.LastParameter())
429 d = Min(anL.SquareDistance(aP), d);
440 while ( SeanceDeRattrapage < nn // TolInit <= 0.01
441 && ( Points2.Length() != Params.Length() ||
442 (Points2.Length() == 0 && Params.Length() == 0) ) ) {
445 cout << "BRepFill_TrimEdgeTool: incoherent intersection. Try with a greater tolerance" << endl;
453 EvalParametersBis(myBis,AC1,Params,TolInit);
454 EvalParametersBis(myBis,AC2,Points2,TolInit);
455 SeanceDeRattrapage++;
459 if(SeanceDeRattrapage != 0) cout << "SeanceDeRattrapage = " << SeanceDeRattrapage << endl;
460 if(SeanceDeRattrapage == nn) {
461 cout << "BRepFill_TrimEdgeTool: incoherent intersection" << endl;
466 if(Params.Length() == 0 && Points2.Length() == 1) {
468 //cout << "Params.Length() == 0 && Points2.Length() == 1" << endl;
469 Standard_Real dmin, dmax = 0.25*myOffset*myOffset;
470 Standard_Real tBis = Points2(1).X();
471 gp_Pnt2d PBis = myBis.Value(tBis);
473 Standard_Real t = AC1.FirstParameter();
474 gp_Pnt2d PC = AC1.Value(t);
475 dmin = PC.SquareDistance(PBis);
476 gp_Pnt P(tBis, t, 0.);
482 t = AC1.LastParameter();
484 Standard_Real dmin1 = PC.SquareDistance(PBis);
485 if(dmin > dmin1 && dmin1 < dmax ) {
490 Params.SetValue(1,P);
493 else if(Params.Length() == 1 && Points2.Length() == 0) {
495 //cout << "Params.Length() == 1 && Points2.Length() == 0" << endl;
496 Standard_Real dmin, dmax = 0.25*myOffset*myOffset;
497 Standard_Real tBis = Params(1).X();
498 gp_Pnt2d PBis = myBis.Value(tBis);
500 Standard_Real t = AC2.FirstParameter();
501 gp_Pnt2d PC = AC2.Value(t);
502 dmin = PC.SquareDistance(PBis);
503 gp_Pnt P(tBis, t, 0.);
509 t = AC2.LastParameter();
511 Standard_Real dmin1 = PC.SquareDistance(PBis);
512 if(dmin > dmin1 && dmin1 < dmax ) {
514 if(Points2.IsEmpty())
517 Points2.SetValue(1,P);
521 // small manipulation to remove incorrect intersections:
522 // return only common intersections (same parameter
523 // on the bissectrice.).
524 // The tolerance can be eventually changed.
527 Standard_Real Tol = 4 * 100 * Precision::PConfusion();
528 Standard_Integer i = 1;
529 Standard_Integer NbPoints = Params.Length();
531 if(NbPoints == 1 && Points2.Length() == 1) {
532 //cout << "NbPoints == 1 && Points2.Length() == 1" << endl;
533 for ( i = 1; i <= NbPoints; i++) {
535 PSeq.SetZ((Points2.Value(i)).Y());
536 Params.SetValue(i,PSeq);
542 while ( i <= Min( Params.Length(), Points2.Length())) {
545 Standard_Real P1xP2x=Abs( P1.X() - P2.X());
547 if ( P1xP2x > Tol ) {
549 cout << "BRepFill_TrimEdgeTool: no same parameter on the bissectrice" << endl;
553 cout << "BRepFill_TrimEdgeTool: Continue somehow" << endl;
558 if ( P1.X() < P2.X()) Params.Remove(i);
559 else Points2.Remove(i);
565 if ( Params.Length() > Points2.Length()) {
566 Params.Remove(Points2.Length()+1, Params.Length());
568 else if ( Params.Length() < Points2.Length()) {
569 Points2.Remove(Params.Length()+1, Points2.Length());
572 NbPoints = Params.Length();
574 //Now we define: if there are more than one point of intersection
576 Standard_Real init_fpar = RealFirst(), init_lpar = RealLast();
578 theJoinType == GeomAbs_Intersection &&
579 InitShape1.ShapeType() != TopAbs_VERTEX &&
580 InitShape2.ShapeType() != TopAbs_VERTEX)
582 //definition of initial first and last parameters:
583 //this is inverse procedure to extension of parameters
584 //(see BRepFill_OffsetWire, function MakeOffset, case of Circle)
585 const TopoDS_Edge& InitEdge1 = TopoDS::Edge(InitShape1);
586 Standard_Boolean ToExtendFirstPar = Standard_True;
587 Standard_Boolean ToExtendLastPar = Standard_True;
590 TopoDS_Vertex V1, V2;
591 TopExp::Vertices(InitEdge1, V1, V2);
592 if (V1.IsSame(End1) ||
594 ToExtendFirstPar = Standard_False;
595 if (V2.IsSame(End1) ||
597 ToExtendLastPar = Standard_False;
599 BRepAdaptor_Curve IC1(InitEdge1);
600 if (IC1.GetType() == GeomAbs_Circle)
602 Standard_Real Delta = 2*M_PI - IC1.LastParameter() + IC1.FirstParameter();
603 if (ToExtendFirstPar && ToExtendLastPar)
604 init_fpar = AC1.FirstParameter() + Delta/2;
605 else if (ToExtendFirstPar)
606 init_fpar = AC1.FirstParameter() + Delta;
607 else if (ToExtendLastPar)
608 init_fpar = AC1.FirstParameter();
609 init_lpar = init_fpar + IC1.LastParameter() - IC1.FirstParameter();
614 if (NbPoints > 1 && theJoinType == GeomAbs_Intersection)
616 //Remove all vertices with non-minimal parameter
617 //if they are out of initial range
618 Standard_Integer imin = 1;
619 for (i = 2; i <= NbPoints; i++)
620 if (Params(i).X() < Params(imin).X())
623 TColgp_SequenceOfPnt ParamsCopy = Params;
624 TColgp_SequenceOfPnt Points2Copy = Points2;
627 for (i = 1; i <= ParamsCopy.Length(); i++)
629 (ParamsCopy(i).Y() >= init_fpar && ParamsCopy(i).Y() <= init_lpar))
631 Params.Append(ParamsCopy(i));
632 Points2.Append(Points2Copy(i));
636 gp_Pnt Pnt1 = Params(imin);
637 gp_Pnt Pnt2 = Points2(imin);
641 Points2.Append(Pnt2);
645 NbPoints = Params.Length();
646 for ( i = 1; i <= NbPoints; i++) {
648 PSeq.SetZ((Points2.Value(i)).Y());
649 Params.SetValue(i,PSeq);
653 //=======================================================================
654 //function : AddOrConfuse
655 //purpose : the first or the last point of the bissectrice is on the
656 // parallel if it was not found in the intersections,
657 // it is projected on parallel lines and added in the parameters
658 //=======================================================================
660 void BRepFill_TrimEdgeTool::AddOrConfuse(const Standard_Boolean Start,
661 const TopoDS_Edge& Edge1,
662 const TopoDS_Edge& Edge2,
663 TColgp_SequenceOfPnt& Params)
666 Standard_Boolean ToProj = Standard_True;
668 Standard_Real Tol = 10*Precision::Confusion();
670 // return curves associated to edges.
673 Handle(Geom_Surface) Surf;
675 Handle(Geom2d_Curve) C1;
676 BRep_Tool::CurveOnSurface(Edge1,C1,Surf,L,f,l);
677 Geom2dAdaptor_Curve AC1(C1,f,l);
680 if (Start) PBis = myBis.Value(myBis.FirstParameter());
681 else PBis = myBis.Value(myBis.LastParameter ());
683 // Test if the end of the bissectrice is in the set of intersection points.
684 if (!Params.IsEmpty()) {
686 if (Start) P = AC1.Value(Params.First().Y());
687 else P = AC1.Value(Params.Last ().Y());
688 ToProj = !PBis.IsEqual(P,Tol);
693 cout << " project extremity bissectrice on parallel."<<endl;
696 // Project point on parallels and add in Params
699 Handle(Geom2d_Curve) C2;
700 BRep_Tool::CurveOnSurface(Edge2,C2,Surf,L,f2,l2);
702 Geom2dAPI_ProjectPointOnCurve Projector1(PBis,C1,f,l);
703 Geom2dAPI_ProjectPointOnCurve Projector2(PBis,C2,f2,l2);
705 if (Projector1.NbPoints() == 0) {
707 cout << "Failed projection in BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
711 if (!Projector1.NearestPoint().IsEqual(PBis,Tol)) {
713 cout <<"Incorrect solution in BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
717 if (Projector2.NbPoints() == 0) {
719 cout << "Failed projection in BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
723 if (!Projector2.NearestPoint().IsEqual(PBis,Tol)) {
725 cout <<" Mauvaisesolution dans BRepFill_TrimEdgeTool::AddOrConfuse"<<endl;
730 Projector1.LowerDistanceParameter(),
731 Projector2.LowerDistanceParameter());
733 PInt.SetX (myBis.FirstParameter());
734 Params.Prepend(PInt);
737 PInt.SetX (myBis.LastParameter());
743 //=======================================================================
744 //function : IsInside
746 //=======================================================================
748 Standard_Boolean BRepFill_TrimEdgeTool::IsInside(const gp_Pnt2d& P) const
750 // Modified by Sergey KHROMOV - Fri Sep 27 11:43:12 2002 Begin
751 // Standard_Real Dist;
752 Standard_Real Dist = RealLast();
753 // Modified by Sergey KHROMOV - Fri Sep 27 11:43:12 2002 End
755 Dist = P.Distance(myP1);
757 Dist = P.Distance(myP2);
759 Geom2dAPI_ProjectPointOnCurve Projector(P,myC1);
760 if (Projector.NbPoints() > 0) {
761 Dist = Projector.LowerDistance();
763 // Modified by Sergey KHROMOV - Fri Sep 27 11:43:43 2002 Begin
765 // gp_Pnt2d PF = myC1->Value(myC1->FirstParameter());
766 // gp_Pnt2d PL = myC1->Value(myC1->LastParameter());
767 // Dist = Min (P.Distance(PF),P.Distance(PL));
770 // Check of distances between P and first and last point of the first curve
771 // should be performed in any case, despite of the results of projection.
772 gp_Pnt2d PF = myC1->Value(myC1->FirstParameter());
773 gp_Pnt2d PL = myC1->Value(myC1->LastParameter());
774 Standard_Real aDistMin = Min (P.Distance(PF),P.Distance(PL));
778 // Modified by Sergey KHROMOV - Fri Sep 27 11:43:44 2002 End
781 // return (Dist < Abs(myOffset);
782 // return (Dist < Abs(myOffset) + Precision::Confusion());
783 return (Dist < Abs(myOffset) - Precision::Confusion());