2e15ce035198778275a66d7262fc0affd383f5d6
[occt.git] / src / IntPatch / IntPatch_PolyLine.cxx
1 // File:      IntPatch_PolyLine.cxx
2 // Created:   Fri Jan 29 17:14:59 1993
3 // Author:    Isabelle GRIGNON
4 // Copyright: Matra Datavision 1993
5
6 //-- lbr le 12 juin : Ajout des fleches sur les Lines
7 //-- msv 13.03.2002 : compute deflection for WLine; Error() returns deflection
8
9 #include <IntPatch_PolyLine.ixx>
10
11 #include <Precision.hxx>
12
13 #define INITDEFLE Precision::PConfusion()*100.
14
15 //=======================================================================
16 //function : IntPatch_PolyLine
17 //purpose  : 
18 //=======================================================================
19
20 IntPatch_PolyLine::IntPatch_PolyLine ()
21      : defle(INITDEFLE)
22 {}
23
24 //=======================================================================
25 //function : IntPatch_PolyLine
26 //purpose  : 
27 //=======================================================================
28
29 IntPatch_PolyLine::IntPatch_PolyLine (const Standard_Real InitDefle)
30      : defle(InitDefle)
31 {}
32
33 //=======================================================================
34 //function : SetWLine
35 //purpose  : 
36 //=======================================================================
37
38 void IntPatch_PolyLine::SetWLine(const Standard_Boolean OnFirst, const Handle(IntPatch_WLine)& Line)
39 {
40   typ = IntPatch_Walking;
41   wpoly = Line;
42   onfirst = OnFirst;
43   Prepare();
44 }
45
46 //=======================================================================
47 //function : SetRLine
48 //purpose  : 
49 //=======================================================================
50
51 void IntPatch_PolyLine::SetRLine(const Standard_Boolean OnFirst, const Handle(IntPatch_RLine)& Line)
52 {
53   typ = IntPatch_Restriction;
54   rpoly = Line;
55   onfirst = OnFirst;
56   Prepare();
57 }
58
59 //=======================================================================
60 //function : Prepare
61 //purpose  : 
62 //=======================================================================
63
64 void IntPatch_PolyLine::Prepare()
65 {
66   Standard_Integer i;
67   box.SetVoid();
68   Standard_Integer n=NbPoints();
69   Standard_Real eps = defle;
70
71   gp_Pnt2d P1, P2;
72   if (n >= 3) {
73     P1 = Point(1); P2 = Point(2);
74   }
75   for (i=1; i<=n ;i++) {
76     const gp_Pnt2d& P3 = Point(i);
77     if (i >= 3) {
78       gp_XY V13 = P3.XY() - P1.XY();
79       gp_XY V12 = P2.XY() - P1.XY();
80       Standard_Real d13 = V13.Modulus(), d;
81       if (d13 > eps)
82         d = V13.CrossMagnitude(V12) / d13;
83       else
84         d = eps;
85       if (d > defle) {
86         // try to compute deflection more precisely using parabola interpolation
87         gp_XY V23 = P3.XY() - P2.XY();
88         Standard_Real d12 = V12.Modulus(), d23 = V23.Modulus();
89         // compute parameter of P2 (assume parameters of P1,P3 are 0,1)
90         Standard_Real tm = d12 / (d12+d23);
91         if (tm > 0.1 && tm < 0.9) {
92           tm -= (tm-0.5) * 0.6;
93           Standard_Real tm1mtm = tm*(1-tm);
94           // coefficients of parabola
95           Standard_Real Ax = (tm*V13.X() - V12.X()) / tm1mtm;
96           Standard_Real Bx = (V12.X() - tm*tm*V13.X()) / tm1mtm;
97           Standard_Real Cx = P1.X();
98           Standard_Real Ay = (tm*V13.Y() - V12.Y()) / tm1mtm;
99           Standard_Real By = (V12.Y() - tm*tm*V13.Y()) / tm1mtm;
100           Standard_Real Cy = P1.Y();
101           // equations of lines P1-P2 and P2-P3
102           Standard_Real A1 = V12.Y() / d12;
103           Standard_Real B1 = -V12.X() / d12;
104           Standard_Real C1 = (P2.X()*P1.Y() - P1.X()*P2.Y()) / d12;
105           Standard_Real A2 = V23.Y() / d23;
106           Standard_Real B2 = -V23.X() / d23;
107           Standard_Real C2 = (P3.X()*P2.Y() - P2.X()*P3.Y()) / d23;
108           // points on parabola with max deflection
109           Standard_Real t1 = -0.5 * (A1*Bx + B1*By) / (A1*Ax + B1*Ay);
110           Standard_Real t2 = -0.5 * (A2*Bx + B2*By) / (A2*Ax + B2*Ay);
111           Standard_Real xt1 = Ax*t1*t1 + Bx*t1 + Cx;
112           Standard_Real yt1 = Ay*t1*t1 + By*t1 + Cy;
113           Standard_Real xt2 = Ax*t2*t2 + Bx*t2 + Cx;
114           Standard_Real yt2 = Ay*t2*t2 + By*t2 + Cy;
115           // max deflection on segments P1-P2 and P2-P3
116           Standard_Real d1 = Abs (A1*xt1 + B1*yt1 + C1);
117           Standard_Real d2 = Abs (A2*xt2 + B2*yt2 + C2);
118           if (d2 > d1) d1 = d2;
119           // select min deflection from linear and parabolic ones
120           if (d1 < d) d = d1;
121         }
122         if (d > defle) defle=d;
123       }
124       P1 = P2; P2 = P3;
125     }
126     box.Add(P3);
127   }
128   box.Enlarge(defle);  
129 }
130
131 //=======================================================================
132 //function : ResetError
133 //purpose  : 
134 //=======================================================================
135
136 void IntPatch_PolyLine::ResetError()
137 {
138   defle = INITDEFLE;
139 }
140
141 //=======================================================================
142 //function : Bounding
143 //purpose  : 
144 //=======================================================================
145
146 const Bnd_Box2d& IntPatch_PolyLine::Bounding() const 
147 {
148   return box;
149 }
150
151 //=======================================================================
152 //function : Error
153 //purpose  : 
154 //=======================================================================
155
156 Standard_Real IntPatch_PolyLine::Error() const
157 {
158   // return 0.0000001;
159   return defle;
160 }
161
162 //=======================================================================
163 //function : Closed
164 //purpose  : 
165 //=======================================================================
166
167 Standard_Boolean IntPatch_PolyLine::Closed() const
168 {
169   return Standard_False;
170 }
171
172 //=======================================================================
173 //function : NbPoints
174 //purpose  : 
175 //=======================================================================
176
177 Standard_Integer IntPatch_PolyLine::NbPoints() const
178 {
179   return (typ == IntPatch_Walking ? wpoly->NbPnts() : rpoly->NbPnts());
180 }
181
182 //=======================================================================
183 //function : Point
184 //purpose  : 
185 //=======================================================================
186
187 gp_Pnt2d IntPatch_PolyLine::Point(const Standard_Integer Index )  const 
188
189   Standard_Real X,Y,X1,Y1,DX,DY;
190   DX=DY=0;
191   if (onfirst) {
192     if (typ == IntPatch_Walking) {
193       wpoly->Point(Index).ParametersOnS1(X,Y);
194       if(Index==1) { 
195         wpoly->Point(2).ParametersOnS1(X1,Y1);
196         DX=0.0000001*(X-X1);
197         DY=0.0000001*(Y-Y1);    
198       }
199       else if(Index==wpoly->NbPnts()) { 
200         wpoly->Point(Index-1).ParametersOnS1(X1,Y1);
201         DX=0.0000001*(X-X1);
202         DY=0.0000001*(Y-Y1);    
203       }
204     }
205     else {
206       rpoly->Point(Index).ParametersOnS1(X,Y);
207     }
208   }
209   else {
210     if (typ == IntPatch_Walking) {
211       wpoly->Point(Index).ParametersOnS2(X,Y);
212       if(Index==1) { 
213         wpoly->Point(2).ParametersOnS2(X1,Y1);
214         DX=0.0000001*(X-X1);
215         DY=0.0000001*(Y-Y1);    
216       }
217       else if(Index==wpoly->NbPnts()) { 
218         wpoly->Point(Index-1).ParametersOnS2(X1,Y1);
219         DX=0.0000001*(X-X1);
220         DY=0.0000001*(Y-Y1);    
221       }
222     }
223     else {
224       rpoly->Point(Index).ParametersOnS2(X,Y);
225     }
226   }
227
228   return(gp_Pnt2d(X+DX,Y+DY));
229 }