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