b311480e |
1 | // Created on: 1993-01-27 |
2 | // Created by: Isabelle GRIGNON |
3 | // Copyright (c) 1993-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
7fd59977 |
17 | |
42cf5bc1 |
18 | #include <Adaptor2d_HCurve2d.hxx> |
19 | #include <Bnd_Box2d.hxx> |
20 | #include <gp_Pnt2d.hxx> |
21 | #include <IntPatch_PolyArc.hxx> |
7fd59977 |
22 | #include <Standard_ConstructionError.hxx> |
23 | |
24 | inline void MinMax (const Standard_Real a1, const Standard_Real a2, |
25 | Standard_Real& amin, Standard_Real& amax) |
26 | { |
27 | if (a1 < a2) { |
28 | amin = a1; amax = a2; |
29 | } |
30 | else { |
31 | amin = a2; amax = a1; |
32 | } |
33 | } |
34 | |
35 | IntPatch_PolyArc::IntPatch_PolyArc(const Handle(Adaptor2d_HCurve2d)& Line , |
36 | const Standard_Integer NbSample, |
37 | const Standard_Real aPdeb, |
38 | const Standard_Real aPfin, |
39 | const Bnd_Box2d& BoxOtherPolygon): |
40 | brise(1,Max(1,NbSample)), |
41 | param(1,Max(1,NbSample)), |
42 | offsetx(0.0), |
43 | offsety(0.0) |
44 | { |
45 | Standard_Real Pdeb = aPdeb; |
46 | Standard_Real Pfin = aPfin; |
47 | gp_Pnt2d p2d; |
48 | |
49 | if (Pdeb == RealFirst() || Pfin == RealLast() || NbSample <= 1) { |
9775fa61 |
50 | throw Standard_ConstructionError(); |
7fd59977 |
51 | } |
52 | //---------------------------------------------------------------------- |
53 | //-- On veut eviter les cas ou le present polygone est beaucoup plus |
54 | //-- grand que l objet en second. |
55 | //-- |
56 | //-- Par exemple lorsque l objet en second est une ligne de cheminement |
57 | //-- qui contient de nombreux segments (>>100), une fleche nulle |
58 | //-- et ce polygone quelques segments et une fleche qui contient |
59 | //-- toute la ligne de cheminement. |
60 | //-- |
61 | //-- Dans ce cas (tout un polygone compris dans la zone d influence) |
62 | //-- les calculs deviennent tres longs (N2) |
63 | //---------------------------------------------------------------------- |
64 | Standard_Integer IndexInf = NbSample+1; |
65 | Standard_Integer IndexSup = 0; |
66 | |
67 | Standard_Real bx0,by0,bxmin,bxmax,bymin,bymax,r,r2; |
68 | |
69 | BoxOtherPolygon.Get(bxmin,bymin,bxmax,bymax); |
70 | r=(bxmax-bxmin)+(bymax-bymin); |
71 | bx0=(bxmax+bxmin)*0.5; |
72 | by0=(bymax+bymin)*0.5; |
73 | |
74 | Standard_Real Pas; |
75 | Standard_Real X,Y,Xs,Ys,Xm,Ym,XXs,YYs; |
76 | |
77 | r*=0.8; |
78 | r2 = r*r*49.; |
79 | Standard_Integer nbloop=0; |
80 | |
81 | do { |
82 | nbloop++; |
83 | Pas = (Pfin-Pdeb)/(NbSample-1); |
84 | param(1) = Pdeb; |
85 | Line->D0(Pdeb,p2d); |
86 | Xs = p2d.X(); Ys = p2d.Y(); |
87 | brise(1).SetCoord(Xs,Ys); |
88 | |
9530af27 |
89 | myBox.SetVoid(); |
7fd59977 |
90 | |
9530af27 |
91 | myBox.Add(brise(1)); |
92 | myError =0.; |
7fd59977 |
93 | |
94 | for (Standard_Integer i =2; i<=NbSample;i++) { |
95 | param(i) = Pdeb + (i-1)*Pas; |
96 | Line->D0(param(i),p2d); |
97 | X = p2d.X(); Y = p2d.Y(); |
98 | brise(i).SetCoord(X,Y); |
99 | XXs = 0.5*(Xs+X); |
100 | YYs = 0.5*(Ys+Y); |
101 | //------------------------------------------------------------ |
102 | //-- On recherche le debut et la fin de la zone significative |
103 | //------------------------------------------------------------ |
104 | // MSV: (see cda 002 H2) if segment is too large (>>r) we have |
105 | // a risk to jump through BoxOtherPolygon, therefore we should |
106 | // check this condition if the first one is failure. |
107 | Standard_Boolean isMidPtInBox = (Abs(bx0-XXs) + Abs(by0-YYs)) < r; |
108 | Standard_Boolean isSegOut = Standard_True; |
109 | if(!isMidPtInBox) { |
110 | Standard_Real d = (X-Xs)*(X-Xs)+(Y-Ys)*(Y-Ys); |
111 | if (d > r2) { |
112 | Standard_Real xmin,xmax,ymin,ymax; |
113 | MinMax (Xs,X, xmin,xmax); |
114 | MinMax (Ys,Y, ymin,ymax); |
115 | isSegOut = (xmax < bxmin || xmin > bxmax || |
116 | ymax < bymin || ymin > bymax); |
117 | } |
118 | } |
119 | if(isMidPtInBox || !isSegOut) { |
120 | // MSV: take the previous and the next segments too, because of |
121 | // we check only the middle point (see BUC60946) |
122 | //if(IndexInf>i) IndexInf=i-1; |
123 | //if(IndexSup<i) IndexSup=i; |
124 | if(IndexInf>i) IndexInf=Max(i-2,1); |
125 | if(IndexSup<i) IndexSup=Min(i+1,NbSample); |
126 | } |
127 | |
9530af27 |
128 | myBox.Add(brise(i)); |
7fd59977 |
129 | Line->D0(param(i)-Pas*0.5,p2d); |
130 | Xm = p2d.X() - XXs; |
131 | Ym = p2d.Y() - YYs; |
132 | Xm = Sqrt(Xm*Xm+Ym*Ym); |
9530af27 |
133 | myError =Max (myError , Xm); |
7fd59977 |
134 | Xs = X; |
135 | Ys = Y; |
136 | } |
137 | if(IndexInf > IndexSup) { |
138 | r+=r; |
139 | r2 = r*r*49.; |
140 | //-- cout<<" Le rayon : "<<r<<" est insuffisant "<<endl; |
141 | } |
142 | else { |
143 | //---------------------------------------------- |
144 | //-- Si le nombre de points significatifs est |
145 | //-- insuffisant, on reechantillonne une fois |
146 | //-- encore |
147 | //---------------------------------------------- |
148 | if((IndexSup-IndexInf)<(NbSample/2)) { |
149 | //-- cout<<" --- On remet ca entre les index "<<IndexInf<<" et "<<IndexSup<<endl; |
150 | nbloop = 10; |
151 | //if(IndexInf>1) IndexInf--; |
152 | //if(IndexSup<NbSample) IndexSup++; |
153 | Pdeb = param(IndexInf); |
154 | Pfin = param(IndexSup); |
155 | //IndexInf = IndexSup+1; |
156 | IndexInf = NbSample+1; |
157 | IndexSup = 0; |
158 | } |
159 | } |
160 | } |
161 | while((IndexInf > IndexSup) && nbloop<=10); |
9530af27 |
162 | myError*=1.2; |
163 | if(myError<0.00000001) |
164 | myError = 0.00000001; |
165 | myBox.Enlarge(myError); |
7fd59977 |
166 | |
9530af27 |
167 | ferme = (Line->Value(aPdeb).Distance(Line->Value(aPfin)) <= 1e-7); |
7fd59977 |
168 | } |
169 | |
7fd59977 |
170 | Standard_Boolean IntPatch_PolyArc::Closed() const { return ferme;} |
171 | |
172 | Standard_Integer IntPatch_PolyArc::NbPoints() const {return brise.Length();} |
173 | |
174 | gp_Pnt2d IntPatch_PolyArc::Point(const Standard_Integer Index ) const |
175 | { |
176 | if(offsetx == 0.0 && offsety==0.0) |
177 | return(brise(Index)); |
178 | |
179 | const gp_Pnt2d& P = brise(Index); |
180 | return (gp_Pnt2d(P.X()+offsetx,P.Y()+offsety)); |
181 | } |
182 | |
183 | Standard_Real IntPatch_PolyArc::Parameter(const Standard_Integer Index ) const |
184 | { return param(Index);} |
185 | |
186 | |
187 | void IntPatch_PolyArc::SetOffset(const Standard_Real ox,const Standard_Real oy) { |
188 | Standard_Real xmin,ymin,xmax,ymax,g; |
9530af27 |
189 | myBox.Get(xmin,ymin,xmax,ymax); |
190 | g = myBox.GetGap(); |
7fd59977 |
191 | |
9530af27 |
192 | myBox.SetVoid(); |
7fd59977 |
193 | |
9530af27 |
194 | myBox.Update(xmin-offsetx,ymin-offsety, |
7fd59977 |
195 | xmax-offsetx,ymax-offsety); |
196 | offsetx = ox; |
197 | offsety = oy; |
9530af27 |
198 | myBox.Update(xmin+offsetx,ymin+offsety, |
7fd59977 |
199 | xmax+offsetx,ymax+offsety); |
9530af27 |
200 | myBox.SetGap(g); |
7fd59977 |
201 | } |