0026708: Fix shape did not fix attached shape. Seam edge was not added to the attache...
[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>
18
19//=======================================================================
20//function : MinMax
21//purpose : Replaces theParMIN = MIN(theParMIN, theParMAX),
22// theParMAX = MAX(theParMIN, theParMAX).
23//
24// Static subfunction in IsSeamOrBound.
25//=======================================================================
26static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
27{
28 if(theParMIN > theParMAX)
29 {
30 const Standard_Real aTmp = theParMAX;
31 theParMAX = theParMIN;
32 theParMIN = aTmp;
33 }
34}
35
36//=========================================================================
37// function : FillPointsHash
38// purpose : Fill points hash by input data.
39// Static subfunction in ComputePurgedWLine.
40//=========================================================================
41static void FillPointsHash(const Handle(IntPatch_WLine) &theWLine,
42 NCollection_Array1<Standard_Integer> &thePointsHash)
43{
44 // 1 - Delete point.
45 // 0 - Store point.
46 // -1 - Vertex point (not delete).
47 Standard_Integer i, v;
48
49 for(i = 1; i <= theWLine->NbPnts(); i++)
50 thePointsHash.SetValue(i, 0);
51
52 for(v = 1; v <= theWLine->NbVertex(); v++)
53 {
54 IntPatch_Point aVertex = theWLine->Vertex(v);
55 Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
56 thePointsHash.SetValue(avertexindex, -1);
57 }
58}
59
60//=========================================================================
61// function : MakeNewWLine
62// purpose : Makes new walking line according to the points hash
63// Static subfunction in ComputePurgedWLine and DeleteOuter.
64//=========================================================================
65static Handle(IntPatch_WLine) MakeNewWLine(const Handle(IntPatch_WLine) &theWLine,
66 const NCollection_Array1<Standard_Integer> &thePointsHash)
67{
68 Standard_Integer i;
69
70 Handle(IntSurf_LineOn2S) aPurgedLineOn2S = new IntSurf_LineOn2S();
71 Handle(IntPatch_WLine) aLocalWLine = new IntPatch_WLine(aPurgedLineOn2S, Standard_False);
72 Standard_Integer anOldLineIdx = 1, aVertexIdx = 1;
73 for(i = 1; i <= thePointsHash.Upper(); i++)
74 {
75 if (thePointsHash(i) == 0)
76 {
77 // Store this point.
78 aPurgedLineOn2S->Add(theWLine->Point(i));
79 anOldLineIdx++;
80 }
81 else if (thePointsHash(i) == -1)
82 {
83 // Add vertex.
84 IntPatch_Point aVertex = theWLine->Vertex(aVertexIdx++);
85 aVertex.SetParameter(anOldLineIdx++);
86 aLocalWLine->AddVertex(aVertex);
87 aPurgedLineOn2S->Add(theWLine->Point(i));
88 }
89 }
90
91 return aLocalWLine;
92}
93
94//=========================================================================
95// function : MovePoint
96// purpose : Move point into surface param space. No interpolation used
97// because walking algorithm should care for closeness to the param space.
98// Static subfunction in ComputePurgedWLine.
99//=========================================================================
100static void MovePoint(const Handle(Adaptor3d_HSurface) &theS1,
101 Standard_Real &U1, Standard_Real &V1)
102{
103 if (U1 < theS1->FirstUParameter())
104 U1 = theS1->FirstUParameter();
105
106 if (U1 > theS1->LastUParameter())
107 U1 = theS1->LastUParameter();
108
109 if (V1 < theS1->FirstVParameter())
110 V1 = theS1->FirstVParameter();
111
112 if (V1 > theS1->LastVParameter())
113 V1 = theS1->LastVParameter();
114}
115
116//=========================================================================
117// function : DeleteOuterPoints
118// purpose : Check and delete out of bounds points on walking line.
119// Static subfunction in ComputePurgedWLine.
120//=========================================================================
121static Handle(IntPatch_WLine)
122 DeleteOuterPoints(const Handle(IntPatch_WLine) &theWLine,
123 const Handle(Adaptor3d_HSurface) &theS1,
124 const Handle(Adaptor3d_HSurface) &theS2,
125 const Handle(Adaptor3d_TopolTool) &theDom1,
126 const Handle(Adaptor3d_TopolTool) &theDom2)
127{
128 Standard_Integer i;
129
130 NCollection_Array1<Standard_Integer> aDelOuterPointsHash(1, theWLine->NbPnts());
131 FillPointsHash(theWLine, aDelOuterPointsHash);
132
133 if (theS1->IsUPeriodic() || theS1->IsVPeriodic() ||
134 theS2->IsUPeriodic() || theS2->IsVPeriodic() )
135 return theWLine;
136
137 gp_Pnt2d aPntOnF1, aPntOnF2;
138 Standard_Real aX1, aY1, aX2, aY2;
139
140 // Iterate over points in walking line and delete which are out of bounds.
141 // Forward.
142 Standard_Boolean isAllDeleted = Standard_True;
143 Standard_Boolean aChangedFirst = Standard_False;
144 Standard_Integer aFirstGeomIdx = 1;
145 for(i = 1; i <= theWLine->NbPnts(); i++)
146 {
147 theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
148 aPntOnF1.SetCoord(aX1, aY1);
149 aPntOnF2.SetCoord(aX2, aY2);
150
151 TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
152 TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
153
154 if (aState1 == TopAbs_OUT ||
155 aState2 == TopAbs_OUT )
156 {
157 aDelOuterPointsHash(i) = 1;
158 aChangedFirst = Standard_True;
159 }
160 else
161 {
162 isAllDeleted = Standard_False;
163
164 aFirstGeomIdx = Max (i - 1, 1);
165 if (aDelOuterPointsHash(i) == -1)
166 aFirstGeomIdx = i; // Use data what lies in (i) point / vertex.
167
168 aDelOuterPointsHash(i) = -1;
169 break;
170 }
171 }
172
173 if (isAllDeleted)
174 {
175 // ALL points are out of bounds:
176 // case boolean bcut_complex F5 and similar.
177 return theWLine;
178 }
179
180 // Backward.
181 Standard_Boolean aChangedLast = Standard_False;
182 Standard_Integer aLastGeomIdx = theWLine->NbPnts();
183 for(i = theWLine->NbPnts(); i >= 1; i--)
184 {
185 theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
186 aPntOnF1.SetCoord(aX1, aY1);
187 aPntOnF2.SetCoord(aX2, aY2);
188
189 TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
190 TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
191
192 if (aState1 == TopAbs_OUT ||
193 aState2 == TopAbs_OUT )
194 {
195 aDelOuterPointsHash(i) = 1;
196 aChangedLast = Standard_True; // Move vertex to first good point
197 }
198 else
199 {
200 aLastGeomIdx = Min (i + 1, theWLine->NbPnts());
201 if (aDelOuterPointsHash(i) == -1)
202 aLastGeomIdx = i; // Use data what lies in (i) point / vertex.
203
204 aDelOuterPointsHash(i) = -1;
205 break;
206 }
207 }
208
209 if (!aChangedFirst && !aChangedLast)
210 {
211 // Nothing is done, return input.
212 return theWLine;
213 }
214
215 // Build new line and modify geometry of necessary vertexes.
216 Handle(IntPatch_WLine) aLocalWLine = MakeNewWLine(theWLine, aDelOuterPointsHash);
217
218 if (aChangedFirst)
219 {
220 // Vertex geometry.
221 IntPatch_Point aVertex = aLocalWLine->Vertex(1);
222 aVertex.SetValue(theWLine->Point(aFirstGeomIdx).Value());
223 Standard_Real aU1, aU2, aV1, aV2;
224 theWLine->Point(aFirstGeomIdx).Parameters(aU1, aV1, aU2, aV2);
225 MovePoint(theS1, aU1, aV1);
226 MovePoint(theS2, aU2, aV2);
227 aVertex.SetParameters(aU1, aV1, aU2, aV2);
228 aLocalWLine->Replace(1, aVertex);
229 // Change point in walking line.
230 aLocalWLine->SetPoint(1, aVertex);
231 }
232
233 if (aChangedLast)
234 {
235 // Vertex geometry.
236 IntPatch_Point aVertex = aLocalWLine->Vertex(aLocalWLine->NbVertex());
237 aVertex.SetValue(theWLine->Point(aLastGeomIdx).Value());
238 Standard_Real aU1, aU2, aV1, aV2;
239 theWLine->Point(aLastGeomIdx).Parameters(aU1, aV1, aU2, aV2);
240 MovePoint(theS1, aU1, aV1);
241 MovePoint(theS2, aU2, aV2);
242 aVertex.SetParameters(aU1, aV1, aU2, aV2);
243 aLocalWLine->Replace(aLocalWLine->NbVertex(), aVertex);
244 // Change point in walking line.
245 aLocalWLine->SetPoint(aLocalWLine->NbPnts(), aVertex);
246 }
247
248
249 return aLocalWLine;
250}
251
252//=========================================================================
253// function : IsInsideIn2d
254// purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
255// In 2d space. Static subfunction in DeleteByTube.
256//=========================================================================
257static Standard_Boolean IsInsideIn2d(const gp_Pnt2d& aBasePnt,
258 const gp_Vec2d& aBaseVec,
259 const gp_Pnt2d& aNextPnt,
260 const Standard_Real aSquareMaxDist)
261{
262 gp_Vec2d aVec2d(aBasePnt, aNextPnt);
263
264 //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
265 Standard_Real aCross = aVec2d.Crossed(aBaseVec);
266 Standard_Real aSquareDist = aCross * aCross
267 / aBaseVec.SquareMagnitude();
268
269 return (aSquareDist <= aSquareMaxDist);
270}
271
272//=========================================================================
273// function : IsInsideIn3d
274// purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
275// In 3d space. Static subfunction in DeleteByTube.
276//=========================================================================
277static Standard_Boolean IsInsideIn3d(const gp_Pnt& aBasePnt,
278 const gp_Vec& aBaseVec,
279 const gp_Pnt& aNextPnt,
280 const Standard_Real aSquareMaxDist)
281{
282 gp_Vec aVec(aBasePnt, aNextPnt);
283
284 //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
285 Standard_Real aSquareDist = aVec.CrossSquareMagnitude(aBaseVec)
286 / aBaseVec.SquareMagnitude();
287
288 return (aSquareDist <= aSquareMaxDist);
289}
290
291static const Standard_Integer aMinNbBadDistr = 15;
292static const Standard_Integer aNbSingleBezier = 30;
293
294//=========================================================================
295// function : DeleteByTube
296// purpose : Check and delete points using tube criteria.
297// Static subfunction in ComputePurgedWLine.
298//=========================================================================
299static Handle(IntPatch_WLine)
300 DeleteByTube(const Handle(IntPatch_WLine) &theWLine,
301 const Handle(Adaptor3d_HSurface) &theS1,
302 const Handle(Adaptor3d_HSurface) &theS2)
303{
304 // III: Check points for tube criteria:
305 // Workaround to handle case of small amount points after purge.
306 // Test "boolean boptuc_complex B5" and similar.
307 Standard_Integer aNbPnt = 0 , i;
308
309 if (theWLine->NbPnts() <= 2)
310 return theWLine;
311
312 NCollection_Array1<Standard_Integer> aNewPointsHash(1, theWLine->NbPnts());
313 FillPointsHash(theWLine, aNewPointsHash);
314
315 // Inital computations.
316 Standard_Real UonS1[3], VonS1[3], UonS2[3], VonS2[3];
317 theWLine->Point(1).ParametersOnS1(UonS1[0], VonS1[0]);
318 theWLine->Point(2).ParametersOnS1(UonS1[1], VonS1[1]);
319 theWLine->Point(1).ParametersOnS2(UonS2[0], VonS2[0]);
320 theWLine->Point(2).ParametersOnS2(UonS2[1], VonS2[1]);
321
322 gp_Pnt2d aBase2dPnt1(UonS1[0], VonS1[0]);
323 gp_Pnt2d aBase2dPnt2(UonS2[0], VonS2[0]);
324 gp_Vec2d aBase2dVec1(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
325 gp_Vec2d aBase2dVec2(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
326 gp_Pnt aBase3dPnt = theWLine->Point(1).Value();
327 gp_Vec aBase3dVec(theWLine->Point(1).Value(), theWLine->Point(2).Value());
328
329 // Choose base tolerance and scale it to pipe algorithm.
330 const Standard_Real aBaseTolerance = Precision::Approximation();
331 Standard_Real aResS1Tol = Min(theS1->UResolution(aBaseTolerance),
332 theS1->VResolution(aBaseTolerance));
333 Standard_Real aResS2Tol = Min(theS2->UResolution(aBaseTolerance),
334 theS2->VResolution(aBaseTolerance));
335 Standard_Real aTol1 = aResS1Tol * aResS1Tol;
336 Standard_Real aTol2 = aResS2Tol * aResS2Tol;
337 Standard_Real aTol3d = aBaseTolerance * aBaseTolerance;
338
339 const Standard_Real aLimitCoeff = 0.99 * 0.99;
340 for(i = 3; i <= theWLine->NbPnts(); i++)
341 {
342 Standard_Boolean isDeleteState = Standard_False;
343
344 theWLine->Point(i).ParametersOnS1(UonS1[2], VonS1[2]);
345 theWLine->Point(i).ParametersOnS2(UonS2[2], VonS2[2]);
346 gp_Pnt2d aPnt2dOnS1(UonS1[2], VonS1[2]);
347 gp_Pnt2d aPnt2dOnS2(UonS2[2], VonS2[2]);
348 const gp_Pnt& aPnt3d = theWLine->Point(i).Value();
349
350 if (aNewPointsHash(i - 1) != - 1 &&
351 IsInsideIn2d(aBase2dPnt1, aBase2dVec1, aPnt2dOnS1, aTol1) &&
352 IsInsideIn2d(aBase2dPnt2, aBase2dVec2, aPnt2dOnS2, aTol2) &&
353 IsInsideIn3d(aBase3dPnt, aBase3dVec, aPnt3d, aTol3d) )
354 {
355 // Handle possible uneven parametrization on one of 2d subspaces.
356 // Delete point only when expected lengths are close to each other (aLimitCoeff).
357 // Example:
358 // c2d1 - line
359 // c3d - line
360 // c2d2 - geometrically line, but have uneven parametrization -> c2d2 is bspline.
361 gp_XY aPntOnS1[2]= { gp_XY(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0])
362 , gp_XY(UonS1[2] - UonS1[1], VonS1[2] - VonS1[1])};
363 gp_XY aPntOnS2[2]= { gp_XY(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0])
364 , gp_XY(UonS2[2] - UonS2[1], VonS2[2] - VonS2[1])};
365
366 Standard_Real aStepOnS1 = aPntOnS1[0].SquareModulus() / aPntOnS1[1].SquareModulus();
367 Standard_Real aStepOnS2 = aPntOnS2[0].SquareModulus() / aPntOnS2[1].SquareModulus();
368
369 Standard_Real aStepCoeff = Min(aStepOnS1, aStepOnS2) / Max(aStepOnS1, aStepOnS2);
370
371 if (aStepCoeff > aLimitCoeff)
372 {
373 // Set hash flag to "Delete" state.
374 isDeleteState = Standard_True;
375 aNewPointsHash.SetValue(i - 1, 1);
376
377 // Change middle point.
378 UonS1[1] = UonS1[2];
379 UonS2[1] = UonS2[2];
380 VonS1[1] = VonS1[2];
381 VonS2[1] = VonS2[2];
382 }
383 }
384
385 if (!isDeleteState)
386 {
387 // Compute new pipe parameters.
388 UonS1[0] = UonS1[1];
389 VonS1[0] = VonS1[1];
390 UonS2[0] = UonS2[1];
391 VonS2[0] = VonS2[1];
392
393 UonS1[1] = UonS1[2];
394 VonS1[1] = VonS1[2];
395 UonS2[1] = UonS2[2];
396 VonS2[1] = VonS2[2];
397
398 aBase2dPnt1.SetCoord(UonS1[0], VonS1[0]);
399 aBase2dPnt2.SetCoord(UonS2[0], VonS2[0]);
400 aBase2dVec1.SetCoord(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
401 aBase2dVec2.SetCoord(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
402 aBase3dPnt = theWLine->Point(i - 1).Value();
403 aBase3dVec = gp_Vec(theWLine->Point(i - 1).Value(), theWLine->Point(i).Value());
404
405 aNbPnt++;
406 }
407 }
408
409 // Workaround to handle case of small amount of points after purge.
410 // Test "boolean boptuc_complex B5" and similar.
411 // This is possible since there are at least two points.
412 if (aNewPointsHash(1) == -1 &&
413 aNewPointsHash(2) == -1 &&
414 aNbPnt <= 3)
415 {
416 // Delete first.
417 aNewPointsHash(1) = 1;
418 }
419 if (aNewPointsHash(theWLine->NbPnts() - 1) == -1 &&
420 aNewPointsHash(theWLine->NbPnts() ) == -1 &&
421 aNbPnt <= 3)
422 {
423 // Delete last.
424 aNewPointsHash(theWLine->NbPnts()) = 1;
425 }
426
427 // Purgre when too small amount of points left.
428 if (aNbPnt <= 2)
429 {
430 for(i = aNewPointsHash.Lower(); i <= aNewPointsHash.Upper(); i++)
431 {
432 if (aNewPointsHash(i) != -1)
433 {
434 aNewPointsHash(i) = 1;
435 }
436 }
437 }
438
439 // Handle possible bad distribution of points,
440 // which are will converted into one single bezier curve (less than 30 points).
441 // Make distribution more even:
442 // max step will be nearly to 0.1 of param distance.
443 if (aNbPnt + 2 > aMinNbBadDistr &&
444 aNbPnt + 2 < aNbSingleBezier )
445 {
446 for(Standard_Integer anIdx = 1; anIdx <= 8; anIdx++)
447 {
448 Standard_Integer aHashIdx =
449 Standard_Integer(anIdx * theWLine->NbPnts() / 9);
450
451 //Store this point.
452 aNewPointsHash(aHashIdx) = 0;
453 }
454 }
455
456 return MakeNewWLine(theWLine, aNewPointsHash);
457}
458
459//=======================================================================
460//function : IsSeam
461//purpose : Returns:
462// 0 - if interval [theU1, theU2] does not intersect the "seam-edge"
463// or if "seam-edge" do not exist;
464// 1 - if interval (theU1, theU2) intersect the "seam-edge".
465// 2 - if theU1 or/and theU2 lie ON the "seam-edge"
466//
467//ATTENTION!!!
468// If (theU1 == theU2) then this function will return only both 0 or 2.
469//
470// Static subfunction in IsSeamOrBound.
471//=======================================================================
472static Standard_Integer IsSeam( const Standard_Real theU1,
473 const Standard_Real theU2,
474 const Standard_Real thePeriod)
475{
476 if(IsEqual(thePeriod, 0.0))
477 return 0;
478
479 //If interval [theU1, theU2] intersect seam-edge then there exists an integer
480 //number N such as
481 // (theU1 <= T*N <= theU2) <=> (theU1/T <= N <= theU2/T),
482 //where T is the period.
483 //I.e. the inerval [theU1/T, theU2/T] must contain at least one
484 //integer number. In this case, Floor(theU1/T) and Floor(theU2/T)
485 //return different values or theU1/T is strictly integer number.
486 //Examples:
487 // 1. theU1/T==2.8, theU2/T==3.5 => Floor(theU1/T) == 2, Floor(theU2/T) == 3.
488 // 2. theU1/T==2.0, theU2/T==2.6 => Floor(theU1/T) == Floor(theU2/T) == 2.
489
490 const Standard_Real aVal1 = theU1/thePeriod,
491 aVal2 = theU2/thePeriod;
492 const Standard_Integer aPar1 = static_cast<Standard_Integer>(Floor(aVal1));
493 const Standard_Integer aPar2 = static_cast<Standard_Integer>(Floor(aVal2));
494 if(aPar1 != aPar2)
495 {//Interval (theU1, theU2] intersects seam-edge
496 if(IsEqual(aVal2, static_cast<Standard_Real>(aPar2)))
497 {//aVal2 is an integer number => theU2 lies ON the "seam-edge"
498 return 2;
499 }
500
501 return 1;
502 }
503
504 //Here, aPar1 == aPar2.
505
506 if(IsEqual(aVal1, static_cast<Standard_Real>(aPar1)))
507 {//aVal1 is an integer number => theU1 lies ON the "seam-edge"
508 return 2;
509 }
510
511 //If aVal2 is a true integer number then always (aPar1 != aPar2).
512
513 return 0;
514}
515
516//=======================================================================
517//function : IsSeamOrBound
518//purpose : Returns TRUE if segment [thePtf, thePtl] intersects "seam-edge"
519// (if it exist) or surface boundaries and both thePtf and thePtl do
520// not match "seam-edge" or boundaries.
521// Point thePtmid lies in this segment. If thePtmid match
522// "seam-edge" or boundaries strictly (without any tolerance) then
523// the function will return TRUE.
524// See comments in function body for detail information.
525//
526// Static subfunction in JoinWLines.
527//=======================================================================
528static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
529 const IntSurf_PntOn2S& thePtl,
530 const IntSurf_PntOn2S& thePtmid,
531 const Standard_Real theU1Period,
532 const Standard_Real theU2Period,
533 const Standard_Real theV1Period,
534 const Standard_Real theV2Period,
535 const Standard_Real theUfSurf1,
536 const Standard_Real theUlSurf1,
537 const Standard_Real theVfSurf1,
538 const Standard_Real theVlSurf1,
539 const Standard_Real theUfSurf2,
540 const Standard_Real theUlSurf2,
541 const Standard_Real theVfSurf2,
542 const Standard_Real theVlSurf2)
543{
544 Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0;
545 Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0;
546 thePtf.Parameters(aU11, aV11, aU12, aV12);
547 thePtl.Parameters(aU21, aV21, aU22, aV22);
548
549 MinMax(aU11, aU21);
550 MinMax(aV11, aV21);
551 MinMax(aU12, aU22);
552 MinMax(aV12, aV22);
553
554 if((aU11 - theUfSurf1)*(aU21 - theUfSurf1) < 0.0)
555 {//Interval [aU11, aU21] intersects theUfSurf1
556 return Standard_True;
557 }
558
559 if((aU11 - theUlSurf1)*(aU21 - theUlSurf1) < 0.0)
560 {//Interval [aU11, aU21] intersects theUlSurf1
561 return Standard_True;
562 }
563
564 if((aV11 - theVfSurf1)*(aV21 - theVfSurf1) < 0.0)
565 {//Interval [aV11, aV21] intersects theVfSurf1
566 return Standard_True;
567 }
568
569 if((aV11 - theVlSurf1)*(aV21 - theVlSurf1) < 0.0)
570 {//Interval [aV11, aV21] intersects theVlSurf1
571 return Standard_True;
572 }
573
574 if((aU12 - theUfSurf2)*(aU22 - theUfSurf2) < 0.0)
575 {//Interval [aU12, aU22] intersects theUfSurf2
576 return Standard_True;
577 }
578
579 if((aU12 - theUlSurf2)*(aU22 - theUlSurf2) < 0.0)
580 {//Interval [aU12, aU22] intersects theUlSurf2
581 return Standard_True;
582 }
583
584 if((aV12 - theVfSurf2)*(aV22 - theVfSurf2) < 0.0)
585 {//Interval [aV12, aV22] intersects theVfSurf2
586 return Standard_True;
587 }
588
589 if((aV12 - theVlSurf2)*(aV22 - theVlSurf2) < 0.0)
590 {//Interval [aV12, aV22] intersects theVlSurf2
591 return Standard_True;
592 }
593
594 if(IsSeam(aU11, aU21, theU1Period))
595 return Standard_True;
596
597 if(IsSeam(aV11, aV21, theV1Period))
598 return Standard_True;
599
600 if(IsSeam(aU12, aU22, theU2Period))
601 return Standard_True;
602
603 if(IsSeam(aV12, aV22, theV2Period))
604 return Standard_True;
605
606 /*
607 The segment [thePtf, thePtl] does not intersect the boundaries and
608 the seam-edge of the surfaces.
609 Nevertheless, following situation is possible:
610
611 seam or
612 bound
613 |
614 thePtf * |
615 |
616 * thePtmid
617 thePtl * |
618 |
619
620 This case must be processed, too.
621 */
622
623 Standard_Real aU1 = 0.0, aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
624 thePtmid.Parameters(aU1, aV1, aU2, aV2);
625
626 if(IsEqual(aU1, theUfSurf1) || IsEqual(aU1, theUlSurf1))
627 return Standard_True;
628
629 if(IsEqual(aU2, theUfSurf2) || IsEqual(aU2, theUlSurf2))
630 return Standard_True;
631
632 if(IsEqual(aV1, theVfSurf1) || IsEqual(aV1, theVlSurf1))
633 return Standard_True;
634
635 if(IsEqual(aV2, theVfSurf2) || IsEqual(aV2, theVlSurf2))
636 return Standard_True;
637
638 if(IsSeam(aU1, aU1, theU1Period))
639 return Standard_True;
640
641 if(IsSeam(aU2, aU2, theU2Period))
642 return Standard_True;
643
644 if(IsSeam(aV1, aV1, theV1Period))
645 return Standard_True;
646
647 if(IsSeam(aV2, aV2, theV2Period))
648 return Standard_True;
649
650 return Standard_False;
651}
652
653//=========================================================================
654// function : ComputePurgedWLine
655// purpose :
656//=========================================================================
657Handle(IntPatch_WLine) IntPatch_WLineTool::
658 ComputePurgedWLine(const Handle(IntPatch_WLine) &theWLine,
659 const Handle(Adaptor3d_HSurface) &theS1,
660 const Handle(Adaptor3d_HSurface) &theS2,
661 const Handle(Adaptor3d_TopolTool) &theDom1,
662 const Handle(Adaptor3d_TopolTool) &theDom2)
663{
664 Standard_Integer i, k, v, nb, nbvtx;
665 Handle(IntPatch_WLine) aResult;
666 nbvtx = theWLine->NbVertex();
667 nb = theWLine->NbPnts();
668 if (nb==2)
669 {
670 const IntSurf_PntOn2S& p1 = theWLine->Point(1);
671 const IntSurf_PntOn2S& p2 = theWLine->Point(2);
672 if(p1.Value().IsEqual(p2.Value(), gp::Resolution()))
673 return aResult;
674 }
675
676 Handle(IntPatch_WLine) aLocalWLine;
677 Handle(IntPatch_WLine) aTmpWLine = theWLine;
678 Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
679 aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
680 for(i = 1; i <= nb; i++)
681 aLineOn2S->Add(theWLine->Point(i));
682
683 for(v = 1; v <= nbvtx; v++)
684 aLocalWLine->AddVertex(theWLine->Vertex(v));
685
686 // I: Delete equal points
687 for(i = 1; i <= aLineOn2S->NbPoints(); i++)
688 {
689 Standard_Integer aStartIndex = i + 1;
690 Standard_Integer anEndIndex = i + 5;
691 nb = aLineOn2S->NbPoints();
692 anEndIndex = (anEndIndex > nb) ? nb : anEndIndex;
693
694 if((aStartIndex > nb) || (anEndIndex <= 1))
695 continue;
696
697 k = aStartIndex;
698
699 while(k <= anEndIndex)
700 {
701 if(i != k)
702 {
703 IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
704 IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
705
706 Standard_Real UV[8];
707 p1.Parameters(UV[0], UV[1], UV[2], UV[3]);
708 p2.Parameters(UV[4], UV[5], UV[6], UV[7]);
709
710 Standard_Real aMax = Abs(UV[0]);
711 for(Standard_Integer anIdx = 1; anIdx < 8; anIdx++)
712 {
713 if (aMax < Abs(UV[anIdx]))
714 aMax = Abs(UV[anIdx]);
715 }
716
717 if(p1.Value().IsEqual(p2.Value(), gp::Resolution()) ||
718 Abs(UV[0] - UV[4]) + Abs(UV[1] - UV[5]) < 1.0e-16 * aMax ||
719 Abs(UV[2] - UV[6]) + Abs(UV[3] - UV[7]) < 1.0e-16 * aMax )
720 {
721 aTmpWLine = aLocalWLine;
722 aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
723
724 for(v = 1; v <= aTmpWLine->NbVertex(); v++)
725 {
726 IntPatch_Point aVertex = aTmpWLine->Vertex(v);
727 Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
728
729 if(avertexindex >= k)
730 {
731 aVertex.SetParameter(aVertex.ParameterOnLine() - 1.);
732 }
733 aLocalWLine->AddVertex(aVertex);
734 }
735 aLineOn2S->RemovePoint(k);
736 anEndIndex--;
737 continue;
738 }
739 }
740 k++;
741 }
742 }
743
744 if (aLineOn2S->NbPoints() <= 2)
745 {
746 if (aLineOn2S->NbPoints() == 2)
747 return aLocalWLine;
748 else
749 return aResult;
750 }
751
752 // Avoid purge in case of C0 continuity:
753 // Intersection approximator may produce invalid curve after purge, example:
754 // bugs modalg_5 bug24731.
755 // Do not run purger when base number of points is too small.
756 if (theS1->UContinuity() == GeomAbs_C0 ||
757 theS1->VContinuity() == GeomAbs_C0 ||
758 theS2->UContinuity() == GeomAbs_C0 ||
759 theS2->VContinuity() == GeomAbs_C0 ||
760 nb < aNbSingleBezier)
761 {
762 return aLocalWLine;
763 }
764
765 // II: Delete out of borders points.
766 Handle(IntPatch_WLine) aLocalWLineOuter =
767 DeleteOuterPoints(aLocalWLine, theS1, theS2, theDom1, theDom2);
768
769 // III: Delete points by tube criteria.
770 Handle(IntPatch_WLine) aLocalWLineTube =
771 DeleteByTube(aLocalWLineOuter, theS1, theS2);
772
773 if(aLocalWLineTube->NbPnts() > 1)
774 {
775 aResult = aLocalWLineTube;
776 }
777 return aResult;
778}
779
780
781//=======================================================================
782//function : JoinWLines
783//purpose :
784//=======================================================================
785void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
786 IntPatch_SequenceOfPoint& theSPnt,
787 const Standard_Real theTol3D,
788 const Standard_Real theU1Period,
789 const Standard_Real theU2Period,
790 const Standard_Real theV1Period,
791 const Standard_Real theV2Period,
792 const Standard_Real theUfSurf1,
793 const Standard_Real theUlSurf1,
794 const Standard_Real theVfSurf1,
795 const Standard_Real theVlSurf1,
796 const Standard_Real theUfSurf2,
797 const Standard_Real theUlSurf2,
798 const Standard_Real theVfSurf2,
799 const Standard_Real theVlSurf2)
800{
801 if(theSlin.Length() == 0)
802 return;
803
804 for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
805 {
806 Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine1)));
807
808 if(aWLine1.IsNull())
809 {//We must have failed to join not-point-lines
810 continue;
811 }
812
813 const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
814 const IntSurf_PntOn2S& aPntFW1 = aWLine1->Point(1);
815 const IntSurf_PntOn2S& aPntLW1 = aWLine1->Point(aNbPntsWL1);
816
817 for(Standard_Integer aNPt = 1; aNPt <= theSPnt.Length(); aNPt++)
818 {
819 const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNPt).PntOn2S();
820
821 if( aPntCur.IsSame(aPntFW1, Precision::Confusion()) ||
822 aPntCur.IsSame(aPntLW1, Precision::Confusion()))
823 {
824 theSPnt.Remove(aNPt);
825 aNPt--;
826 }
827 }
828
829 Standard_Boolean hasBeenRemoved = Standard_False;
830 for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1; aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
831 {
832 Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine2)));
833
834 if(aWLine2.IsNull())
835 continue;
836
837 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
838
839 const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
840 const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
841
842 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
843 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
844
845 if(aPntFWL1.IsSame(aPntFWL2, Precision::Confusion()))
846 {
847 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
848 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
849 if(!IsSeamOrBound(aPt1, aPt2, aPntFWL1, theU1Period, theU2Period,
850 theV1Period, theV2Period, theUfSurf1, theUlSurf1,
851 theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
852 theVfSurf2, theVlSurf2))
853 {
854 aWLine1->ClearVertexes();
855 for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
856 {
857 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
858 aWLine1->Curve()->InsertBefore(1, aPt);
859 }
860
861 aWLine1->ComputeVertexParameters(theTol3D);
862
863 theSlin.Remove(aNumOfLine2);
864 aNumOfLine2--;
865 hasBeenRemoved = Standard_True;
866
867 continue;
868 }
869 }
870
871 if(aPntFWL1.IsSame(aPntLWL2, Precision::Confusion()))
872 {
873 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
874 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
875 if(!IsSeamOrBound(aPt1, aPt2, aPntFWL1, theU1Period, theU2Period,
876 theV1Period, theV2Period, theUfSurf1, theUlSurf1,
877 theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
878 theVfSurf2, theVlSurf2))
879 {
880 aWLine1->ClearVertexes();
881 for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
882 {
883 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
884 aWLine1->Curve()->InsertBefore(1, aPt);
885 }
886
887 aWLine1->ComputeVertexParameters(theTol3D);
888
889 theSlin.Remove(aNumOfLine2);
890 aNumOfLine2--;
891 hasBeenRemoved = Standard_True;
892
893 continue;
894 }
895 }
896
897 if(aPntLWL1.IsSame(aPntFWL2, Precision::Confusion()))
898 {
899 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
900 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
901 if(!IsSeamOrBound(aPt1, aPt2, aPntLWL1, theU1Period, theU2Period,
902 theV1Period, theV2Period, theUfSurf1, theUlSurf1,
903 theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
904 theVfSurf2, theVlSurf2))
905 {
906 aWLine1->ClearVertexes();
907 for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
908 {
909 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
910 aWLine1->Curve()->Add(aPt);
911 }
912
913 aWLine1->ComputeVertexParameters(theTol3D);
914
915 theSlin.Remove(aNumOfLine2);
916 aNumOfLine2--;
917 hasBeenRemoved = Standard_True;
918
919 continue;
920 }
921 }
922
923 if(aPntLWL1.IsSame(aPntLWL2, Precision::Confusion()))
924 {
925 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
926 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
927 if(!IsSeamOrBound(aPt1, aPt2, aPntLWL1, theU1Period, theU2Period,
928 theV1Period, theV2Period, theUfSurf1, theUlSurf1,
929 theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
930 theVfSurf2, theVlSurf2))
931 {
932 aWLine1->ClearVertexes();
933 for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
934 {
935 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
936 aWLine1->Curve()->Add(aPt);
937 }
938
939 aWLine1->ComputeVertexParameters(theTol3D);
940
941 theSlin.Remove(aNumOfLine2);
942 aNumOfLine2--;
943 hasBeenRemoved = Standard_True;
944
945 continue;
946 }
947 }
948 }
949
950 if(hasBeenRemoved)
951 aNumOfLine1--;
952 }
953}