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