b311480e |
1 | // Created on: 1995-02-07 |
2 | // Created by: Jacques GOUSSARD |
3 | // Copyright (c) 1995-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 | |
94783b51 |
17 | #include <algorithm> |
7fd59977 |
18 | |
42cf5bc1 |
19 | #include <Adaptor2d_HCurve2d.hxx> |
20 | #include <Adaptor3d_TopolTool.hxx> |
21 | #include <ElCLib.hxx> |
22 | #include <GeomAbs_SurfaceType.hxx> |
23 | #include <GeomAdaptor_HSurface.hxx> |
24 | #include <GeomInt.hxx> |
25 | #include <GeomInt_LineConstructor.hxx> |
7fd59977 |
26 | #include <GeomInt_LineTool.hxx> |
7fd59977 |
27 | #include <GeomInt_ParameterAndOrientation.hxx> |
42cf5bc1 |
28 | #include <GeomInt_SequenceOfParameterAndOrientation.hxx> |
29 | #include <gp_Pnt2d.hxx> |
30 | #include <IntPatch_ALine.hxx> |
7fd59977 |
31 | #include <IntPatch_GLine.hxx> |
42cf5bc1 |
32 | #include <IntPatch_Line.hxx> |
33 | #include <IntPatch_Point.hxx> |
7fd59977 |
34 | #include <IntPatch_WLine.hxx> |
42cf5bc1 |
35 | #include <IntSurf_PntOn2S.hxx> |
36 | #include <IntSurf_Quadric.hxx> |
7fd59977 |
37 | #include <IntSurf_Transition.hxx> |
7fd59977 |
38 | #include <Precision.hxx> |
7fd59977 |
39 | #include <Standard_ConstructionError.hxx> |
42cf5bc1 |
40 | #include <Standard_OutOfRange.hxx> |
41 | #include <StdFail_NotDone.hxx> |
2a78ec6a |
42 | #include <TColStd_IndexedMapOfInteger.hxx> |
42cf5bc1 |
43 | #include <TopAbs_Orientation.hxx> |
2a78ec6a |
44 | |
94783b51 |
45 | static const Standard_Real TwoPI = M_PI + M_PI; |
46 | |
7fd59977 |
47 | //======================================================================= |
94783b51 |
48 | //class : GeomInt_Vertex |
49 | //purpose : This class has been created in order to provide possibility |
50 | // to sort IntPatch_Points by their parameter on line. |
7fd59977 |
51 | //======================================================================= |
94783b51 |
52 | class GeomInt_Vertex |
53 | { |
54 | public: |
55 | GeomInt_Vertex() |
7fd59977 |
56 | { |
2a78ec6a |
57 | }; |
94783b51 |
58 | |
59 | //! Initializes this class by IntPatch_Point |
60 | void SetVertex(const IntPatch_Point& theOther) |
61 | { |
62 | myVertex = theOther; |
63 | const Standard_Real aNewParam = ElCLib::InPeriod(theOther.ParameterOnLine(), 0.0, TwoPI); |
64 | SetParameter(aNewParam); |
7fd59977 |
65 | } |
94783b51 |
66 | |
67 | //! Sets Parameter on Line |
68 | void SetParameter(const Standard_Real theParam) |
69 | { |
70 | myVertex.SetParameter(theParam); |
7fd59977 |
71 | } |
94783b51 |
72 | |
73 | //! Returns IntPatch_Point |
74 | const IntPatch_Point& Getvertex() const |
75 | { |
76 | return myVertex; |
7fd59977 |
77 | } |
94783b51 |
78 | |
79 | //! To provide sort |
80 | Standard_Boolean operator < (const GeomInt_Vertex& theOther) const |
81 | { |
82 | return myVertex.ParameterOnLine() < theOther.myVertex.ParameterOnLine(); |
83 | } |
84 | |
85 | private: |
86 | IntPatch_Point myVertex; |
2a78ec6a |
87 | }; |
94783b51 |
88 | |
2a78ec6a |
89 | //------------ |
94783b51 |
90 | static void Parameters(const Handle(GeomAdaptor_HSurface)& myHS1, |
91 | const gp_Pnt& Ptref, |
92 | Standard_Real& U1, |
93 | Standard_Real& V1); |
94 | |
95 | static void Parameters(const Handle(GeomAdaptor_HSurface)& myHS1, |
96 | const Handle(GeomAdaptor_HSurface)& myHS2, |
97 | const gp_Pnt& Ptref, |
98 | Standard_Real& U1, |
99 | Standard_Real& V1, |
100 | Standard_Real& U2, |
101 | Standard_Real& V2); |
102 | |
103 | static void GLinePoint(const IntPatch_IType typl, |
104 | const Handle(IntPatch_GLine)& GLine, |
105 | const Standard_Real aT, |
106 | gp_Pnt& aP); |
107 | |
108 | static void AdjustPeriodic(const Handle(GeomAdaptor_HSurface)& myHS1, |
109 | const Handle(GeomAdaptor_HSurface)& myHS2, |
110 | Standard_Real& u1, |
111 | Standard_Real& v1, |
112 | Standard_Real& u2, |
113 | Standard_Real& v2); |
2a78ec6a |
114 | |
115 | static |
116 | Standard_Boolean RejectMicroCircle(const Handle(IntPatch_GLine)& aGLine, |
117 | const IntPatch_IType aType, |
118 | const Standard_Real aTol3D); |
7fd59977 |
119 | |
94783b51 |
120 | static void RejectDuplicates(NCollection_Array1<GeomInt_Vertex>& theVtxArr); |
121 | |
7fd59977 |
122 | //======================================================================= |
123 | //function : Perform |
124 | //purpose : |
125 | //======================================================================= |
126 | void GeomInt_LineConstructor::Perform(const Handle(IntPatch_Line)& L) |
127 | { |
128 | Standard_Integer i,nbvtx; |
129 | Standard_Real firstp,lastp; |
130 | const Standard_Real Tol = Precision::PConfusion() * 35.0; |
131 | |
132 | const IntPatch_IType typl = L->ArcType(); |
2a78ec6a |
133 | if(typl == IntPatch_Analytic) { |
7fd59977 |
134 | Standard_Real u1,v1,u2,v2; |
a1eb3afd |
135 | Handle(IntPatch_ALine) ALine (Handle(IntPatch_ALine)::DownCast (L)); |
7fd59977 |
136 | seqp.Clear(); |
137 | nbvtx = GeomInt_LineTool::NbVertex(L); |
2a78ec6a |
138 | for(i=1;i<nbvtx;i++) { |
7fd59977 |
139 | firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine(); |
140 | lastp = GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine(); |
2a78ec6a |
141 | if(firstp!=lastp) { |
142 | const Standard_Real pmid = (firstp+lastp)*0.5; |
143 | const gp_Pnt Pmid = ALine->Value(pmid); |
7fd59977 |
144 | Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2); |
94783b51 |
145 | AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2); |
7fd59977 |
146 | const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol); |
2a78ec6a |
147 | if(in1 != TopAbs_OUT) { |
7fd59977 |
148 | const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol); |
149 | if(in2 != TopAbs_OUT) { |
150 | seqp.Append(firstp); |
151 | seqp.Append(lastp); |
152 | } |
153 | } |
154 | } |
155 | } |
156 | done = Standard_True; |
157 | return; |
2a78ec6a |
158 | } // if(typl == IntPatch_Analytic) { |
159 | else if(typl == IntPatch_Walking) { |
7fd59977 |
160 | Standard_Real u1,v1,u2,v2; |
a1eb3afd |
161 | Handle(IntPatch_WLine) WLine (Handle(IntPatch_WLine)::DownCast (L)); |
7fd59977 |
162 | seqp.Clear(); |
163 | nbvtx = GeomInt_LineTool::NbVertex(L); |
2a78ec6a |
164 | for(i=1;i<nbvtx;i++) { |
7fd59977 |
165 | firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine(); |
166 | lastp = GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine(); |
98974dcc |
167 | if(firstp!=lastp) |
168 | { |
169 | if (lastp != firstp + 1) |
170 | { |
171 | const Standard_Integer pmid = (Standard_Integer) ((firstp + lastp) / 2); |
2a78ec6a |
172 | const IntSurf_PntOn2S& Pmid = WLine->Point(pmid); |
173 | Pmid.Parameters(u1,v1,u2,v2); |
94783b51 |
174 | AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2); |
98974dcc |
175 | const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1, v1), Tol); |
176 | if (in1 != TopAbs_OUT) |
177 | { |
178 | const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2, v2), Tol); |
179 | if (in2 != TopAbs_OUT) |
180 | { |
2a78ec6a |
181 | seqp.Append(firstp); |
182 | seqp.Append(lastp); |
183 | } |
184 | } |
00302ba4 |
185 | } |
98974dcc |
186 | else |
187 | { |
188 | if (WLine->GetCreatingWay() == IntPatch_WLine::IntPatch_WLImpPrm) |
189 | { |
190 | //The fix #29972. |
191 | //Implicit-Parametric intersector does not respect domain of |
192 | //the quadric surface (it takes into account the domain of the |
193 | //parametric surface only). It means that we cannot warrant that |
194 | //we have a point exactly in the quadric boundary. |
195 | //E.g. in the test cases "bugs modalg_5 bug25697_2", |
196 | //"bugs modalg_5 bug23948", "boolean bopfuse_complex G9", |
197 | //"boolean bopcommon_complex H7", "boolean bopcut_complex I7" etc. |
198 | //the WLine contains 2 points and one is out of the quadric's domain. |
199 | //In order to process these cases correctly, we classify a middle |
200 | //(between these two) point (obtained by interpolation). |
201 | |
202 | //Other types of intersector take into account the domains of both surfaces. |
203 | //So, they require to reject all "outboundaried" parts of WLine. As result, |
204 | //more strict check (all two points of WLine are checksed) is |
205 | //applied in this case. |
206 | |
207 | Standard_Real aU21, aV21, aU22, aV22; |
208 | const IntSurf_PntOn2S& aPfirst = WLine->Point((Standard_Integer) (firstp)); |
209 | const IntSurf_PntOn2S& aPlast = WLine->Point((Standard_Integer) (lastp)); |
210 | aPfirst.Parameters(u1, v1, u2, v2); |
211 | AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2); |
212 | aPlast.Parameters(aU21, aV21, aU22, aV22); |
213 | AdjustPeriodic(myHS1, myHS2, aU21, aV21, aU22, aV22); |
214 | |
215 | u1 = 0.5*(u1 + aU21); |
216 | v1 = 0.5*(v1 + aV21); |
217 | u2 = 0.5*(u2 + aU22); |
218 | v2 = 0.5*(v2 + aV22); |
219 | |
220 | const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1, v1), Tol); |
221 | if (in1 != TopAbs_OUT) |
222 | { |
223 | const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2, v2), Tol); |
224 | if (in2 != TopAbs_OUT) |
225 | { |
226 | seqp.Append(firstp); |
227 | seqp.Append(lastp); |
228 | } |
229 | } |
230 | } |
231 | else |
232 | { |
233 | const IntSurf_PntOn2S& Pfirst = WLine->Point((Standard_Integer) (firstp)); |
234 | Pfirst.Parameters(u1, v1, u2, v2); |
235 | AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2); |
236 | TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1, v1), Tol); |
237 | if (in1 != TopAbs_OUT) |
238 | { |
239 | TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2, v2), Tol); |
240 | if (in2 != TopAbs_OUT) |
241 | { |
242 | const IntSurf_PntOn2S& Plast = WLine->Point((Standard_Integer) (lastp)); |
243 | Plast.Parameters(u1, v1, u2, v2); |
244 | AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2); |
245 | in1 = myDom1->Classify(gp_Pnt2d(u1, v1), Tol); |
246 | if (in1 != TopAbs_OUT) |
247 | { |
248 | in2 = myDom2->Classify(gp_Pnt2d(u2, v2), Tol); |
249 | if (in2 != TopAbs_OUT) |
250 | { |
251 | seqp.Append(firstp); |
252 | seqp.Append(lastp); |
253 | } |
2a78ec6a |
254 | } |
255 | } |
256 | } |
257 | } |
7fd59977 |
258 | } |
2a78ec6a |
259 | } |
260 | } |
261 | // |
262 | // The One resulting curve consists of 7 segments that are |
263 | // connected between each other. |
264 | // The aim of the block is to reject these segments and have |
265 | // one segment instead of 7. |
266 | // The other reason to do that is value of TolReached3D=49. |
267 | // Why -? It is not known yet. |
268 | // PKV 22.Apr.2002 |
269 | // |
270 | Standard_Integer aNbParts; |
271 | // |
272 | aNbParts = seqp.Length()/2; |
273 | if (aNbParts > 1) { |
274 | Standard_Boolean bCond; |
275 | GeomAbs_SurfaceType aST1, aST2; |
276 | aST1 = myHS1->Surface().GetType(); |
277 | aST2 = myHS2->Surface().GetType(); |
278 | // |
279 | bCond=Standard_False; |
280 | if (aST1==GeomAbs_Plane) { |
281 | if (aST2==GeomAbs_SurfaceOfExtrusion || |
282 | aST2==GeomAbs_SurfaceOfRevolution) {//+zft |
283 | bCond=!bCond; |
00302ba4 |
284 | } |
2a78ec6a |
285 | } |
286 | else if (aST2==GeomAbs_Plane) { |
287 | if (aST1==GeomAbs_SurfaceOfExtrusion || |
288 | aST1==GeomAbs_SurfaceOfRevolution) {//+zft |
289 | bCond=!bCond; |
00302ba4 |
290 | } |
7fd59977 |
291 | } |
2a78ec6a |
292 | // |
293 | if (bCond) { |
294 | Standard_Integer aNb, anIndex, aNbTmp, jx; |
295 | TColStd_IndexedMapOfInteger aMap; |
296 | TColStd_SequenceOfReal aSeqTmp; |
297 | // |
298 | aNb=seqp.Length(); |
299 | for(i=1; i<=aNb; ++i) { |
300 | lastp =seqp(i); |
301 | anIndex=(Standard_Integer)lastp; |
302 | if (!aMap.Contains(anIndex)){ |
303 | aMap.Add(anIndex); |
304 | aSeqTmp.Append(lastp); |
305 | } |
306 | else { |
307 | aNbTmp=aSeqTmp.Length(); |
308 | aSeqTmp.Remove(aNbTmp); |
309 | } |
310 | } |
311 | // |
312 | seqp.Clear(); |
313 | // |
314 | aNb=aSeqTmp.Length()/2; |
315 | for(i=1; i<=aNb;++i) { |
316 | jx=2*i; |
317 | firstp=aSeqTmp(jx-1); |
318 | lastp =aSeqTmp(jx); |
319 | seqp.Append(firstp); |
320 | seqp.Append(lastp); |
321 | } |
322 | }//if (bCond) { |
7fd59977 |
323 | } |
324 | done = Standard_True; |
325 | return; |
2a78ec6a |
326 | }// else if(typl == IntPatch_Walking) { |
327 | // |
328 | //----------------------------------------------------------- |
329 | else if (typl != IntPatch_Restriction) { |
7fd59977 |
330 | seqp.Clear(); |
2a78ec6a |
331 | // |
a1eb3afd |
332 | Handle(IntPatch_GLine) GLine (Handle(IntPatch_GLine)::DownCast (L)); |
2a78ec6a |
333 | // |
334 | if(typl == IntPatch_Circle || typl == IntPatch_Ellipse) { |
335 | TreatCircle(L, Tol); |
336 | done=Standard_True; |
337 | return; |
338 | } |
339 | //---------------------------- |
340 | Standard_Boolean intrvtested; |
341 | Standard_Real u1,v1,u2,v2; |
342 | // |
7fd59977 |
343 | nbvtx = GeomInt_LineTool::NbVertex(L); |
2a78ec6a |
344 | intrvtested = Standard_False; |
345 | for(i=1; i<nbvtx; ++i) { |
7fd59977 |
346 | firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine(); |
347 | lastp = GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine(); |
2a78ec6a |
348 | if(Abs(firstp-lastp)>Precision::PConfusion()) { |
7fd59977 |
349 | intrvtested = Standard_True; |
350 | const Standard_Real pmid = (firstp+lastp)*0.5; |
2a78ec6a |
351 | gp_Pnt Pmid; |
352 | GLinePoint(typl, GLine, pmid, Pmid); |
353 | // |
354 | Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2); |
94783b51 |
355 | AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2); |
2a78ec6a |
356 | const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol); |
357 | if(in1 != TopAbs_OUT) { |
358 | const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol); |
359 | if(in2 != TopAbs_OUT) { |
360 | seqp.Append(firstp); |
361 | seqp.Append(lastp); |
7fd59977 |
362 | } |
363 | } |
364 | } |
00302ba4 |
365 | } |
2a78ec6a |
366 | // |
7fd59977 |
367 | if (!intrvtested) { |
2a78ec6a |
368 | // Keep a priori. A point 2d on each |
369 | // surface is required to make the decision. Will be done in the caller |
7fd59977 |
370 | seqp.Append(GeomInt_LineTool::FirstParameter(L)); |
371 | seqp.Append(GeomInt_LineTool::LastParameter(L)); |
372 | } |
2a78ec6a |
373 | // |
374 | done =Standard_True; |
7fd59977 |
375 | return; |
2a78ec6a |
376 | } // else if (typl != IntPatch_Restriction) { |
7fd59977 |
377 | |
378 | done = Standard_False; |
379 | seqp.Clear(); |
380 | nbvtx = GeomInt_LineTool::NbVertex(L); |
2a78ec6a |
381 | if (nbvtx == 0) { // Keep a priori. Point 2d is required on each |
382 | // surface to make the decision. Will be done in the caller |
7fd59977 |
383 | seqp.Append(GeomInt_LineTool::FirstParameter(L)); |
384 | seqp.Append(GeomInt_LineTool::LastParameter(L)); |
385 | done = Standard_True; |
386 | return; |
387 | } |
388 | |
389 | GeomInt_SequenceOfParameterAndOrientation seqpss; |
390 | TopAbs_Orientation or1=TopAbs_FORWARD,or2=TopAbs_FORWARD; |
391 | |
2a78ec6a |
392 | for (i=1; i<=nbvtx; i++) { |
7fd59977 |
393 | const IntPatch_Point& thevtx = GeomInt_LineTool::Vertex(L,i); |
394 | const Standard_Real prm = thevtx.ParameterOnLine(); |
2a78ec6a |
395 | if (thevtx.IsOnDomS1()) { |
396 | switch (thevtx.TransitionLineArc1().TransitionType()) { |
397 | case IntSurf_In: or1 = TopAbs_FORWARD; break; |
398 | case IntSurf_Out: or1 = TopAbs_REVERSED; break; |
399 | case IntSurf_Touch: or1 = TopAbs_INTERNAL; break; |
7fd59977 |
400 | case IntSurf_Undecided: or1 = TopAbs_INTERNAL; break; |
401 | } |
402 | } |
2a78ec6a |
403 | else { |
7fd59977 |
404 | or1 = TopAbs_INTERNAL; |
2a78ec6a |
405 | } |
406 | |
407 | if (thevtx.IsOnDomS2()) { |
408 | switch (thevtx.TransitionLineArc2().TransitionType()) { |
409 | case IntSurf_In: or2 = TopAbs_FORWARD; break; |
410 | case IntSurf_Out: or2 = TopAbs_REVERSED; break; |
411 | case IntSurf_Touch: or2 = TopAbs_INTERNAL; break; |
412 | case IntSurf_Undecided: or2 = TopAbs_INTERNAL; break; |
7fd59977 |
413 | } |
414 | } |
2a78ec6a |
415 | else { |
7fd59977 |
416 | or2 = TopAbs_INTERNAL; |
2a78ec6a |
417 | } |
418 | // |
7fd59977 |
419 | const Standard_Integer nbinserted = seqpss.Length(); |
420 | Standard_Boolean inserted = Standard_False; |
2a78ec6a |
421 | for (Standard_Integer j=1; j<=nbinserted;j++) { |
422 | if (Abs(prm-seqpss(j).Parameter()) <= Tol) { |
423 | // accumulate |
7fd59977 |
424 | GeomInt_ParameterAndOrientation& valj = seqpss.ChangeValue(j); |
2a78ec6a |
425 | if (or1 != TopAbs_INTERNAL) { |
426 | if (valj.Orientation1() != TopAbs_INTERNAL) { |
427 | if (or1 != valj.Orientation1()) { |
7fd59977 |
428 | valj.SetOrientation1(TopAbs_INTERNAL); |
429 | } |
430 | } |
2a78ec6a |
431 | else { |
7fd59977 |
432 | valj.SetOrientation1(or1); |
433 | } |
434 | } |
2a78ec6a |
435 | |
436 | if (or2 != TopAbs_INTERNAL) { |
437 | if (valj.Orientation2() != TopAbs_INTERNAL) { |
438 | if (or2 != valj.Orientation2()) { |
7fd59977 |
439 | valj.SetOrientation2(TopAbs_INTERNAL); |
440 | } |
441 | } |
2a78ec6a |
442 | else { |
7fd59977 |
443 | valj.SetOrientation2(or2); |
444 | } |
2a78ec6a |
445 | } |
7fd59977 |
446 | inserted = Standard_True; |
447 | break; |
448 | } |
449 | |
450 | if (prm < seqpss(j).Parameter()-Tol ) { |
2a78ec6a |
451 | // insert before position j |
7fd59977 |
452 | seqpss.InsertBefore(j,GeomInt_ParameterAndOrientation(prm,or1,or2)); |
453 | inserted = Standard_True; |
454 | break; |
455 | } |
2a78ec6a |
456 | |
7fd59977 |
457 | } |
2a78ec6a |
458 | if (!inserted) { |
7fd59977 |
459 | seqpss.Append(GeomInt_ParameterAndOrientation(prm,or1,or2)); |
460 | } |
461 | } |
462 | |
2a78ec6a |
463 | // determine the state at the beginning of line |
7fd59977 |
464 | Standard_Boolean trim = Standard_False; |
465 | Standard_Boolean dansS1 = Standard_False; |
466 | Standard_Boolean dansS2 = Standard_False; |
467 | |
468 | nbvtx = seqpss.Length(); |
2a78ec6a |
469 | for (i=1; i<= nbvtx; i++) { |
7fd59977 |
470 | or1 = seqpss(i).Orientation1(); |
2a78ec6a |
471 | if (or1 != TopAbs_INTERNAL) { |
7fd59977 |
472 | trim = Standard_True; |
473 | dansS1 = (or1 != TopAbs_FORWARD); |
474 | break; |
475 | } |
476 | } |
2a78ec6a |
477 | |
478 | if (i > nbvtx) { |
7fd59977 |
479 | Standard_Real U,V; |
2a78ec6a |
480 | for (i=1; i<=GeomInt_LineTool::NbVertex(L); i++ ) { |
481 | if (!GeomInt_LineTool::Vertex(L,i).IsOnDomS1() ) { |
7fd59977 |
482 | GeomInt_LineTool::Vertex(L,i).ParametersOnS1(U,V); |
483 | gp_Pnt2d PPCC(U,V); |
484 | if (myDom1->Classify(PPCC,Tol) == TopAbs_OUT) { |
485 | done = Standard_True; |
486 | return; |
487 | } |
488 | break; |
489 | } |
490 | } |
2a78ec6a |
491 | dansS1 = Standard_True; // Keep in doubt |
7fd59977 |
492 | } |
2a78ec6a |
493 | // |
494 | for (i=1; i<= nbvtx; i++) { |
7fd59977 |
495 | or2 = seqpss(i).Orientation2(); |
2a78ec6a |
496 | if (or2 != TopAbs_INTERNAL) { |
7fd59977 |
497 | trim = Standard_True; |
498 | dansS2 = (or2 != TopAbs_FORWARD); |
499 | break; |
500 | } |
501 | } |
502 | |
2a78ec6a |
503 | if (i > nbvtx) { |
7fd59977 |
504 | Standard_Real U,V; |
2a78ec6a |
505 | for (i=1; i<=GeomInt_LineTool::NbVertex(L); i++ ) { |
506 | if (!GeomInt_LineTool::Vertex(L,i).IsOnDomS2() ) { |
7fd59977 |
507 | GeomInt_LineTool::Vertex(L,i).ParametersOnS2(U,V); |
508 | if (myDom2->Classify(gp_Pnt2d(U,V),Tol) == TopAbs_OUT) { |
509 | done = Standard_True; |
510 | return; |
511 | } |
512 | break; |
513 | } |
514 | } |
2a78ec6a |
515 | dansS2 = Standard_True; // Keep in doubt |
7fd59977 |
516 | } |
517 | |
2a78ec6a |
518 | if (!trim) { // necessarily dansS1 == dansS2 == Standard_True |
7fd59977 |
519 | seqp.Append(GeomInt_LineTool::FirstParameter(L)); |
520 | seqp.Append(GeomInt_LineTool::LastParameter(L)); |
521 | done = Standard_True; |
522 | return; |
523 | } |
524 | |
2a78ec6a |
525 | // sequence seqpss is peeled to create valid ends |
526 | // and store them in seqp(2*i+1) and seqp(2*i+2) |
7fd59977 |
527 | Standard_Real thefirst = GeomInt_LineTool::FirstParameter(L); |
528 | Standard_Real thelast = GeomInt_LineTool::LastParameter(L); |
529 | firstp = thefirst; |
530 | |
2a78ec6a |
531 | for (i=1; i<=nbvtx; i++) { |
7fd59977 |
532 | or1 = seqpss(i).Orientation1(); |
533 | or2 = seqpss(i).Orientation2(); |
2a78ec6a |
534 | if (dansS1 && dansS2) { |
535 | if (or1 == TopAbs_REVERSED){ |
7fd59977 |
536 | dansS1 = Standard_False; |
2a78ec6a |
537 | } |
538 | |
539 | if (or2 == TopAbs_REVERSED){ |
7fd59977 |
540 | dansS2 = Standard_False; |
2a78ec6a |
541 | } |
542 | if (!dansS1 || !dansS2) { |
7fd59977 |
543 | lastp = seqpss(i).Parameter(); |
544 | Standard_Real stofirst = Max(firstp, thefirst); |
545 | Standard_Real stolast = Min(lastp, thelast) ; |
2a78ec6a |
546 | |
547 | if (stolast > stofirst) { |
7fd59977 |
548 | seqp.Append(stofirst); |
549 | seqp.Append(stolast); |
550 | } |
2a78ec6a |
551 | if (lastp > thelast) { |
7fd59977 |
552 | break; |
2a78ec6a |
553 | } |
7fd59977 |
554 | } |
555 | } |
2a78ec6a |
556 | else { |
557 | if (dansS1) { |
558 | if (or1 == TopAbs_REVERSED) { |
7fd59977 |
559 | dansS1 = Standard_False; |
2a78ec6a |
560 | } |
7fd59977 |
561 | } |
2a78ec6a |
562 | else { |
563 | if (or1 == TopAbs_FORWARD){ |
7fd59977 |
564 | dansS1 = Standard_True; |
2a78ec6a |
565 | } |
7fd59977 |
566 | } |
2a78ec6a |
567 | if (dansS2) { |
568 | if (or2 == TopAbs_REVERSED) { |
7fd59977 |
569 | dansS2 = Standard_False; |
2a78ec6a |
570 | } |
7fd59977 |
571 | } |
2a78ec6a |
572 | else { |
573 | if (or2 == TopAbs_FORWARD){ |
7fd59977 |
574 | dansS2 = Standard_True; |
2a78ec6a |
575 | } |
7fd59977 |
576 | } |
2a78ec6a |
577 | if (dansS1 && dansS2){ |
7fd59977 |
578 | firstp = seqpss(i).Parameter(); |
2a78ec6a |
579 | } |
7fd59977 |
580 | } |
581 | } |
2a78ec6a |
582 | // |
583 | // finally to add |
584 | if (dansS1 && dansS2) { |
7fd59977 |
585 | lastp = thelast; |
586 | firstp = Max(firstp,thefirst); |
587 | if (lastp > firstp) { |
588 | seqp.Append(firstp); |
589 | seqp.Append(lastp); |
590 | } |
591 | } |
592 | done = Standard_True; |
593 | } |
594 | |
94783b51 |
595 | //======================================================================= |
596 | //function : TreatCircle |
597 | //purpose : |
598 | //======================================================================= |
599 | void GeomInt_LineConstructor::TreatCircle(const Handle(IntPatch_Line)& theLine, |
600 | const Standard_Real theTol) |
601 | { |
602 | const IntPatch_IType aType = theLine->ArcType(); |
603 | const Handle(IntPatch_GLine) aGLine(Handle(IntPatch_GLine)::DownCast(theLine)); |
604 | if (RejectMicroCircle(aGLine, aType, theTol)) |
605 | { |
606 | return; |
607 | } |
608 | //---------------------------------------- |
609 | const Standard_Integer aNbVtx = aGLine->NbVertex(); |
610 | NCollection_Array1<GeomInt_Vertex> aVtxArr(1, aNbVtx + 1); |
611 | for (Standard_Integer i = 1; i <= aNbVtx; i++) |
612 | { |
613 | aVtxArr(i).SetVertex(aGLine->Vertex(i)); |
614 | } |
615 | |
616 | std::sort(aVtxArr.begin(), aVtxArr.begin() + aNbVtx); |
617 | |
618 | //Create last vertex |
619 | const Standard_Real aMinPrm = aVtxArr.First().Getvertex().ParameterOnLine() + TwoPI; |
620 | aVtxArr.ChangeLast().SetParameter(aMinPrm); |
621 | |
622 | RejectDuplicates(aVtxArr); |
623 | |
624 | std::sort(aVtxArr.begin(), aVtxArr.end()); |
625 | |
626 | Standard_Real aU1, aV1, aU2, aV2; |
627 | gp_Pnt aPmid; |
628 | gp_Pnt2d aP2D; |
629 | for (Standard_Integer i = aVtxArr.Lower(); i <= aVtxArr.Upper() - 1; i++) |
630 | { |
631 | const Standard_Real aT1 = aVtxArr(i).Getvertex().ParameterOnLine(); |
632 | const Standard_Real aT2 = aVtxArr(i + 1).Getvertex().ParameterOnLine(); |
633 | |
634 | if (aT2 == RealLast()) |
635 | break; |
636 | |
637 | const Standard_Real aTmid = (aT1 + aT2)*0.5; |
638 | GLinePoint(aType, aGLine, aTmid, aPmid); |
639 | // |
640 | Parameters(myHS1, myHS2, aPmid, aU1, aV1, aU2, aV2); |
641 | AdjustPeriodic(myHS1, myHS2, aU1, aV1, aU2, aV2); |
642 | // |
643 | aP2D.SetCoord(aU1, aV1); |
644 | TopAbs_State aState = myDom1->Classify(aP2D, theTol); |
645 | if (aState != TopAbs_OUT) |
646 | { |
647 | aP2D.SetCoord(aU2, aV2); |
648 | aState = myDom2->Classify(aP2D, theTol); |
649 | if (aState != TopAbs_OUT) |
650 | { |
651 | seqp.Append(aT1); |
652 | seqp.Append(aT2); |
653 | } |
654 | } |
655 | } |
656 | } |
7fd59977 |
657 | |
658 | //======================================================================= |
94783b51 |
659 | //function : AdjustPeriodic |
2a78ec6a |
660 | //purpose : |
661 | //======================================================================= |
94783b51 |
662 | void AdjustPeriodic(const Handle(GeomAdaptor_HSurface)& myHS1, |
663 | const Handle(GeomAdaptor_HSurface)& myHS2, |
664 | Standard_Real& u1, |
665 | Standard_Real& v1, |
666 | Standard_Real& u2, |
667 | Standard_Real& v2) |
668 | { |
669 | Standard_Boolean myHS1IsUPeriodic, myHS1IsVPeriodic; |
2a78ec6a |
670 | const GeomAbs_SurfaceType typs1 = myHS1->GetType(); |
671 | switch (typs1) |
94783b51 |
672 | { |
2a78ec6a |
673 | case GeomAbs_Cylinder: |
674 | case GeomAbs_Cone: |
94783b51 |
675 | case GeomAbs_Sphere: |
676 | { |
2a78ec6a |
677 | myHS1IsUPeriodic = Standard_True; |
678 | myHS1IsVPeriodic = Standard_False; |
679 | break; |
680 | } |
681 | case GeomAbs_Torus: |
682 | { |
683 | myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_True; |
684 | break; |
685 | } |
686 | default: |
687 | { |
688 | //-- Case of periodic biparameters is processed upstream |
689 | myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_False; |
690 | break; |
691 | } |
692 | } |
94783b51 |
693 | Standard_Boolean myHS2IsUPeriodic, myHS2IsVPeriodic; |
2a78ec6a |
694 | const GeomAbs_SurfaceType typs2 = myHS2->GetType(); |
695 | switch (typs2) |
94783b51 |
696 | { |
2a78ec6a |
697 | case GeomAbs_Cylinder: |
698 | case GeomAbs_Cone: |
94783b51 |
699 | case GeomAbs_Sphere: |
700 | { |
2a78ec6a |
701 | myHS2IsUPeriodic = Standard_True; |
702 | myHS2IsVPeriodic = Standard_False; |
703 | break; |
704 | } |
705 | case GeomAbs_Torus: |
706 | { |
707 | myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_True; |
708 | break; |
709 | } |
710 | default: |
711 | { |
712 | //-- Case of periodic biparameters is processed upstream |
713 | myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_False; |
714 | break; |
715 | } |
716 | } |
717 | Standard_Real du, dv; |
718 | // |
94783b51 |
719 | if (myHS1IsUPeriodic) |
720 | { |
721 | const Standard_Real lmf = M_PI + M_PI; //-- myHS1->UPeriod(); |
2a78ec6a |
722 | const Standard_Real f = myHS1->FirstUParameter(); |
723 | const Standard_Real l = myHS1->LastUParameter(); |
724 | GeomInt::AdjustPeriodic(u1, f, l, lmf, u1, du); |
725 | } |
94783b51 |
726 | if (myHS1IsVPeriodic) |
727 | { |
728 | const Standard_Real lmf = M_PI + M_PI; //-- myHS1->VPeriod(); |
2a78ec6a |
729 | const Standard_Real f = myHS1->FirstVParameter(); |
730 | const Standard_Real l = myHS1->LastVParameter(); |
731 | GeomInt::AdjustPeriodic(v1, f, l, lmf, v1, dv); |
732 | } |
94783b51 |
733 | if (myHS2IsUPeriodic) |
734 | { |
735 | const Standard_Real lmf = M_PI + M_PI; //-- myHS2->UPeriod(); |
2a78ec6a |
736 | const Standard_Real f = myHS2->FirstUParameter(); |
737 | const Standard_Real l = myHS2->LastUParameter(); |
738 | GeomInt::AdjustPeriodic(u2, f, l, lmf, u2, du); |
739 | } |
94783b51 |
740 | if (myHS2IsVPeriodic) |
741 | { |
742 | const Standard_Real lmf = M_PI + M_PI; //-- myHS2->VPeriod(); |
2a78ec6a |
743 | const Standard_Real f = myHS2->FirstVParameter(); |
744 | const Standard_Real l = myHS2->LastVParameter(); |
745 | GeomInt::AdjustPeriodic(v2, f, l, lmf, v2, dv); |
746 | } |
747 | } |
94783b51 |
748 | |
2a78ec6a |
749 | //======================================================================= |
750 | //function : Parameters |
751 | //purpose : |
752 | //======================================================================= |
753 | void Parameters(const Handle(GeomAdaptor_HSurface)& myHS1, |
754 | const Handle(GeomAdaptor_HSurface)& myHS2, |
755 | const gp_Pnt& Ptref, |
756 | Standard_Real& U1, |
757 | Standard_Real& V1, |
758 | Standard_Real& U2, |
759 | Standard_Real& V2) |
760 | { |
761 | Parameters(myHS1, Ptref, U1, V1); |
762 | Parameters(myHS2, Ptref, U2, V2); |
763 | } |
94783b51 |
764 | |
2a78ec6a |
765 | //======================================================================= |
766 | //function : Parameter |
767 | //purpose : |
768 | //======================================================================= |
769 | void Parameters(const Handle(GeomAdaptor_HSurface)& myHS1, |
770 | const gp_Pnt& Ptref, |
771 | Standard_Real& U1, |
772 | Standard_Real& V1) |
773 | { |
774 | IntSurf_Quadric quad1; |
775 | // |
94783b51 |
776 | switch (myHS1->Surface().GetType()) |
777 | { |
778 | case GeomAbs_Plane: |
779 | quad1.SetValue(myHS1->Surface().Plane()); |
2a78ec6a |
780 | break; |
94783b51 |
781 | case GeomAbs_Cylinder: |
782 | quad1.SetValue(myHS1->Surface().Cylinder()); |
2a78ec6a |
783 | break; |
94783b51 |
784 | case GeomAbs_Cone: |
785 | quad1.SetValue(myHS1->Surface().Cone()); |
2a78ec6a |
786 | break; |
94783b51 |
787 | case GeomAbs_Sphere: |
788 | quad1.SetValue(myHS1->Surface().Sphere()); |
2a78ec6a |
789 | break; |
790 | case GeomAbs_Torus: |
94783b51 |
791 | quad1.SetValue(myHS1->Surface().Torus()); |
2a78ec6a |
792 | break; |
94783b51 |
793 | default: |
9775fa61 |
794 | throw Standard_ConstructionError("GeomInt_LineConstructor::Parameters"); |
2a78ec6a |
795 | } |
94783b51 |
796 | quad1.Parameters(Ptref, U1, V1); |
2a78ec6a |
797 | } |
798 | |
799 | //======================================================================= |
800 | //function : GLinePoint |
7fd59977 |
801 | //purpose : |
802 | //======================================================================= |
2a78ec6a |
803 | void GLinePoint(const IntPatch_IType typl, |
804 | const Handle(IntPatch_GLine)& GLine, |
805 | const Standard_Real aT, |
806 | gp_Pnt& aP) |
7fd59977 |
807 | { |
94783b51 |
808 | switch (typl) |
809 | { |
810 | case IntPatch_Lin: |
811 | aP = ElCLib::Value(aT, GLine->Line()); |
812 | break; |
813 | case IntPatch_Circle: |
814 | aP = ElCLib::Value(aT, GLine->Circle()); |
815 | break; |
816 | case IntPatch_Ellipse: |
817 | aP = ElCLib::Value(aT, GLine->Ellipse()); |
818 | break; |
819 | case IntPatch_Hyperbola: |
820 | aP = ElCLib::Value(aT, GLine->Hyperbola()); |
821 | break; |
822 | case IntPatch_Parabola: |
823 | aP = ElCLib::Value(aT, GLine->Parabola()); |
824 | break; |
825 | default: |
826 | throw Standard_ConstructionError("GeomInt_LineConstructor::Parameters"); |
2a78ec6a |
827 | } |
2a78ec6a |
828 | } |
829 | |
2a78ec6a |
830 | //======================================================================= |
831 | //function : RejectMicroCrcles |
832 | //purpose : |
833 | //======================================================================= |
834 | Standard_Boolean RejectMicroCircle(const Handle(IntPatch_GLine)& aGLine, |
835 | const IntPatch_IType aType, |
836 | const Standard_Real aTol3D) |
837 | { |
838 | Standard_Boolean bRet; |
839 | Standard_Real aR; |
840 | // |
841 | bRet=Standard_False; |
842 | // |
843 | if (aType==IntPatch_Circle) { |
844 | aR=aGLine->Circle().Radius(); |
845 | bRet=(aR<aTol3D); |
846 | } |
847 | else if (aType==IntPatch_Ellipse) { |
848 | aR=aGLine->Ellipse().MajorRadius(); |
849 | bRet=(aR<aTol3D); |
850 | } |
851 | return bRet; |
852 | } |
94783b51 |
853 | |
2a78ec6a |
854 | //======================================================================= |
94783b51 |
855 | //function : RejectDuplicates |
856 | //purpose : Finds two coincident IntPatch_Points (if they exist) and |
857 | // sets Parameter-On-Line fore one such point to DBL_MAX |
858 | // (i.e. its use in the future is forbidden). |
859 | // |
860 | //ATTENTION!!! |
861 | // The source array must be sorted in ascending order. |
2a78ec6a |
862 | //======================================================================= |
94783b51 |
863 | void RejectDuplicates(NCollection_Array1<GeomInt_Vertex>& theVtxArr) |
2a78ec6a |
864 | { |
94783b51 |
865 | // About the value aTolPC=1000.*Precision::PConfusion(), |
866 | // see IntPatch_GLine::ComputeVertexParameters(...) |
867 | // for more details; |
868 | const Standard_Real aTolPC = 1000.*Precision::PConfusion(); |
869 | |
870 | //Find duplicates in a slice of the array [LowerBound, UpperBound-1]. |
871 | //If a duplicate has been found, the element with greater index will be rejected. |
872 | for (Standard_Integer i = theVtxArr.Lower(); i <= theVtxArr.Upper() - 2; i++) |
873 | { |
874 | const IntPatch_Point &aVi = theVtxArr(i).Getvertex(); |
875 | const Standard_Real aPrmi = aVi.ParameterOnLine(); |
876 | |
877 | if (aPrmi == RealLast()) |
878 | continue; |
879 | |
880 | for (Standard_Integer j = i + 1; j <= theVtxArr.Upper() - 1; j++) |
881 | { |
882 | const IntPatch_Point &aVj = theVtxArr(j).Getvertex(); |
883 | const Standard_Real aPrmj = aVj.ParameterOnLine(); |
884 | |
885 | if (aPrmj - aPrmi < aTolPC) |
886 | { |
887 | theVtxArr(j).SetParameter(RealLast()); |
888 | } |
889 | else |
890 | { |
891 | break; |
892 | } |
893 | } |
894 | } |
895 | |
896 | //Find duplicates with the last element of the array. |
897 | //If a duplicate has been found, the found element will be rejected. |
898 | const Standard_Real aMaxPrm = theVtxArr.Last().Getvertex().ParameterOnLine(); |
899 | for (Standard_Integer i = theVtxArr.Upper() - 1; i > theVtxArr.Lower(); i--) |
900 | { |
901 | const IntPatch_Point &aVi = theVtxArr(i).Getvertex(); |
902 | const Standard_Real aPrmi = aVi.ParameterOnLine(); |
903 | |
904 | if (aPrmi == RealLast()) |
905 | continue; |
906 | |
907 | if ((aMaxPrm - aPrmi) < aTolPC) |
908 | { |
909 | theVtxArr(i).SetParameter(RealLast()); |
910 | } |
911 | else |
912 | { |
913 | break; |
914 | } |
2a78ec6a |
915 | } |
7fd59977 |
916 | } |