0027194: Possible division by zero in IntPatch_WLineTool
[occt.git] / src / IntPatch / IntPatch_WLineTool.cxx
CommitLineData
4e14c88f 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
2//
3// This file is part of Open CASCADE Technology software library.
4//
5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
10//
11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
13
14#include <IntPatch_WLineTool.hxx>
15
16#include <Adaptor3d_HSurface.hxx>
17#include <Adaptor3d_TopolTool.hxx>
b8f67cc2 18#include <ElCLib.hxx>
19
20//Bit-mask is used for information about
21//the operation made in
22//IntPatch_WLineTool::ExtendTwoWlinesToEachOther() method.
23enum
24{
25 IntPatchWT_EnAll = 0x00,
26 IntPatchWT_DisLastLast = 0x01,
27 IntPatchWT_DisLastFirst = 0x02,
28 IntPatchWT_DisFirstLast = 0x04,
29 IntPatchWT_DisFirstFirst = 0x08
30};
4e14c88f 31
32//=======================================================================
33//function : MinMax
34//purpose : Replaces theParMIN = MIN(theParMIN, theParMAX),
35// theParMAX = MAX(theParMIN, theParMAX).
36//
37// Static subfunction in IsSeamOrBound.
38//=======================================================================
39static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
40{
41 if(theParMIN > theParMAX)
42 {
43 const Standard_Real aTmp = theParMAX;
44 theParMAX = theParMIN;
45 theParMIN = aTmp;
46 }
47}
48
49//=========================================================================
50// function : FillPointsHash
51// purpose : Fill points hash by input data.
52// Static subfunction in ComputePurgedWLine.
53//=========================================================================
54static void FillPointsHash(const Handle(IntPatch_WLine) &theWLine,
55 NCollection_Array1<Standard_Integer> &thePointsHash)
56{
57 // 1 - Delete point.
58 // 0 - Store point.
59 // -1 - Vertex point (not delete).
60 Standard_Integer i, v;
61
62 for(i = 1; i <= theWLine->NbPnts(); i++)
63 thePointsHash.SetValue(i, 0);
64
65 for(v = 1; v <= theWLine->NbVertex(); v++)
66 {
67 IntPatch_Point aVertex = theWLine->Vertex(v);
68 Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
69 thePointsHash.SetValue(avertexindex, -1);
70 }
71}
72
73//=========================================================================
74// function : MakeNewWLine
75// purpose : Makes new walking line according to the points hash
76// Static subfunction in ComputePurgedWLine and DeleteOuter.
77//=========================================================================
78static Handle(IntPatch_WLine) MakeNewWLine(const Handle(IntPatch_WLine) &theWLine,
79 const NCollection_Array1<Standard_Integer> &thePointsHash)
80{
81 Standard_Integer i;
82
83 Handle(IntSurf_LineOn2S) aPurgedLineOn2S = new IntSurf_LineOn2S();
84 Handle(IntPatch_WLine) aLocalWLine = new IntPatch_WLine(aPurgedLineOn2S, Standard_False);
85 Standard_Integer anOldLineIdx = 1, aVertexIdx = 1;
86 for(i = 1; i <= thePointsHash.Upper(); i++)
87 {
88 if (thePointsHash(i) == 0)
89 {
90 // Store this point.
91 aPurgedLineOn2S->Add(theWLine->Point(i));
92 anOldLineIdx++;
93 }
94 else if (thePointsHash(i) == -1)
95 {
96 // Add vertex.
97 IntPatch_Point aVertex = theWLine->Vertex(aVertexIdx++);
98 aVertex.SetParameter(anOldLineIdx++);
99 aLocalWLine->AddVertex(aVertex);
100 aPurgedLineOn2S->Add(theWLine->Point(i));
101 }
102 }
103
104 return aLocalWLine;
105}
106
107//=========================================================================
108// function : MovePoint
109// purpose : Move point into surface param space. No interpolation used
110// because walking algorithm should care for closeness to the param space.
111// Static subfunction in ComputePurgedWLine.
112//=========================================================================
113static void MovePoint(const Handle(Adaptor3d_HSurface) &theS1,
114 Standard_Real &U1, Standard_Real &V1)
115{
116 if (U1 < theS1->FirstUParameter())
117 U1 = theS1->FirstUParameter();
118
119 if (U1 > theS1->LastUParameter())
120 U1 = theS1->LastUParameter();
121
122 if (V1 < theS1->FirstVParameter())
123 V1 = theS1->FirstVParameter();
124
125 if (V1 > theS1->LastVParameter())
126 V1 = theS1->LastVParameter();
127}
128
129//=========================================================================
130// function : DeleteOuterPoints
131// purpose : Check and delete out of bounds points on walking line.
132// Static subfunction in ComputePurgedWLine.
133//=========================================================================
134static Handle(IntPatch_WLine)
135 DeleteOuterPoints(const Handle(IntPatch_WLine) &theWLine,
136 const Handle(Adaptor3d_HSurface) &theS1,
137 const Handle(Adaptor3d_HSurface) &theS2,
138 const Handle(Adaptor3d_TopolTool) &theDom1,
139 const Handle(Adaptor3d_TopolTool) &theDom2)
140{
141 Standard_Integer i;
142
143 NCollection_Array1<Standard_Integer> aDelOuterPointsHash(1, theWLine->NbPnts());
144 FillPointsHash(theWLine, aDelOuterPointsHash);
145
146 if (theS1->IsUPeriodic() || theS1->IsVPeriodic() ||
147 theS2->IsUPeriodic() || theS2->IsVPeriodic() )
148 return theWLine;
149
150 gp_Pnt2d aPntOnF1, aPntOnF2;
151 Standard_Real aX1, aY1, aX2, aY2;
152
153 // Iterate over points in walking line and delete which are out of bounds.
154 // Forward.
155 Standard_Boolean isAllDeleted = Standard_True;
156 Standard_Boolean aChangedFirst = Standard_False;
157 Standard_Integer aFirstGeomIdx = 1;
158 for(i = 1; i <= theWLine->NbPnts(); i++)
159 {
160 theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
161 aPntOnF1.SetCoord(aX1, aY1);
162 aPntOnF2.SetCoord(aX2, aY2);
163
164 TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
165 TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
166
167 if (aState1 == TopAbs_OUT ||
168 aState2 == TopAbs_OUT )
169 {
170 aDelOuterPointsHash(i) = 1;
171 aChangedFirst = Standard_True;
172 }
173 else
174 {
175 isAllDeleted = Standard_False;
176
177 aFirstGeomIdx = Max (i - 1, 1);
178 if (aDelOuterPointsHash(i) == -1)
179 aFirstGeomIdx = i; // Use data what lies in (i) point / vertex.
180
181 aDelOuterPointsHash(i) = -1;
182 break;
183 }
184 }
185
186 if (isAllDeleted)
187 {
188 // ALL points are out of bounds:
189 // case boolean bcut_complex F5 and similar.
190 return theWLine;
191 }
192
193 // Backward.
194 Standard_Boolean aChangedLast = Standard_False;
195 Standard_Integer aLastGeomIdx = theWLine->NbPnts();
196 for(i = theWLine->NbPnts(); i >= 1; i--)
197 {
198 theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
199 aPntOnF1.SetCoord(aX1, aY1);
200 aPntOnF2.SetCoord(aX2, aY2);
201
202 TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
203 TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
204
205 if (aState1 == TopAbs_OUT ||
206 aState2 == TopAbs_OUT )
207 {
208 aDelOuterPointsHash(i) = 1;
209 aChangedLast = Standard_True; // Move vertex to first good point
210 }
211 else
212 {
213 aLastGeomIdx = Min (i + 1, theWLine->NbPnts());
214 if (aDelOuterPointsHash(i) == -1)
215 aLastGeomIdx = i; // Use data what lies in (i) point / vertex.
216
217 aDelOuterPointsHash(i) = -1;
218 break;
219 }
220 }
221
222 if (!aChangedFirst && !aChangedLast)
223 {
224 // Nothing is done, return input.
225 return theWLine;
226 }
227
228 // Build new line and modify geometry of necessary vertexes.
229 Handle(IntPatch_WLine) aLocalWLine = MakeNewWLine(theWLine, aDelOuterPointsHash);
230
231 if (aChangedFirst)
232 {
233 // Vertex geometry.
234 IntPatch_Point aVertex = aLocalWLine->Vertex(1);
235 aVertex.SetValue(theWLine->Point(aFirstGeomIdx).Value());
236 Standard_Real aU1, aU2, aV1, aV2;
237 theWLine->Point(aFirstGeomIdx).Parameters(aU1, aV1, aU2, aV2);
238 MovePoint(theS1, aU1, aV1);
239 MovePoint(theS2, aU2, aV2);
240 aVertex.SetParameters(aU1, aV1, aU2, aV2);
241 aLocalWLine->Replace(1, aVertex);
242 // Change point in walking line.
243 aLocalWLine->SetPoint(1, aVertex);
244 }
245
246 if (aChangedLast)
247 {
248 // Vertex geometry.
249 IntPatch_Point aVertex = aLocalWLine->Vertex(aLocalWLine->NbVertex());
250 aVertex.SetValue(theWLine->Point(aLastGeomIdx).Value());
251 Standard_Real aU1, aU2, aV1, aV2;
252 theWLine->Point(aLastGeomIdx).Parameters(aU1, aV1, aU2, aV2);
253 MovePoint(theS1, aU1, aV1);
254 MovePoint(theS2, aU2, aV2);
255 aVertex.SetParameters(aU1, aV1, aU2, aV2);
256 aLocalWLine->Replace(aLocalWLine->NbVertex(), aVertex);
257 // Change point in walking line.
258 aLocalWLine->SetPoint(aLocalWLine->NbPnts(), aVertex);
259 }
260
261
262 return aLocalWLine;
263}
264
265//=========================================================================
266// function : IsInsideIn2d
267// purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
268// In 2d space. Static subfunction in DeleteByTube.
269//=========================================================================
270static Standard_Boolean IsInsideIn2d(const gp_Pnt2d& aBasePnt,
271 const gp_Vec2d& aBaseVec,
272 const gp_Pnt2d& aNextPnt,
273 const Standard_Real aSquareMaxDist)
274{
275 gp_Vec2d aVec2d(aBasePnt, aNextPnt);
276
277 //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
278 Standard_Real aCross = aVec2d.Crossed(aBaseVec);
279 Standard_Real aSquareDist = aCross * aCross
280 / aBaseVec.SquareMagnitude();
281
282 return (aSquareDist <= aSquareMaxDist);
283}
284
285//=========================================================================
286// function : IsInsideIn3d
287// purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
288// In 3d space. Static subfunction in DeleteByTube.
289//=========================================================================
290static Standard_Boolean IsInsideIn3d(const gp_Pnt& aBasePnt,
291 const gp_Vec& aBaseVec,
292 const gp_Pnt& aNextPnt,
293 const Standard_Real aSquareMaxDist)
294{
295 gp_Vec aVec(aBasePnt, aNextPnt);
296
297 //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
298 Standard_Real aSquareDist = aVec.CrossSquareMagnitude(aBaseVec)
299 / aBaseVec.SquareMagnitude();
300
301 return (aSquareDist <= aSquareMaxDist);
302}
303
304static const Standard_Integer aMinNbBadDistr = 15;
305static const Standard_Integer aNbSingleBezier = 30;
306
307//=========================================================================
308// function : DeleteByTube
309// purpose : Check and delete points using tube criteria.
310// Static subfunction in ComputePurgedWLine.
311//=========================================================================
312static Handle(IntPatch_WLine)
313 DeleteByTube(const Handle(IntPatch_WLine) &theWLine,
314 const Handle(Adaptor3d_HSurface) &theS1,
315 const Handle(Adaptor3d_HSurface) &theS2)
316{
317 // III: Check points for tube criteria:
318 // Workaround to handle case of small amount points after purge.
319 // Test "boolean boptuc_complex B5" and similar.
320 Standard_Integer aNbPnt = 0 , i;
321
322 if (theWLine->NbPnts() <= 2)
323 return theWLine;
324
325 NCollection_Array1<Standard_Integer> aNewPointsHash(1, theWLine->NbPnts());
326 FillPointsHash(theWLine, aNewPointsHash);
327
328 // Inital computations.
329 Standard_Real UonS1[3], VonS1[3], UonS2[3], VonS2[3];
330 theWLine->Point(1).ParametersOnS1(UonS1[0], VonS1[0]);
331 theWLine->Point(2).ParametersOnS1(UonS1[1], VonS1[1]);
332 theWLine->Point(1).ParametersOnS2(UonS2[0], VonS2[0]);
333 theWLine->Point(2).ParametersOnS2(UonS2[1], VonS2[1]);
334
335 gp_Pnt2d aBase2dPnt1(UonS1[0], VonS1[0]);
336 gp_Pnt2d aBase2dPnt2(UonS2[0], VonS2[0]);
337 gp_Vec2d aBase2dVec1(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
338 gp_Vec2d aBase2dVec2(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
339 gp_Pnt aBase3dPnt = theWLine->Point(1).Value();
340 gp_Vec aBase3dVec(theWLine->Point(1).Value(), theWLine->Point(2).Value());
341
342 // Choose base tolerance and scale it to pipe algorithm.
343 const Standard_Real aBaseTolerance = Precision::Approximation();
344 Standard_Real aResS1Tol = Min(theS1->UResolution(aBaseTolerance),
345 theS1->VResolution(aBaseTolerance));
346 Standard_Real aResS2Tol = Min(theS2->UResolution(aBaseTolerance),
347 theS2->VResolution(aBaseTolerance));
348 Standard_Real aTol1 = aResS1Tol * aResS1Tol;
349 Standard_Real aTol2 = aResS2Tol * aResS2Tol;
350 Standard_Real aTol3d = aBaseTolerance * aBaseTolerance;
351
352 const Standard_Real aLimitCoeff = 0.99 * 0.99;
353 for(i = 3; i <= theWLine->NbPnts(); i++)
354 {
355 Standard_Boolean isDeleteState = Standard_False;
356
357 theWLine->Point(i).ParametersOnS1(UonS1[2], VonS1[2]);
358 theWLine->Point(i).ParametersOnS2(UonS2[2], VonS2[2]);
359 gp_Pnt2d aPnt2dOnS1(UonS1[2], VonS1[2]);
360 gp_Pnt2d aPnt2dOnS2(UonS2[2], VonS2[2]);
361 const gp_Pnt& aPnt3d = theWLine->Point(i).Value();
362
363 if (aNewPointsHash(i - 1) != - 1 &&
364 IsInsideIn2d(aBase2dPnt1, aBase2dVec1, aPnt2dOnS1, aTol1) &&
365 IsInsideIn2d(aBase2dPnt2, aBase2dVec2, aPnt2dOnS2, aTol2) &&
366 IsInsideIn3d(aBase3dPnt, aBase3dVec, aPnt3d, aTol3d) )
367 {
368 // Handle possible uneven parametrization on one of 2d subspaces.
369 // Delete point only when expected lengths are close to each other (aLimitCoeff).
370 // Example:
371 // c2d1 - line
372 // c3d - line
373 // c2d2 - geometrically line, but have uneven parametrization -> c2d2 is bspline.
374 gp_XY aPntOnS1[2]= { gp_XY(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0])
375 , gp_XY(UonS1[2] - UonS1[1], VonS1[2] - VonS1[1])};
376 gp_XY aPntOnS2[2]= { gp_XY(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0])
377 , gp_XY(UonS2[2] - UonS2[1], VonS2[2] - VonS2[1])};
378
379 Standard_Real aStepOnS1 = aPntOnS1[0].SquareModulus() / aPntOnS1[1].SquareModulus();
380 Standard_Real aStepOnS2 = aPntOnS2[0].SquareModulus() / aPntOnS2[1].SquareModulus();
381
871776ea 382 // Check very rare case when wline fluctuates nearly one point and some of them may be equal.
383 // Middle point will be deleted when such situation occurs.
384 // bugs moddata_2 bug469.
385 if (Min(aStepOnS1, aStepOnS2) >= aLimitCoeff * Max(aStepOnS1, aStepOnS2))
4e14c88f 386 {
387 // Set hash flag to "Delete" state.
388 isDeleteState = Standard_True;
389 aNewPointsHash.SetValue(i - 1, 1);
390
391 // Change middle point.
392 UonS1[1] = UonS1[2];
393 UonS2[1] = UonS2[2];
394 VonS1[1] = VonS1[2];
395 VonS2[1] = VonS2[2];
396 }
397 }
398
399 if (!isDeleteState)
400 {
401 // Compute new pipe parameters.
402 UonS1[0] = UonS1[1];
403 VonS1[0] = VonS1[1];
404 UonS2[0] = UonS2[1];
405 VonS2[0] = VonS2[1];
406
407 UonS1[1] = UonS1[2];
408 VonS1[1] = VonS1[2];
409 UonS2[1] = UonS2[2];
410 VonS2[1] = VonS2[2];
411
412 aBase2dPnt1.SetCoord(UonS1[0], VonS1[0]);
413 aBase2dPnt2.SetCoord(UonS2[0], VonS2[0]);
414 aBase2dVec1.SetCoord(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
415 aBase2dVec2.SetCoord(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
416 aBase3dPnt = theWLine->Point(i - 1).Value();
417 aBase3dVec = gp_Vec(theWLine->Point(i - 1).Value(), theWLine->Point(i).Value());
418
419 aNbPnt++;
420 }
421 }
422
423 // Workaround to handle case of small amount of points after purge.
424 // Test "boolean boptuc_complex B5" and similar.
425 // This is possible since there are at least two points.
426 if (aNewPointsHash(1) == -1 &&
427 aNewPointsHash(2) == -1 &&
428 aNbPnt <= 3)
429 {
430 // Delete first.
431 aNewPointsHash(1) = 1;
432 }
433 if (aNewPointsHash(theWLine->NbPnts() - 1) == -1 &&
434 aNewPointsHash(theWLine->NbPnts() ) == -1 &&
435 aNbPnt <= 3)
436 {
437 // Delete last.
438 aNewPointsHash(theWLine->NbPnts()) = 1;
439 }
440
441 // Purgre when too small amount of points left.
442 if (aNbPnt <= 2)
443 {
444 for(i = aNewPointsHash.Lower(); i <= aNewPointsHash.Upper(); i++)
445 {
446 if (aNewPointsHash(i) != -1)
447 {
448 aNewPointsHash(i) = 1;
449 }
450 }
451 }
452
453 // Handle possible bad distribution of points,
454 // which are will converted into one single bezier curve (less than 30 points).
455 // Make distribution more even:
456 // max step will be nearly to 0.1 of param distance.
457 if (aNbPnt + 2 > aMinNbBadDistr &&
458 aNbPnt + 2 < aNbSingleBezier )
459 {
460 for(Standard_Integer anIdx = 1; anIdx <= 8; anIdx++)
461 {
462 Standard_Integer aHashIdx =
463 Standard_Integer(anIdx * theWLine->NbPnts() / 9);
464
47e3009d 465 //Vertex must be stored as VERTEX (HASH = -1)
466 if (aNewPointsHash(aHashIdx) != -1)
467 aNewPointsHash(aHashIdx) = 0;
4e14c88f 468 }
469 }
470
471 return MakeNewWLine(theWLine, aNewPointsHash);
472}
473
474//=======================================================================
b8f67cc2 475//function : IsOnPeriod
476//purpose : Checks, if [theU1, theU2] intersects the period-value
477// (k*thePeriod, where k is an integer number (k = 0, +/-1, +/-2, ...).
478//
479// Returns:
480// 0 - if interval [theU1, theU2] does not intersect the "period-value"
481// or if thePeriod == 0.0;
482// 1 - if interval (theU1, theU2) intersect the "period-value".
483// 2 - if theU1 or/and theU2 lie ON the "period-value"
4e14c88f 484//
485//ATTENTION!!!
486// If (theU1 == theU2) then this function will return only both 0 or 2.
4e14c88f 487//=======================================================================
b8f67cc2 488static Standard_Integer IsOnPeriod(const Standard_Real theU1,
489 const Standard_Real theU2,
490 const Standard_Real thePeriod)
4e14c88f 491{
b8f67cc2 492 if(thePeriod < RealSmall())
4e14c88f 493 return 0;
494
495 //If interval [theU1, theU2] intersect seam-edge then there exists an integer
496 //number N such as
497 // (theU1 <= T*N <= theU2) <=> (theU1/T <= N <= theU2/T),
498 //where T is the period.
499 //I.e. the inerval [theU1/T, theU2/T] must contain at least one
500 //integer number. In this case, Floor(theU1/T) and Floor(theU2/T)
501 //return different values or theU1/T is strictly integer number.
502 //Examples:
503 // 1. theU1/T==2.8, theU2/T==3.5 => Floor(theU1/T) == 2, Floor(theU2/T) == 3.
504 // 2. theU1/T==2.0, theU2/T==2.6 => Floor(theU1/T) == Floor(theU2/T) == 2.
505
506 const Standard_Real aVal1 = theU1/thePeriod,
507 aVal2 = theU2/thePeriod;
508 const Standard_Integer aPar1 = static_cast<Standard_Integer>(Floor(aVal1));
509 const Standard_Integer aPar2 = static_cast<Standard_Integer>(Floor(aVal2));
510 if(aPar1 != aPar2)
511 {//Interval (theU1, theU2] intersects seam-edge
512 if(IsEqual(aVal2, static_cast<Standard_Real>(aPar2)))
513 {//aVal2 is an integer number => theU2 lies ON the "seam-edge"
514 return 2;
515 }
516
517 return 1;
518 }
519
520 //Here, aPar1 == aPar2.
521
522 if(IsEqual(aVal1, static_cast<Standard_Real>(aPar1)))
523 {//aVal1 is an integer number => theU1 lies ON the "seam-edge"
524 return 2;
525 }
526
527 //If aVal2 is a true integer number then always (aPar1 != aPar2).
528
529 return 0;
530}
531
532//=======================================================================
533//function : IsSeamOrBound
534//purpose : Returns TRUE if segment [thePtf, thePtl] intersects "seam-edge"
535// (if it exist) or surface boundaries and both thePtf and thePtl do
536// not match "seam-edge" or boundaries.
eee615ad 537// Point thePtmid lies in this segment (in both 3D and 2D-space).
538// If thePtmid match "seam-edge" or boundaries strictly
539// (without any tolerance) then the function will return TRUE.
4e14c88f 540// See comments in function body for detail information.
4e14c88f 541//=======================================================================
542static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
543 const IntSurf_PntOn2S& thePtl,
544 const IntSurf_PntOn2S& thePtmid,
545 const Standard_Real theU1Period,
546 const Standard_Real theU2Period,
547 const Standard_Real theV1Period,
548 const Standard_Real theV2Period,
549 const Standard_Real theUfSurf1,
550 const Standard_Real theUlSurf1,
551 const Standard_Real theVfSurf1,
552 const Standard_Real theVlSurf1,
553 const Standard_Real theUfSurf2,
554 const Standard_Real theUlSurf2,
555 const Standard_Real theVfSurf2,
556 const Standard_Real theVlSurf2)
557{
558 Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0;
559 Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0;
560 thePtf.Parameters(aU11, aV11, aU12, aV12);
561 thePtl.Parameters(aU21, aV21, aU22, aV22);
562
563 MinMax(aU11, aU21);
564 MinMax(aV11, aV21);
565 MinMax(aU12, aU22);
566 MinMax(aV12, aV22);
567
568 if((aU11 - theUfSurf1)*(aU21 - theUfSurf1) < 0.0)
569 {//Interval [aU11, aU21] intersects theUfSurf1
570 return Standard_True;
571 }
572
573 if((aU11 - theUlSurf1)*(aU21 - theUlSurf1) < 0.0)
574 {//Interval [aU11, aU21] intersects theUlSurf1
575 return Standard_True;
576 }
577
578 if((aV11 - theVfSurf1)*(aV21 - theVfSurf1) < 0.0)
579 {//Interval [aV11, aV21] intersects theVfSurf1
580 return Standard_True;
581 }
582
583 if((aV11 - theVlSurf1)*(aV21 - theVlSurf1) < 0.0)
584 {//Interval [aV11, aV21] intersects theVlSurf1
585 return Standard_True;
586 }
587
588 if((aU12 - theUfSurf2)*(aU22 - theUfSurf2) < 0.0)
589 {//Interval [aU12, aU22] intersects theUfSurf2
590 return Standard_True;
591 }
592
593 if((aU12 - theUlSurf2)*(aU22 - theUlSurf2) < 0.0)
594 {//Interval [aU12, aU22] intersects theUlSurf2
595 return Standard_True;
596 }
597
598 if((aV12 - theVfSurf2)*(aV22 - theVfSurf2) < 0.0)
599 {//Interval [aV12, aV22] intersects theVfSurf2
600 return Standard_True;
601 }
602
603 if((aV12 - theVlSurf2)*(aV22 - theVlSurf2) < 0.0)
604 {//Interval [aV12, aV22] intersects theVlSurf2
605 return Standard_True;
606 }
607
b8f67cc2 608 if(IsOnPeriod(aU11, aU21, theU1Period))
4e14c88f 609 return Standard_True;
610
b8f67cc2 611 if(IsOnPeriod(aV11, aV21, theV1Period))
4e14c88f 612 return Standard_True;
613
b8f67cc2 614 if(IsOnPeriod(aU12, aU22, theU2Period))
4e14c88f 615 return Standard_True;
616
b8f67cc2 617 if(IsOnPeriod(aV12, aV22, theV2Period))
4e14c88f 618 return Standard_True;
619
620 /*
621 The segment [thePtf, thePtl] does not intersect the boundaries and
622 the seam-edge of the surfaces.
623 Nevertheless, following situation is possible:
624
625 seam or
626 bound
627 |
628 thePtf * |
629 |
630 * thePtmid
631 thePtl * |
632 |
633
634 This case must be processed, too.
635 */
636
637 Standard_Real aU1 = 0.0, aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
638 thePtmid.Parameters(aU1, aV1, aU2, aV2);
639
640 if(IsEqual(aU1, theUfSurf1) || IsEqual(aU1, theUlSurf1))
641 return Standard_True;
642
643 if(IsEqual(aU2, theUfSurf2) || IsEqual(aU2, theUlSurf2))
644 return Standard_True;
645
646 if(IsEqual(aV1, theVfSurf1) || IsEqual(aV1, theVlSurf1))
647 return Standard_True;
648
649 if(IsEqual(aV2, theVfSurf2) || IsEqual(aV2, theVlSurf2))
650 return Standard_True;
651
b8f67cc2 652 if(IsOnPeriod(aU1, aU1, theU1Period))
4e14c88f 653 return Standard_True;
654
b8f67cc2 655 if(IsOnPeriod(aU2, aU2, theU2Period))
4e14c88f 656 return Standard_True;
657
b8f67cc2 658 if(IsOnPeriod(aV1, aV1, theV1Period))
4e14c88f 659 return Standard_True;
660
b8f67cc2 661 if(IsOnPeriod(aV2, aV2, theV2Period))
4e14c88f 662 return Standard_True;
663
664 return Standard_False;
665}
666
eee615ad 667//=======================================================================
668//function : AbjustPeriodicToPrevPoint
669//purpose : Returns theCurrentParam in order to the distance betwen
670// theRefParam and theCurrentParam is less than 0.5*thePeriod.
671//=======================================================================
672static void AbjustPeriodicToPrevPoint(const Standard_Real theRefParam,
673 const Standard_Real thePeriod,
674 Standard_Real& theCurrentParam)
675{
676 if(thePeriod == 0.0)
677 return;
678
679 Standard_Real aDeltaPar = 2.0*(theRefParam - theCurrentParam);
680 const Standard_Real anIncr = Sign(thePeriod, aDeltaPar);
681 while(Abs(aDeltaPar) > thePeriod)
682 {
683 theCurrentParam += anIncr;
684 aDeltaPar = 2.0*(theRefParam-theCurrentParam);
685 }
686}
687
688//=======================================================================
689//function : IsIntersectionPoint
690//purpose : Returns True if thePmid is intersection point
691// between theS1 and theS2 with given tolerance.
692// In this case, parameters of thePmid on every quadric
693// will be recomputed and returned.
694//=======================================================================
695static Standard_Boolean IsIntersectionPoint(const gp_Pnt& thePmid,
696 const IntSurf_Quadric& theS1,
697 const IntSurf_Quadric& theS2,
698 const IntSurf_PntOn2S& theRefPt,
699 const Standard_Real theTol,
700 const Standard_Real theU1Period,
701 const Standard_Real theU2Period,
702 const Standard_Real theV1Period,
703 const Standard_Real theV2Period,
704 Standard_Real &theU1,
705 Standard_Real &theV1,
706 Standard_Real &theU2,
707 Standard_Real &theV2)
708{
709 Standard_Real aU1Ref = 0.0, aV1Ref = 0.0, aU2Ref = 0.0, aV2Ref = 0.0;
710 theRefPt.Parameters(aU1Ref, aV1Ref, aU2Ref, aV2Ref);
711 theS1.Parameters(thePmid, theU1, theV1);
712 theS2.Parameters(thePmid, theU2, theV2);
713
714 AbjustPeriodicToPrevPoint(aU1Ref, theU1Period, theU1);
715 AbjustPeriodicToPrevPoint(aV1Ref, theV1Period, theV1);
716 AbjustPeriodicToPrevPoint(aU2Ref, theU2Period, theU2);
717 AbjustPeriodicToPrevPoint(aV2Ref, theV2Period, theV2);
718
719 const gp_Pnt aP1(theS1.Value(theU1, theV1));
720 const gp_Pnt aP2(theS2.Value(theU2, theV2));
721
722 return (aP1.SquareDistance(aP2) <= theTol*theTol);
723}
724
725//=======================================================================
726//function : ExtendFirst
727//purpose : Adds thePOn2S to the begin of theWline
728//=======================================================================
729static void ExtendFirst(const Handle(IntPatch_WLine)& theWline,
b8f67cc2 730 const IntSurf_PntOn2S& theAddedPt)
eee615ad 731{
b8f67cc2 732 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
733 theAddedPt.Parameters(aU1, aV1, aU2, aV2);
eee615ad 734
b8f67cc2 735 if(theAddedPt.IsSame(theWline->Point(1), Precision::Confusion()))
736 {
737 theWline->Curve()->Value(1, theAddedPt);
738 for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
739 {
740 IntPatch_Point &aVert = theWline->ChangeVertex(i);
741 if(aVert.ParameterOnLine() != 1)
742 break;
eee615ad 743
b8f67cc2 744 aVert.SetParameters(aU1, aV1, aU2, aV2);
745 aVert.SetValue(theAddedPt.Value());
746 }
747
748 return;
749 }
eee615ad 750
b8f67cc2 751 theWline->Curve()->InsertBefore(1, theAddedPt);
eee615ad 752
b8f67cc2 753 for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
eee615ad 754 {
b8f67cc2 755 IntPatch_Point &aVert = theWline->ChangeVertex(i);
756
757 if(aVert.ParameterOnLine() == 1)
758 {
759 aVert.SetParameters(aU1, aV1, aU2, aV2);
760 aVert.SetValue(theAddedPt.Value());
761 }
762 else
763 {
764 aVert.SetParameter(aVert.ParameterOnLine()+1);
765 }
eee615ad 766 }
767}
768
769//=======================================================================
770//function : ExtendLast
771//purpose : Adds thePOn2S to the end of theWline
772//=======================================================================
773static void ExtendLast(const Handle(IntPatch_WLine)& theWline,
b8f67cc2 774 const IntSurf_PntOn2S& theAddedPt)
eee615ad 775{
b8f67cc2 776 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
777 theAddedPt.Parameters(aU1, aV1, aU2, aV2);
778
779 const Standard_Integer aNbPnts = theWline->NbPnts();
780 if(theAddedPt.IsSame(theWline->Point(aNbPnts), Precision::Confusion()))
781 {
782 theWline->Curve()->Value(aNbPnts, theAddedPt);
783 }
784 else
785 {
786 theWline->Curve()->Add(theAddedPt);
787 }
eee615ad 788
b8f67cc2 789 for(Standard_Integer i = theWline->NbVertex(); i >= 1; i--)
790 {
791 IntPatch_Point &aVert = theWline->ChangeVertex(i);
792 if(aVert.ParameterOnLine() != aNbPnts)
793 break;
eee615ad 794
b8f67cc2 795 aVert.SetParameters(aU1, aV1, aU2, aV2);
796 aVert.SetValue(theAddedPt.Value());
797 aVert.SetParameter(theWline->NbPnts());
798 }
799}
800
801//=========================================================================
802// function: IsOutOfDomain
803// purpose : Checks, if 2D-representation of thePOn2S is in surfaces domain,
804// defined by bounding-boxes theBoxS1 and theBoxS2
805//=========================================================================
806static Standard_Boolean IsOutOfDomain(const Bnd_Box2d& theBoxS1,
807 const Bnd_Box2d& theBoxS2,
808 const IntSurf_PntOn2S &thePOn2S,
809 const Standard_Real theU1Period,
810 const Standard_Real theU2Period,
811 const Standard_Real theV1Period,
812 const Standard_Real theV2Period)
813{
eee615ad 814 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
b8f67cc2 815 Standard_Real aU1min = 0.0, aU1max = 0.0, aV1min = 0.0, aV1max = 0.0;
816 Standard_Real aU2min = 0.0, aU2max = 0.0, aV2min = 0.0, aV2max = 0.0;
817
eee615ad 818 thePOn2S.Parameters(aU1, aV1, aU2, aV2);
819
b8f67cc2 820 theBoxS1.Get(aU1min, aV1min, aU1max, aV1max);
821 theBoxS2.Get(aU2min, aV2min, aU2max, aV2max);
822
823 aU1 = ElCLib::InPeriod(aU1, aU1min, aU1min + theU1Period);
824 aV1 = ElCLib::InPeriod(aV1, aV1min, aV1min + theV1Period);
825 aU2 = ElCLib::InPeriod(aU2, aU2min, aU2min + theU2Period);
826 aV2 = ElCLib::InPeriod(aV2, aV2min, aV2min + theV2Period);
827
828 return (theBoxS1.IsOut(gp_Pnt2d(aU1, aV1)) ||
829 theBoxS2.IsOut(gp_Pnt2d(aU2, aV2)));
830}
831
832//=======================================================================
833//function : CheckArguments
834//purpose : Check if extending is possible
835// (see IntPatch_WLineTool::ExtendTwoWlinesToEachOther)
836//=======================================================================
837static Standard_Boolean CheckArguments(const IntSurf_Quadric& theS1,
838 const IntSurf_Quadric& theS2,
839 const IntSurf_PntOn2S& thePtWL1,
840 const IntSurf_PntOn2S& thePtWL2,
841 IntSurf_PntOn2S& theNewPoint,
842 const gp_Vec& theVec1,
843 const gp_Vec& theVec2,
844 const gp_Vec& theVec3,
845 const Bnd_Box2d& theBoxS1,
846 const Bnd_Box2d& theBoxS2,
847 const Standard_Real theToler3D,
848 const Standard_Real theU1Period,
849 const Standard_Real theU2Period,
850 const Standard_Real theV1Period,
851 const Standard_Real theV2Period)
852{
853 const Standard_Real aMaxAngle = M_PI/6; //30 degree
854 const Standard_Real aSqToler = theToler3D*theToler3D;
855
856 if(theVec3.SquareMagnitude() <= aSqToler)
857 {
858 return Standard_False;
859 }
860
861 if((theVec1.Angle(theVec2) > aMaxAngle) ||
862 (theVec1.Angle(theVec3) > aMaxAngle) ||
863 (theVec2.Angle(theVec3) > aMaxAngle))
864 {
865 return Standard_False;
866 }
867
868 const gp_Pnt aPmid(0.5*(thePtWL1.Value().XYZ()+thePtWL2.Value().XYZ()));
869
870 Standard_Real aU1=0.0, aV1=0.0, aU2=0.0, aV2=0.0;
871
872 theBoxS1.Get(aU1, aV1, aU2, aV2);
873 const Standard_Real aU1f = aU1, aV1f = aV1;
874 theBoxS2.Get(aU1, aV1, aU2, aV2);
875 const Standard_Real aU2f = aU1, aV2f = aV1;
876
877 if(!IsIntersectionPoint(aPmid, theS1, theS2, thePtWL1, theToler3D,
878 theU1Period, theU2Period, theV1Period, theV2Period,
879 aU1, aV1, aU2, aV2))
880 {
881 return Standard_False;
882 }
883
884 theNewPoint.SetValue(aPmid, aU1, aV1, aU2, aV2);
885
886 if(IsOutOfDomain(theBoxS1, theBoxS2, theNewPoint,
887 theU1Period, theU2Period,
888 theV1Period, theV2Period))
889 {
890 return Standard_False;
891 }
892
893 Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
894 aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
895
896 thePtWL1.Parameters(aU11, aV11, aU21, aV21);
897 thePtWL2.Parameters(aU12, aV12, aU22, aV22);
898
899 if(IsOnPeriod(aU11 - aU1f, aU12 - aU1f, theU1Period) ||
900 IsOnPeriod(aV11 - aV1f, aV12 - aV1f, theV1Period) ||
901 IsOnPeriod(aU21 - aU2f, aU22 - aU2f, theU2Period) ||
902 IsOnPeriod(aV21 - aV2f, aV22 - aV2f, theV2Period))
903 {
904 return Standard_False;
905 }
906
907 return Standard_True;
908}
909
910//=======================================================================
911//function : ExtendTwoWLFirstFirst
912//purpose : Performs extending theWLine1 and theWLine2 through their
913// respecting start point.
914//=======================================================================
915static void ExtendTwoWLFirstFirst(const IntSurf_Quadric& theS1,
916 const IntSurf_Quadric& theS2,
917 const Handle(IntPatch_WLine)& theWLine1,
918 const Handle(IntPatch_WLine)& theWLine2,
919 const IntSurf_PntOn2S& thePtWL1,
920 const IntSurf_PntOn2S& thePtWL2,
921 const gp_Vec& theVec1,
922 const gp_Vec& theVec2,
923 const gp_Vec& theVec3,
924 const Bnd_Box2d& theBoxS1,
925 const Bnd_Box2d& theBoxS2,
926 const Standard_Real theToler3D,
927 const Standard_Real theU1Period,
928 const Standard_Real theU2Period,
929 const Standard_Real theV1Period,
930 const Standard_Real theV2Period,
931 unsigned int &theCheckResult,
932 Standard_Boolean &theHasBeenJoined)
933{
934 IntSurf_PntOn2S aPOn2S;
935 if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
936 theVec1, theVec2, theVec3,
937 theBoxS1, theBoxS2, theToler3D,
938 theU1Period, theU2Period, theV1Period, theV2Period))
939 {
940 return;
941 }
942
943 theCheckResult |= (IntPatchWT_DisFirstLast | IntPatchWT_DisLastFirst);
944
945 ExtendFirst(theWLine1, aPOn2S);
946 ExtendFirst(theWLine2, aPOn2S);
947
948 if(theHasBeenJoined)
949 return;
950
951 Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
952 while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
953 theWLine1->RemoveVertex(1);
954
955 aPrm = theWLine2->Vertex(1).ParameterOnLine();
956 while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
957 theWLine2->RemoveVertex(1);
958
959 const Standard_Integer aNbPts = theWLine2->NbPnts();
960 for(Standard_Integer aNPt = 2; aNPt <= aNbPts; aNPt++)
961 {
962 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
963 theWLine1->Curve()->InsertBefore(1, aPt);
964 }
965
966 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
967 {
968 IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
969 const Standard_Real aCurParam = aVert.ParameterOnLine();
970 aVert.SetParameter(aNbPts+aCurParam-1);
971 }
972
973 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
974 {
975 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
976 const Standard_Real aCurParam = aVert.ParameterOnLine();
977 aVert.SetParameter(aNbPts-aCurParam+1);
978 theWLine1->AddVertex(aVert, Standard_True);
979 }
980
981 theHasBeenJoined = Standard_True;
982}
983
984//=======================================================================
985//function : ExtendTwoWLFirstLast
986//purpose : Performs extending theWLine1 through its start point and theWLine2
987// through its end point.
988//=======================================================================
989static void ExtendTwoWLFirstLast(const IntSurf_Quadric& theS1,
990 const IntSurf_Quadric& theS2,
991 const Handle(IntPatch_WLine)& theWLine1,
992 const Handle(IntPatch_WLine)& theWLine2,
993 const IntSurf_PntOn2S& thePtWL1,
994 const IntSurf_PntOn2S& thePtWL2,
995 const gp_Vec& theVec1,
996 const gp_Vec& theVec2,
997 const gp_Vec& theVec3,
998 const Bnd_Box2d& theBoxS1,
999 const Bnd_Box2d& theBoxS2,
1000 const Standard_Real theToler3D,
1001 const Standard_Real theU1Period,
1002 const Standard_Real theU2Period,
1003 const Standard_Real theV1Period,
1004 const Standard_Real theV2Period,
1005 unsigned int &theCheckResult,
1006 Standard_Boolean &theHasBeenJoined)
1007{
1008 IntSurf_PntOn2S aPOn2S;
1009 if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1010 theVec1, theVec2, theVec3,
1011 theBoxS1, theBoxS2, theToler3D,
1012 theU1Period, theU2Period, theV1Period, theV2Period))
1013 {
1014 return;
1015 }
1016
1017 theCheckResult |= IntPatchWT_DisLastLast;
1018
1019 ExtendFirst(theWLine1, aPOn2S);
1020 ExtendLast (theWLine2, aPOn2S);
1021
1022 if(theHasBeenJoined)
1023 return;
1024
1025 Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
1026 while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
1027 theWLine1->RemoveVertex(1);
1028
1029 aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
1030 while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
1031 theWLine2->RemoveVertex(theWLine2->NbVertex());
1032
1033 const Standard_Integer aNbPts = theWLine2->NbPnts();
1034 for(Standard_Integer aNPt = aNbPts - 1; aNPt >= 1; aNPt--)
1035 {
1036 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1037 theWLine1->Curve()->InsertBefore(1, aPt);
1038 }
1039
1040 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
1041 {
1042 IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
1043 const Standard_Real aCurParam = aVert.ParameterOnLine();
1044 aVert.SetParameter(aNbPts+aCurParam-1);
1045 }
1046
1047 for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
1048 {
1049 const IntPatch_Point &aVert = theWLine2->Vertex(aNVtx);
1050 theWLine1->AddVertex(aVert, Standard_True);
1051 }
1052
1053 theHasBeenJoined = Standard_True;
1054}
1055
1056//=======================================================================
1057//function : ExtendTwoWLLastFirst
1058//purpose : Performs extending theWLine1 through its end point and theWLine2
1059// through its start point.
1060//=======================================================================
1061static void ExtendTwoWLLastFirst(const IntSurf_Quadric& theS1,
1062 const IntSurf_Quadric& theS2,
1063 const Handle(IntPatch_WLine)& theWLine1,
1064 const Handle(IntPatch_WLine)& theWLine2,
1065 const IntSurf_PntOn2S& thePtWL1,
1066 const IntSurf_PntOn2S& thePtWL2,
1067 const gp_Vec& theVec1,
1068 const gp_Vec& theVec2,
1069 const gp_Vec& theVec3,
1070 const Bnd_Box2d& theBoxS1,
1071 const Bnd_Box2d& theBoxS2,
1072 const Standard_Real theToler3D,
1073 const Standard_Real theU1Period,
1074 const Standard_Real theU2Period,
1075 const Standard_Real theV1Period,
1076 const Standard_Real theV2Period,
1077 unsigned int &theCheckResult,
1078 Standard_Boolean &theHasBeenJoined)
1079{
1080 IntSurf_PntOn2S aPOn2S;
1081 if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1082 theVec1, theVec2, theVec3,
1083 theBoxS1, theBoxS2, theToler3D,
1084 theU1Period, theU2Period, theV1Period, theV2Period))
1085 {
1086 return;
1087 }
1088
1089 theCheckResult |= IntPatchWT_DisLastLast;
1090
1091 ExtendLast (theWLine1, aPOn2S);
1092 ExtendFirst(theWLine2, aPOn2S);
1093
1094 if(theHasBeenJoined)
1095 {
1096 return;
1097 }
1098
1099 Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
1100 while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
1101 theWLine1->RemoveVertex(theWLine1->NbVertex());
1102
1103 aPrm = theWLine2->Vertex(1).ParameterOnLine();
1104 while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
1105 theWLine2->RemoveVertex(1);
1106
1107 const Standard_Integer aNbPts = theWLine1->NbPnts();
1108 for(Standard_Integer aNPt = 2; aNPt <= theWLine2->NbPnts(); aNPt++)
1109 {
1110 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1111 theWLine1->Curve()->Add(aPt);
1112 }
1113
1114 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
1115 {
1116 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1117 const Standard_Real aCurParam = aVert.ParameterOnLine();
1118 aVert.SetParameter(aNbPts+aCurParam-1);
1119 theWLine1->AddVertex(aVert, Standard_False);
1120 }
1121
1122 theHasBeenJoined = Standard_True;
1123}
1124
1125//=======================================================================
1126//function : ExtendTwoWLLastLast
1127//purpose :
1128//=======================================================================
1129static void ExtendTwoWLLastLast(const IntSurf_Quadric& theS1,
1130 const IntSurf_Quadric& theS2,
1131 const Handle(IntPatch_WLine)& theWLine1,
1132 const Handle(IntPatch_WLine)& theWLine2,
1133 const IntSurf_PntOn2S& thePtWL1,
1134 const IntSurf_PntOn2S& thePtWL2,
1135 const gp_Vec& theVec1,
1136 const gp_Vec& theVec2,
1137 const gp_Vec& theVec3,
1138 const Bnd_Box2d& theBoxS1,
1139 const Bnd_Box2d& theBoxS2,
1140 const Standard_Real theToler3D,
1141 const Standard_Real theU1Period,
1142 const Standard_Real theU2Period,
1143 const Standard_Real theV1Period,
1144 const Standard_Real theV2Period,
1145 unsigned int &/*theCheckResult*/,
1146 Standard_Boolean &theHasBeenJoined)
1147{
1148 IntSurf_PntOn2S aPOn2S;
1149 if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1150 theVec1, theVec2, theVec3,
1151 theBoxS1, theBoxS2, theToler3D,
1152 theU1Period, theU2Period, theV1Period, theV2Period))
1153 {
1154 return;
1155 }
1156
1157 //theCheckResult |= IntPatchWT_DisLastLast;
1158
1159 ExtendLast(theWLine1, aPOn2S);
1160 ExtendLast(theWLine2, aPOn2S);
1161
1162 if(theHasBeenJoined)
1163 return;
1164
1165 Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
1166 while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
1167 theWLine1->RemoveVertex(theWLine1->NbVertex());
1168
1169 aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
1170 while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
1171 theWLine2->RemoveVertex(theWLine2->NbVertex());
1172
1173 const Standard_Integer aNbPts = theWLine1->NbPnts() + theWLine2->NbPnts();
1174 for(Standard_Integer aNPt = theWLine2->NbPnts()-1; aNPt >= 1; aNPt--)
1175 {
1176 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1177 theWLine1->Curve()->Add(aPt);
1178 }
1179
1180 for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
1181 {
1182 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1183 const Standard_Real aCurParam = aVert.ParameterOnLine();
1184 aVert.SetParameter(aNbPts - aCurParam);
1185 theWLine1->AddVertex(aVert, Standard_False);
1186 }
1187
1188 theHasBeenJoined = Standard_True;
eee615ad 1189}
1190
4e14c88f 1191//=========================================================================
1192// function : ComputePurgedWLine
1193// purpose :
1194//=========================================================================
1195Handle(IntPatch_WLine) IntPatch_WLineTool::
1196 ComputePurgedWLine(const Handle(IntPatch_WLine) &theWLine,
1197 const Handle(Adaptor3d_HSurface) &theS1,
1198 const Handle(Adaptor3d_HSurface) &theS2,
1199 const Handle(Adaptor3d_TopolTool) &theDom1,
1200 const Handle(Adaptor3d_TopolTool) &theDom2)
1201{
1202 Standard_Integer i, k, v, nb, nbvtx;
1203 Handle(IntPatch_WLine) aResult;
1204 nbvtx = theWLine->NbVertex();
1205 nb = theWLine->NbPnts();
1206 if (nb==2)
1207 {
1208 const IntSurf_PntOn2S& p1 = theWLine->Point(1);
1209 const IntSurf_PntOn2S& p2 = theWLine->Point(2);
1210 if(p1.Value().IsEqual(p2.Value(), gp::Resolution()))
1211 return aResult;
1212 }
1213
1214 Handle(IntPatch_WLine) aLocalWLine;
1215 Handle(IntPatch_WLine) aTmpWLine = theWLine;
1216 Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
1217 aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
1218 for(i = 1; i <= nb; i++)
1219 aLineOn2S->Add(theWLine->Point(i));
1220
1221 for(v = 1; v <= nbvtx; v++)
1222 aLocalWLine->AddVertex(theWLine->Vertex(v));
1223
1224 // I: Delete equal points
1225 for(i = 1; i <= aLineOn2S->NbPoints(); i++)
1226 {
1227 Standard_Integer aStartIndex = i + 1;
1228 Standard_Integer anEndIndex = i + 5;
1229 nb = aLineOn2S->NbPoints();
1230 anEndIndex = (anEndIndex > nb) ? nb : anEndIndex;
1231
1232 if((aStartIndex > nb) || (anEndIndex <= 1))
1233 continue;
1234
1235 k = aStartIndex;
1236
1237 while(k <= anEndIndex)
1238 {
1239 if(i != k)
1240 {
1241 IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
1242 IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
1243
1244 Standard_Real UV[8];
1245 p1.Parameters(UV[0], UV[1], UV[2], UV[3]);
1246 p2.Parameters(UV[4], UV[5], UV[6], UV[7]);
1247
1248 Standard_Real aMax = Abs(UV[0]);
1249 for(Standard_Integer anIdx = 1; anIdx < 8; anIdx++)
1250 {
1251 if (aMax < Abs(UV[anIdx]))
1252 aMax = Abs(UV[anIdx]);
1253 }
1254
1255 if(p1.Value().IsEqual(p2.Value(), gp::Resolution()) ||
1256 Abs(UV[0] - UV[4]) + Abs(UV[1] - UV[5]) < 1.0e-16 * aMax ||
1257 Abs(UV[2] - UV[6]) + Abs(UV[3] - UV[7]) < 1.0e-16 * aMax )
1258 {
1259 aTmpWLine = aLocalWLine;
1260 aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
1261
1262 for(v = 1; v <= aTmpWLine->NbVertex(); v++)
1263 {
1264 IntPatch_Point aVertex = aTmpWLine->Vertex(v);
1265 Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
1266
1267 if(avertexindex >= k)
1268 {
1269 aVertex.SetParameter(aVertex.ParameterOnLine() - 1.);
1270 }
1271 aLocalWLine->AddVertex(aVertex);
1272 }
1273 aLineOn2S->RemovePoint(k);
1274 anEndIndex--;
1275 continue;
1276 }
1277 }
1278 k++;
1279 }
1280 }
1281
1282 if (aLineOn2S->NbPoints() <= 2)
1283 {
1284 if (aLineOn2S->NbPoints() == 2)
1285 return aLocalWLine;
1286 else
1287 return aResult;
1288 }
1289
1290 // Avoid purge in case of C0 continuity:
1291 // Intersection approximator may produce invalid curve after purge, example:
1292 // bugs modalg_5 bug24731.
1293 // Do not run purger when base number of points is too small.
1294 if (theS1->UContinuity() == GeomAbs_C0 ||
1295 theS1->VContinuity() == GeomAbs_C0 ||
1296 theS2->UContinuity() == GeomAbs_C0 ||
1297 theS2->VContinuity() == GeomAbs_C0 ||
1298 nb < aNbSingleBezier)
1299 {
1300 return aLocalWLine;
1301 }
1302
1303 // II: Delete out of borders points.
1304 Handle(IntPatch_WLine) aLocalWLineOuter =
1305 DeleteOuterPoints(aLocalWLine, theS1, theS2, theDom1, theDom2);
1306
1307 // III: Delete points by tube criteria.
1308 Handle(IntPatch_WLine) aLocalWLineTube =
1309 DeleteByTube(aLocalWLineOuter, theS1, theS2);
1310
1311 if(aLocalWLineTube->NbPnts() > 1)
1312 {
1313 aResult = aLocalWLineTube;
1314 }
1315 return aResult;
1316}
1317
1318
1319//=======================================================================
1320//function : JoinWLines
1321//purpose :
1322//=======================================================================
1323void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
1324 IntPatch_SequenceOfPoint& theSPnt,
1325 const Standard_Real theTol3D,
1326 const Standard_Real theU1Period,
1327 const Standard_Real theU2Period,
1328 const Standard_Real theV1Period,
1329 const Standard_Real theV2Period,
1330 const Standard_Real theUfSurf1,
1331 const Standard_Real theUlSurf1,
1332 const Standard_Real theVfSurf1,
1333 const Standard_Real theVlSurf1,
1334 const Standard_Real theUfSurf2,
1335 const Standard_Real theUlSurf2,
1336 const Standard_Real theVfSurf2,
1337 const Standard_Real theVlSurf2)
1338{
1339 if(theSlin.Length() == 0)
1340 return;
1341
1342 for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
1343 {
1344 Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine1)));
1345
1346 if(aWLine1.IsNull())
1347 {//We must have failed to join not-point-lines
1348 continue;
1349 }
1350
1351 const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
1352 const IntSurf_PntOn2S& aPntFW1 = aWLine1->Point(1);
1353 const IntSurf_PntOn2S& aPntLW1 = aWLine1->Point(aNbPntsWL1);
1354
1355 for(Standard_Integer aNPt = 1; aNPt <= theSPnt.Length(); aNPt++)
1356 {
1357 const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNPt).PntOn2S();
1358
1359 if( aPntCur.IsSame(aPntFW1, Precision::Confusion()) ||
1360 aPntCur.IsSame(aPntLW1, Precision::Confusion()))
1361 {
1362 theSPnt.Remove(aNPt);
1363 aNPt--;
1364 }
1365 }
1366
1367 Standard_Boolean hasBeenRemoved = Standard_False;
1368 for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1; aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
1369 {
1370 Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine2)));
1371
1372 if(aWLine2.IsNull())
1373 continue;
1374
1375 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1376
1377 const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
1378 const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
1379
1380 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1381 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1382
1383 if(aPntFWL1.IsSame(aPntFWL2, Precision::Confusion()))
1384 {
1385 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
1386 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
1387 if(!IsSeamOrBound(aPt1, aPt2, aPntFWL1, theU1Period, theU2Period,
1388 theV1Period, theV2Period, theUfSurf1, theUlSurf1,
1389 theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
1390 theVfSurf2, theVlSurf2))
1391 {
1392 aWLine1->ClearVertexes();
1393 for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
1394 {
1395 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1396 aWLine1->Curve()->InsertBefore(1, aPt);
1397 }
1398
1399 aWLine1->ComputeVertexParameters(theTol3D);
1400
1401 theSlin.Remove(aNumOfLine2);
1402 aNumOfLine2--;
1403 hasBeenRemoved = Standard_True;
1404
1405 continue;
1406 }
1407 }
1408
1409 if(aPntFWL1.IsSame(aPntLWL2, Precision::Confusion()))
1410 {
1411 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
1412 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
1413 if(!IsSeamOrBound(aPt1, aPt2, aPntFWL1, theU1Period, theU2Period,
1414 theV1Period, theV2Period, theUfSurf1, theUlSurf1,
1415 theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
1416 theVfSurf2, theVlSurf2))
1417 {
1418 aWLine1->ClearVertexes();
1419 for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
1420 {
1421 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1422 aWLine1->Curve()->InsertBefore(1, aPt);
1423 }
1424
1425 aWLine1->ComputeVertexParameters(theTol3D);
1426
1427 theSlin.Remove(aNumOfLine2);
1428 aNumOfLine2--;
1429 hasBeenRemoved = Standard_True;
1430
1431 continue;
1432 }
1433 }
1434
1435 if(aPntLWL1.IsSame(aPntFWL2, Precision::Confusion()))
1436 {
1437 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
1438 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
1439 if(!IsSeamOrBound(aPt1, aPt2, aPntLWL1, theU1Period, theU2Period,
1440 theV1Period, theV2Period, theUfSurf1, theUlSurf1,
1441 theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
1442 theVfSurf2, theVlSurf2))
1443 {
1444 aWLine1->ClearVertexes();
1445 for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
1446 {
1447 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1448 aWLine1->Curve()->Add(aPt);
1449 }
1450
1451 aWLine1->ComputeVertexParameters(theTol3D);
1452
1453 theSlin.Remove(aNumOfLine2);
1454 aNumOfLine2--;
1455 hasBeenRemoved = Standard_True;
1456
1457 continue;
1458 }
1459 }
1460
1461 if(aPntLWL1.IsSame(aPntLWL2, Precision::Confusion()))
1462 {
1463 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
1464 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
1465 if(!IsSeamOrBound(aPt1, aPt2, aPntLWL1, theU1Period, theU2Period,
1466 theV1Period, theV2Period, theUfSurf1, theUlSurf1,
1467 theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
1468 theVfSurf2, theVlSurf2))
1469 {
1470 aWLine1->ClearVertexes();
1471 for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
1472 {
1473 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1474 aWLine1->Curve()->Add(aPt);
1475 }
1476
1477 aWLine1->ComputeVertexParameters(theTol3D);
1478
1479 theSlin.Remove(aNumOfLine2);
1480 aNumOfLine2--;
1481 hasBeenRemoved = Standard_True;
1482
1483 continue;
1484 }
1485 }
1486 }
1487
1488 if(hasBeenRemoved)
1489 aNumOfLine1--;
1490 }
eee615ad 1491}
1492
1493//=======================================================================
1494//function : ExtendTwoWlinesToEachOther
b8f67cc2 1495//purpose : Performs extending theWLine1 and theWLine2 through their
1496// respecting end point.
eee615ad 1497//=======================================================================
1498void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& theSlin,
1499 const IntSurf_Quadric& theS1,
1500 const IntSurf_Quadric& theS2,
1501 const Standard_Real theToler3D,
1502 const Standard_Real theU1Period,
1503 const Standard_Real theU2Period,
1504 const Standard_Real theV1Period,
b8f67cc2 1505 const Standard_Real theV2Period,
1506 const Bnd_Box2d& theBoxS1,
1507 const Bnd_Box2d& theBoxS2)
eee615ad 1508{
1509 if(theSlin.Length() < 2)
1510 return;
1511
eee615ad 1512 gp_Vec aVec1, aVec2, aVec3;
1513
1514 for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
1515 {
1516 Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::
1517 DownCast(theSlin.Value(aNumOfLine1)));
1518
1519 if(aWLine1.IsNull())
1520 {//We must have failed to join not-point-lines
1521 continue;
1522 }
1523
1524 const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
1525
b8f67cc2 1526 if(aWLine1->Vertex(1).ParameterOnLine() != 1)
1527 continue;
1528
1529 if(aWLine1->Vertex(aWLine1->NbVertex()).ParameterOnLine() != aWLine1->NbPnts())
1530 continue;
1531
eee615ad 1532 for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1;
1533 aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
1534 {
1535 Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::
1536 DownCast(theSlin.Value(aNumOfLine2)));
1537
1538 if(aWLine2.IsNull())
1539 continue;
1540
b8f67cc2 1541 if(aWLine2->Vertex(1).ParameterOnLine() != 1)
1542 continue;
1543
1544 if(aWLine2->Vertex(aWLine2->NbVertex()).ParameterOnLine() != aWLine2->NbPnts())
1545 continue;
1546
eee615ad 1547 //Enable/Disable of some ckeck. Bit-mask is used for it.
1548 //E.g. if 1st point of aWLine1 matches with
1549 //1st point of aWLine2 then we do not need in check
1550 //1st point of aWLine1 and last point of aWLine2 etc.
eee615ad 1551 unsigned int aCheckResult = IntPatchWT_EnAll;
1552
b8f67cc2 1553 Standard_Boolean hasBeenJoined = Standard_False;
1554
eee615ad 1555 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1556
1557 const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
1558 const IntSurf_PntOn2S& aPntFp1WL1 = aWLine1->Point(2);
1559
1560 const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
1561 const IntSurf_PntOn2S& aPntLm1WL1 = aWLine1->Point(aNbPntsWL1-1);
1562
1563 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1564 const IntSurf_PntOn2S& aPntFp1WL2 = aWLine2->Point(2);
1565
1566 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1567 const IntSurf_PntOn2S& aPntLm1WL2 = aWLine2->Point(aNbPntsWL2-1);
1568
1569 //if(!(aCheckResult & IntPatchWT_DisFirstFirst))
1570 {// First/First
1571 aVec1.SetXYZ(aPntFp1WL1.Value().XYZ() - aPntFWL1.Value().XYZ());
1572 aVec2.SetXYZ(aPntFWL2.Value().XYZ() - aPntFp1WL2.Value().XYZ());
1573 aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntFWL2.Value().XYZ());
1574
b8f67cc2 1575 ExtendTwoWLFirstFirst(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntFWL2,
1576 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1577 theU1Period, theU2Period, theV1Period, theV2Period,
1578 aCheckResult, hasBeenJoined);
1579 }
eee615ad 1580
1581 if(!(aCheckResult & IntPatchWT_DisFirstLast))
1582 {// First/Last
1583 aVec1.SetXYZ(aPntFp1WL1.Value().XYZ() - aPntFWL1.Value().XYZ());
1584 aVec2.SetXYZ(aPntLWL2.Value().XYZ() - aPntLm1WL2.Value().XYZ());
1585 aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntLWL2.Value().XYZ());
1586
b8f67cc2 1587 ExtendTwoWLFirstLast(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntLWL2,
1588 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1589 theU1Period, theU2Period, theV1Period, theV2Period,
1590 aCheckResult, hasBeenJoined);
1591 }
eee615ad 1592
1593 if(!(aCheckResult & IntPatchWT_DisLastFirst))
1594 {// Last/First
1595 aVec1.SetXYZ(aPntLWL1.Value().XYZ() - aPntLm1WL1.Value().XYZ());
1596 aVec2.SetXYZ(aPntFp1WL2.Value().XYZ() - aPntFWL2.Value().XYZ());
1597 aVec3.SetXYZ(aPntFWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
1598
b8f67cc2 1599 ExtendTwoWLLastFirst(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntFWL2,
1600 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1601 theU1Period, theU2Period, theV1Period, theV2Period,
1602 aCheckResult, hasBeenJoined);
1603 }
eee615ad 1604
1605 if(!(aCheckResult & IntPatchWT_DisLastLast))
1606 {// Last/Last
1607 aVec1.SetXYZ(aPntLWL1.Value().XYZ() - aPntLm1WL1.Value().XYZ());
1608 aVec2.SetXYZ(aPntLm1WL2.Value().XYZ() - aPntLWL2.Value().XYZ());
1609 aVec3.SetXYZ(aPntLWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
1610
b8f67cc2 1611 ExtendTwoWLLastLast(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntLWL2,
1612 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1613 theU1Period, theU2Period, theV1Period, theV2Period,
1614 aCheckResult, hasBeenJoined);
1615 }
1616
1617 if(hasBeenJoined)
1618 {
1619 theSlin.Remove(aNumOfLine2);
1620 aNumOfLine2--;
1621 }
eee615ad 1622 }
1623 }
1624}