Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2000-01-20 |
2 | // Created by: data exchange team | |
973c2be1 | 3 | // Copyright (c) 2000-2014 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
11 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
7fd59977 | 15 | |
16 | //:pdn 11.12.98: FixDegenerated improved | |
17 | //:pdn 05.01.99: renaming method CheckLittle to CheckSmall | |
18 | //:l0 abv 10.01.99: CATIA01 #1727: fix intersecting edges always if edge is lacking | |
19 | //:n2 abv 22.01.99: ma-test5.igs: IGES read (pref3d): remove degen edge with no pcurve | |
20 | //:o4 abv 17.02.99: r0301_db.stp #53082: adding parameter isClosed to CheckOrder | |
21 | // rln 03.03.99 S4135: using updated ShapeAnalysis_Surface for checking of singularities | |
22 | //:p9 abv 11.03.99: PRO7226 #489490: fix :i9 moved to allow fixing a set of degenerated edges | |
23 | //#77 rln 11.03.99: S4135: using singularity which has minimum gap between singular point and input 3D point | |
24 | //#84 rln 18.03.99: inserting degenerated edge between ends of pcurves | |
25 | //pdn 12.03.99 S4135 check degenerated applies minimal tolerance first. | |
26 | //pdn 16.03.99 S4135 adding check of non adjacent edjes. | |
27 | //#83 rln 19.03.99: processing segments in intersection as in BRepCheck | |
28 | //%15 pdn 15.03.99 checking of small area wire added | |
29 | //#2 smh 26.03.99 S4163 Zero divide | |
30 | //#4 szv S4163 optimizing | |
31 | //:r6 abv 08.04.99: protect FixIE against working out of curve range | |
32 | //:s1 abv 22.04.99: PRO7226 #489490: ensure fixing of degenerated edge | |
33 | //#9 smh 14.12.99 BUC60615 Using tolerance of verteces during checking degenerated edge. | |
34 | ||
42cf5bc1 | 35 | #include <Adaptor3d_CurveOnSurface.hxx> |
36 | #include <Bnd_Array1OfBox2d.hxx> | |
37 | #include <Bnd_Box2d.hxx> | |
38 | #include <BndLib_Add2dCurve.hxx> | |
39 | #include <BRep_Builder.hxx> | |
40 | #include <BRep_Tool.hxx> | |
41 | #include <BRepBuilderAPI_MakeFace.hxx> | |
42 | #include <BRepGProp.hxx> | |
43 | #include <BRepTools.hxx> | |
44 | #include <GCPnts_AbscissaPoint.hxx> | |
7fd59977 | 45 | #include <Geom2d_Curve.hxx> |
7fd59977 | 46 | #include <Geom2dAdaptor_Curve.hxx> |
c22b52d6 | 47 | #include <Geom2dAdaptor_Curve.hxx> |
7fd59977 | 48 | #include <Geom2dInt_GInter.hxx> |
42cf5bc1 | 49 | #include <Geom_Curve.hxx> |
50 | #include <Geom_Plane.hxx> | |
51 | #include <Geom_Surface.hxx> | |
52 | #include <GeomAdaptor_Curve.hxx> | |
c22b52d6 | 53 | #include <GeomAdaptor_Surface.hxx> |
42cf5bc1 | 54 | #include <gp_Pnt2d.hxx> |
56a9db93 | 55 | #include <GProp_GProps.hxx> |
7fd59977 | 56 | #include <IntRes2d_Domain.hxx> |
7fd59977 | 57 | #include <IntRes2d_IntersectionPoint.hxx> |
58 | #include <IntRes2d_IntersectionSegment.hxx> | |
42cf5bc1 | 59 | #include <IntRes2d_Transition.hxx> |
60 | #include <Precision.hxx> | |
7fd59977 | 61 | #include <ShapeAnalysis.hxx> |
62 | #include <ShapeAnalysis_Curve.hxx> | |
63 | #include <ShapeAnalysis_Edge.hxx> | |
7fd59977 | 64 | #include <ShapeAnalysis_Surface.hxx> |
fbf3becf | 65 | #include <ShapeAnalysis_TransferParametersProj.hxx> |
42cf5bc1 | 66 | #include <ShapeAnalysis_Wire.hxx> |
67 | #include <ShapeAnalysis_WireOrder.hxx> | |
fbf3becf | 68 | #include <ShapeBuild_Edge.hxx> |
42cf5bc1 | 69 | #include <ShapeExtend.hxx> |
70 | #include <ShapeExtend_WireData.hxx> | |
71 | #include <Standard_Type.hxx> | |
72 | #include <TColgp_Array1OfPnt.hxx> | |
73 | #include <TColgp_SequenceOfPnt.hxx> | |
74 | #include <TColStd_Array1OfReal.hxx> | |
75 | #include <TopExp.hxx> | |
76 | #include <TopLoc_Location.hxx> | |
77 | #include <TopoDS.hxx> | |
78 | #include <TopoDS_Edge.hxx> | |
79 | #include <TopoDS_Face.hxx> | |
42cf5bc1 | 80 | #include <TopoDS_Shape.hxx> |
81 | #include <TopoDS_Vertex.hxx> | |
82 | #include <TopoDS_Wire.hxx> | |
7fd59977 | 83 | #include <TopTools_DataMapOfShapeListOfShape.hxx> |
42cf5bc1 | 84 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
7fd59977 | 85 | #include <TopTools_IndexedMapOfShape.hxx> |
86 | #include <TopTools_ListIteratorOfListOfShape.hxx> | |
42cf5bc1 | 87 | #include <TopTools_ListOfShape.hxx> |
7fd59977 | 88 | |
25e59720 | 89 | IMPLEMENT_STANDARD_RTTIEXT(ShapeAnalysis_Wire,Standard_Transient) |
92efcf78 | 90 | |
42cf5bc1 | 91 | //szvsh addition |
7fd59977 | 92 | //======================================================================= |
93 | //function : ShapeAnalysis_Wire | |
94 | //purpose : | |
95 | //======================================================================= | |
7fd59977 | 96 | ShapeAnalysis_Wire::ShapeAnalysis_Wire() |
97 | { | |
98 | ClearStatuses(); | |
99 | myPrecision = ::Precision::Confusion(); | |
100 | } | |
101 | ||
102 | //======================================================================= | |
103 | //function : ShapeAnalysis_Wire | |
104 | //purpose : | |
105 | //======================================================================= | |
106 | ||
107 | ShapeAnalysis_Wire::ShapeAnalysis_Wire (const TopoDS_Wire& wire, | |
108 | const TopoDS_Face& face, | |
109 | const Standard_Real precision) | |
110 | { | |
111 | Init (wire, face, precision); | |
112 | } | |
113 | ||
114 | //======================================================================= | |
115 | //function : ShapeAnalysis_Wire | |
116 | //purpose : | |
117 | //======================================================================= | |
118 | ||
119 | ShapeAnalysis_Wire::ShapeAnalysis_Wire (const Handle(ShapeExtend_WireData)& sbwd, | |
120 | const TopoDS_Face& face, | |
121 | const Standard_Real precision) | |
122 | { | |
123 | Init (sbwd, face, precision); | |
124 | } | |
125 | ||
126 | //======================================================================= | |
127 | //function : Init | |
128 | //purpose : | |
129 | //======================================================================= | |
130 | ||
131 | void ShapeAnalysis_Wire::Init (const TopoDS_Wire& wire, | |
132 | const TopoDS_Face& face, const Standard_Real precision) | |
133 | { | |
134 | Init (new ShapeExtend_WireData (wire), face, precision); | |
135 | } | |
136 | ||
137 | //======================================================================= | |
138 | //function : Init | |
139 | //purpose : | |
140 | //======================================================================= | |
141 | ||
142 | void ShapeAnalysis_Wire::Init (const Handle(ShapeExtend_WireData)& sbwd, | |
143 | const TopoDS_Face& face, const Standard_Real precision) | |
144 | { | |
145 | Load (sbwd); | |
146 | SetFace (face); | |
147 | SetPrecision (precision); | |
148 | } | |
149 | ||
150 | //======================================================================= | |
151 | //function : Load | |
152 | //purpose : | |
153 | //======================================================================= | |
154 | ||
155 | void ShapeAnalysis_Wire::Load (const TopoDS_Wire& wire) | |
156 | { | |
157 | ClearStatuses(); | |
158 | myWire = new ShapeExtend_WireData (wire); | |
159 | } | |
160 | ||
161 | //======================================================================= | |
162 | //function : Load | |
163 | //purpose : | |
164 | //======================================================================= | |
165 | ||
166 | void ShapeAnalysis_Wire::Load (const Handle(ShapeExtend_WireData)& sbwd) | |
167 | { | |
168 | ClearStatuses(); | |
169 | myWire = sbwd; | |
170 | } | |
171 | ||
172 | //======================================================================= | |
173 | //function : SetFace | |
174 | //purpose : | |
175 | //======================================================================= | |
176 | ||
177 | void ShapeAnalysis_Wire::SetFace(const TopoDS_Face& face) | |
178 | { | |
179 | myFace = face; | |
180 | if(!face.IsNull()) | |
181 | mySurf = new ShapeAnalysis_Surface ( BRep_Tool::Surface ( myFace ) ); | |
182 | } | |
183 | ||
184 | //======================================================================= | |
185 | //function : SetSurface | |
186 | //purpose : | |
187 | //======================================================================= | |
188 | ||
189 | void ShapeAnalysis_Wire::SetSurface (const Handle(Geom_Surface)& surface) | |
190 | { | |
191 | SetSurface ( surface, TopLoc_Location() ); | |
192 | } | |
193 | ||
194 | //======================================================================= | |
195 | //function : SetSurface | |
196 | //purpose : | |
197 | //======================================================================= | |
198 | ||
199 | void ShapeAnalysis_Wire::SetSurface (const Handle(Geom_Surface)& surface, | |
200 | const TopLoc_Location& location) | |
201 | { | |
202 | BRep_Builder B; | |
203 | TopoDS_Face face; | |
204 | B.MakeFace ( face, surface, location, ::Precision::Confusion() ); | |
205 | SetFace ( face ); | |
206 | } | |
207 | ||
208 | //======================================================================= | |
209 | //function : SetPrecision | |
210 | //purpose : | |
211 | //======================================================================= | |
212 | ||
213 | void ShapeAnalysis_Wire::SetPrecision(const Standard_Real precision) | |
214 | { | |
215 | myPrecision = precision; | |
216 | } | |
217 | ||
218 | //======================================================================= | |
219 | //function : ClearStatuses | |
220 | //purpose : | |
221 | //======================================================================= | |
222 | ||
223 | void ShapeAnalysis_Wire::ClearStatuses() | |
224 | { | |
225 | myStatusOrder = myStatusConnected = | |
226 | myStatusEdgeCurves = myStatusDegenerated = | |
227 | myStatusClosed = myStatusLacking = | |
228 | myStatusSelfIntersection = myStatusSmall = | |
229 | myStatusGaps3d = myStatusGaps2d = | |
230 | myStatusCurveGaps = myStatusLoop = myStatus = 0; | |
231 | ||
232 | myMin3d = myMin2d = myMax3d = myMax2d = 0.; | |
233 | } | |
234 | ||
235 | //======================================================================= | |
236 | //function : Perform | |
237 | //purpose : | |
238 | //======================================================================= | |
239 | ||
240 | Standard_Boolean ShapeAnalysis_Wire::Perform() | |
241 | { | |
242 | Standard_Boolean result = Standard_False; | |
243 | result |= CheckOrder(); | |
244 | result |= CheckSmall(); | |
245 | result |= CheckConnected(); | |
246 | result |= CheckEdgeCurves(); | |
247 | result |= CheckDegenerated(); | |
248 | result |= CheckSelfIntersection(); | |
249 | result |= CheckLacking(); | |
250 | result |= CheckClosed(); | |
251 | return result; | |
252 | } | |
253 | ||
254 | //======================================================================= | |
255 | //function : CheckOrder | |
256 | //purpose : | |
257 | //======================================================================= | |
258 | ||
259 | Standard_Boolean ShapeAnalysis_Wire::CheckOrder (const Standard_Boolean isClosed, | |
260 | const Standard_Boolean mode3d) | |
261 | { | |
262 | ShapeAnalysis_WireOrder sawo; | |
263 | CheckOrder (sawo, isClosed, mode3d); | |
264 | myStatusOrder = myStatus; | |
265 | return StatusOrder (ShapeExtend_DONE); | |
266 | } | |
267 | ||
268 | //======================================================================= | |
269 | //function : CheckSmall | |
270 | //purpose : | |
271 | //======================================================================= | |
272 | ||
273 | Standard_Boolean ShapeAnalysis_Wire::CheckSmall(const Standard_Real precsmall) | |
274 | { | |
275 | for (Standard_Integer i = 1; i <= myWire->NbEdges(); i++) { | |
276 | CheckSmall (i, precsmall); | |
277 | myStatusSmall |= myStatus; | |
278 | } | |
279 | return StatusSmall (ShapeExtend_DONE); | |
280 | } | |
281 | ||
282 | //======================================================================= | |
283 | //function : CheckConnected | |
284 | //purpose : | |
285 | //======================================================================= | |
286 | ||
287 | Standard_Boolean ShapeAnalysis_Wire::CheckConnected(const Standard_Real prec) | |
288 | { | |
289 | for (Standard_Integer i = 1; i <= myWire->NbEdges(); i++) { | |
290 | CheckConnected ( i, prec ); | |
291 | myStatusConnected |= myStatus; | |
292 | } | |
293 | return StatusConnected (ShapeExtend_DONE); | |
294 | } | |
295 | ||
296 | //======================================================================= | |
297 | //function : CheckEdgeCurves | |
298 | //purpose : | |
299 | //======================================================================= | |
300 | ||
301 | Standard_Boolean ShapeAnalysis_Wire::CheckEdgeCurves() | |
302 | { | |
303 | myStatusEdgeCurves = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); | |
304 | if ( ! IsReady() ) return Standard_False; | |
305 | ||
306 | Standard_Integer i, nb = myWire->NbEdges(); | |
307 | ShapeAnalysis_Edge SAE; | |
308 | ||
309 | for (i = 1; i <= nb; i++) { | |
310 | TopoDS_Edge E = myWire->Edge (i); | |
311 | ||
312 | SAE.CheckCurve3dWithPCurve (E, myFace); | |
313 | if (SAE.Status (ShapeExtend_DONE)) | |
314 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
315 | if (SAE.Status ( ShapeExtend_FAIL)) | |
316 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
317 | ||
318 | SAE.CheckVerticesWithPCurve (E, myFace); | |
319 | if (SAE.Status (ShapeExtend_DONE)) | |
320 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE2); | |
321 | if (SAE.Status ( ShapeExtend_FAIL)) | |
322 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
323 | ||
324 | SAE.CheckVerticesWithCurve3d (E); | |
325 | if (SAE.Status (ShapeExtend_DONE)) | |
326 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE3); | |
327 | if (SAE.Status ( ShapeExtend_FAIL)) | |
328 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3); | |
329 | ||
330 | CheckSeam (i); | |
331 | if (LastCheckStatus (ShapeExtend_DONE)) | |
332 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE4); | |
333 | if (LastCheckStatus (ShapeExtend_FAIL)) | |
334 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL4); | |
335 | ||
336 | CheckGap3d (i); | |
337 | if (LastCheckStatus (ShapeExtend_DONE)) | |
338 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE5); | |
339 | if (LastCheckStatus (ShapeExtend_FAIL)) | |
340 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL5); | |
341 | ||
342 | CheckGap2d (i); | |
343 | if (LastCheckStatus (ShapeExtend_DONE)) | |
344 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE6); | |
345 | if (LastCheckStatus (ShapeExtend_FAIL)) | |
346 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL6); | |
347 | ||
348 | Standard_Real maxdev = 0.0; | |
349 | SAE.CheckSameParameter (myWire->Edge (i), maxdev); | |
350 | if (SAE.Status (ShapeExtend_DONE)) | |
351 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_DONE7); | |
352 | if (SAE.Status ( ShapeExtend_FAIL)) | |
353 | myStatusEdgeCurves |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL7); | |
354 | } | |
355 | return StatusEdgeCurves (ShapeExtend_DONE); | |
356 | } | |
357 | ||
358 | //======================================================================= | |
359 | //function : CheckDegenerated | |
360 | //purpose : | |
361 | //======================================================================= | |
362 | ||
363 | Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated() | |
364 | { | |
365 | for (Standard_Integer i = 1; i <= myWire->NbEdges(); i++) { | |
366 | CheckDegenerated (i); | |
367 | myStatusDegenerated |= myStatus; | |
368 | } | |
369 | return StatusDegenerated (ShapeExtend_DONE); | |
370 | } | |
371 | ||
372 | //======================================================================= | |
373 | //function : CheckSelfIntersection | |
374 | //purpose : | |
375 | //======================================================================= | |
376 | ||
377 | Standard_Boolean ShapeAnalysis_Wire::CheckSelfIntersection() | |
378 | { | |
379 | myStatusSelfIntersection = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); | |
380 | if (!IsReady()) return Standard_False; | |
381 | Standard_Integer i, nb = myWire->NbEdges(); | |
382 | for (i = 1; i <= nb; i++) { | |
383 | CheckSelfIntersectingEdge (i); | |
384 | if (LastCheckStatus (ShapeExtend_DONE)) | |
385 | myStatusSelfIntersection |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
386 | if (LastCheckStatus (ShapeExtend_FAIL)) | |
387 | myStatusSelfIntersection |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
388 | ||
389 | CheckIntersectingEdges (i); | |
390 | if (LastCheckStatus (ShapeExtend_DONE)) | |
391 | myStatusSelfIntersection |= ShapeExtend::EncodeStatus (ShapeExtend_DONE2); | |
392 | if (LastCheckStatus (ShapeExtend_FAIL)) | |
393 | myStatusSelfIntersection |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
394 | } | |
395 | ||
396 | Bnd_Array1OfBox2d boxes(1,nb); | |
397 | TopLoc_Location L; | |
398 | const Handle(Geom_Surface)& S = BRep_Tool::Surface(Face(), L); | |
399 | Handle(Geom2d_Curve) c2d; | |
400 | Standard_Real cf,cl; | |
401 | ShapeAnalysis_Edge sae; | |
402 | Handle(ShapeExtend_WireData) sbwd = WireData(); | |
403 | for(i = 1; i <= nb; i++){ | |
404 | TopoDS_Edge E = sbwd->Edge (i); | |
405 | if(sae.PCurve (E,S,L,c2d,cf,cl,Standard_False)) { | |
406 | Bnd_Box2d box; | |
407 | Geom2dAdaptor_Curve gac(c2d,cf,cl); | |
408 | BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box); | |
409 | boxes(i) = box; | |
410 | } | |
411 | } | |
412 | ||
413 | Standard_Boolean isFail = Standard_False, isDone = Standard_False; | |
414 | for(Standard_Integer num1 = 1; num1 < nb-1; num1++) { | |
ef57920a V |
415 | Standard_Integer fin = nb; |
416 | if (CheckClosed(Precision::Confusion()) && 1 == num1) | |
417 | fin = nb-1; | |
7fd59977 | 418 | for(Standard_Integer num2 = num1+2; num2 <= fin; num2++) |
419 | if(!boxes(num1).IsOut(boxes(num2))){ | |
420 | CheckIntersectingEdges(num1, num2); | |
421 | isFail |= LastCheckStatus ( ShapeExtend_FAIL1 ); | |
422 | isDone |= LastCheckStatus ( ShapeExtend_DONE1 ); | |
423 | } | |
424 | } | |
425 | if(isFail) | |
426 | myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 ); | |
427 | if(isDone) | |
428 | myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 ); | |
429 | ||
430 | return StatusSelfIntersection (ShapeExtend_DONE); | |
431 | } | |
432 | ||
433 | //======================================================================= | |
434 | //function : CheckLacking | |
435 | //purpose : | |
436 | //======================================================================= | |
437 | ||
438 | Standard_Boolean ShapeAnalysis_Wire::CheckLacking() | |
439 | { | |
440 | if (!IsReady() || NbEdges() < 2) return Standard_False; | |
441 | for (Standard_Integer i = 1; i <= myWire->NbEdges(); i++) { | |
442 | CheckLacking (i); | |
443 | myStatusLacking |= myStatus; | |
444 | } | |
445 | return StatusLacking (ShapeExtend_DONE); | |
446 | } | |
447 | ||
448 | //======================================================================= | |
449 | //function : CheckClosed | |
450 | //purpose : | |
451 | //======================================================================= | |
452 | ||
453 | Standard_Boolean ShapeAnalysis_Wire::CheckClosed(const Standard_Real prec) | |
454 | { | |
455 | myStatusClosed = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); | |
456 | if (!IsReady() || NbEdges() < 1) return Standard_False; | |
457 | ||
458 | CheckConnected (1, prec); | |
459 | if ( LastCheckStatus ( ShapeExtend_DONE ) ) | |
460 | myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 ); | |
461 | if ( LastCheckStatus ( ShapeExtend_FAIL ) ) | |
462 | myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 ); | |
463 | ||
464 | CheckDegenerated ( 1 ); | |
465 | if ( LastCheckStatus ( ShapeExtend_DONE ) ) | |
466 | myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 ); | |
467 | if ( LastCheckStatus ( ShapeExtend_FAIL ) ) | |
468 | myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 ); | |
469 | ||
470 | return StatusClosed ( ShapeExtend_DONE ); | |
471 | } | |
472 | ||
473 | //======================================================================= | |
474 | //function : CheckGaps3d | |
475 | //purpose : | |
476 | //======================================================================= | |
477 | ||
478 | Standard_Boolean ShapeAnalysis_Wire::CheckGaps3d () | |
479 | { | |
480 | myStatusGaps3d = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); | |
481 | if (!IsLoaded() || NbEdges() < 1) return Standard_False; //gka IsLoaded | |
482 | ||
483 | Standard_Real dist, maxdist = 0.; | |
484 | ||
485 | for (Standard_Integer i = 1; i <= NbEdges(); i++) { | |
486 | CheckGap3d(i); | |
487 | myStatusGaps3d |= myStatus; | |
488 | if (!LastCheckStatus(ShapeExtend_FAIL1)) { | |
489 | dist = MinDistance3d(); | |
490 | if (maxdist<dist) maxdist = dist; | |
491 | } | |
492 | } | |
493 | myMin3d = myMax3d = maxdist; | |
494 | ||
495 | return StatusGaps3d ( ShapeExtend_DONE ); | |
496 | } | |
497 | ||
498 | //======================================================================= | |
499 | //function : CheckGaps2d | |
500 | //purpose : | |
501 | //======================================================================= | |
502 | ||
503 | Standard_Boolean ShapeAnalysis_Wire::CheckGaps2d () | |
504 | { | |
505 | myStatusGaps2d = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); | |
506 | if (!IsReady() || NbEdges() < 1) return Standard_False; | |
507 | ||
508 | Standard_Real dist, maxdist = 0.; | |
509 | ||
510 | for (Standard_Integer i = 1; i <= NbEdges(); i++) { | |
511 | CheckGap2d(i); | |
512 | myStatusGaps2d |= myStatus; | |
513 | if (!LastCheckStatus(ShapeExtend_FAIL1)) { | |
514 | dist = MinDistance2d(); | |
515 | if (maxdist<dist) maxdist = dist; | |
516 | } | |
517 | } | |
518 | myMin2d = myMax2d = maxdist; | |
519 | ||
520 | return StatusGaps2d ( ShapeExtend_DONE ); | |
521 | } | |
522 | ||
523 | //======================================================================= | |
524 | //function : CheckCurveGaps | |
525 | //purpose : | |
526 | //======================================================================= | |
527 | ||
528 | Standard_Boolean ShapeAnalysis_Wire::CheckCurveGaps () | |
529 | { | |
530 | myStatusCurveGaps = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); | |
531 | if (!IsReady() || NbEdges() < 1) return Standard_False; | |
532 | ||
533 | Standard_Real dist, maxdist = 0.; | |
534 | ||
535 | for (Standard_Integer i = 1; i <= NbEdges(); i++) { | |
536 | CheckCurveGap(i); | |
537 | myStatusCurveGaps |= myStatus; | |
538 | if (!LastCheckStatus(ShapeExtend_FAIL1)) { | |
539 | dist = MinDistance3d(); | |
540 | if (maxdist<dist) maxdist = dist; | |
541 | } | |
542 | } | |
543 | myMin3d = myMax3d = maxdist; | |
544 | ||
545 | return StatusCurveGaps ( ShapeExtend_DONE ); | |
546 | } | |
547 | ||
548 | //======================================================================= | |
549 | //function : CheckOrder | |
550 | //purpose : | |
551 | //======================================================================= | |
552 | ||
553 | Standard_Boolean ShapeAnalysis_Wire::CheckOrder(ShapeAnalysis_WireOrder& sawo, | |
554 | const Standard_Boolean isClosed, | |
555 | const Standard_Boolean mode3d) | |
556 | { | |
557 | if ( ! mode3d && myFace.IsNull() ) { | |
558 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
559 | return Standard_False; | |
560 | } | |
561 | ||
562 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
563 | sawo.SetMode ( mode3d, ( mode3d ? myPrecision : ::Precision::PConfusion() ) ); | |
564 | Standard_Integer i, nb = myWire->NbEdges(); | |
565 | ShapeAnalysis_Edge EA; | |
566 | for (i = 1; i <= nb; i ++) { | |
567 | TopoDS_Edge E = myWire->Edge(i); | |
568 | if ( mode3d ) { | |
569 | TopoDS_Vertex V1 = EA.FirstVertex (E); | |
570 | TopoDS_Vertex V2 = EA.LastVertex (E); | |
42e4630c | 571 | if (V1.IsNull() || V2.IsNull()) |
572 | { | |
573 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
574 | return Standard_False; | |
575 | } | |
7fd59977 | 576 | gp_Pnt p1 = BRep_Tool::Pnt (V1); |
577 | gp_Pnt p2 = BRep_Tool::Pnt (V2); | |
578 | sawo.Add (p1.XYZ(),p2.XYZ()); | |
579 | } | |
580 | else { | |
581 | Standard_Real f,l; | |
582 | Handle(Geom2d_Curve) c2d; | |
583 | TopoDS_Shape tmpF = myFace.Oriented(TopAbs_FORWARD); | |
584 | if ( ! EA.PCurve(E,TopoDS::Face(tmpF),c2d,f,l) ) { | |
585 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
586 | return Standard_False; | |
587 | } | |
588 | sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY()); | |
589 | } | |
590 | } | |
591 | sawo.Perform(isClosed); | |
592 | Standard_Integer stat = sawo.Status(); | |
593 | switch (stat) { | |
594 | case 0: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); break; | |
595 | case 1: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); break; | |
596 | case 2: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); break; | |
597 | case -1: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE3); break; | |
598 | case -2: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE4); break; | |
673693f1 | 599 | case 3: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE5); break;//only shifted |
7fd59977 | 600 | case -10: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); break; |
601 | } | |
602 | return LastCheckStatus (ShapeExtend_DONE); | |
603 | } | |
604 | ||
605 | //======================================================================= | |
606 | //function : CheckConnected | |
607 | //purpose : | |
608 | //======================================================================= | |
609 | ||
610 | Standard_Boolean ShapeAnalysis_Wire::CheckConnected (const Standard_Integer num, | |
611 | const Standard_Real prec) | |
612 | { | |
613 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
614 | if ( ! IsLoaded() || NbEdges() < 1 ) return Standard_False; | |
615 | ||
616 | Standard_Integer n2 = ( num >0 ? num : NbEdges() ); | |
617 | Standard_Integer n1 = ( n2 >1 ? n2-1 : NbEdges() ); | |
618 | // if (n1 == n2) return 0; | |
619 | ||
620 | TopoDS_Edge E1 = WireData()->Edge ( n1 ); | |
621 | TopoDS_Edge E2 = WireData()->Edge ( n2 ); | |
622 | ||
623 | ShapeAnalysis_Edge sae; | |
624 | TopoDS_Vertex V1 = sae.LastVertex (E1); | |
625 | TopoDS_Vertex V2 = sae.FirstVertex (E2); | |
42e4630c | 626 | if (V1.IsNull() || V2.IsNull()) |
627 | { | |
628 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
629 | return Standard_False; | |
630 | } | |
7fd59977 | 631 | if (V1.IsSame(V2)) return Standard_False; |
632 | ||
633 | gp_Pnt p1 = BRep_Tool::Pnt (V1); | |
634 | gp_Pnt p2 = BRep_Tool::Pnt (V2); | |
635 | myMin3d = p1.Distance(p2); | |
636 | if ( myMin3d <= gp::Resolution() ) myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
637 | else if ( myMin3d <= myPrecision ) myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE2); | |
638 | else if ( myMin3d <= prec ) myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE3); | |
639 | else { | |
640 | // et en inversant la derniere edge ? | |
641 | if ( n1 == n2 ) myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
642 | else { | |
643 | V2 = sae.LastVertex (E2); | |
644 | p2 = BRep_Tool::Pnt (V2); | |
645 | Standard_Real dist = p1.Distance(p2); | |
646 | if ( dist > myPrecision ) myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
647 | else { | |
648 | myMin3d = dist; | |
649 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
650 | } | |
651 | } | |
652 | return Standard_False; | |
653 | } | |
654 | return Standard_True; | |
655 | } | |
656 | ||
657 | //======================================================================= | |
658 | //function : CheckSmall | |
659 | //purpose : | |
660 | //======================================================================= | |
661 | ||
662 | Standard_Boolean ShapeAnalysis_Wire::CheckSmall (const Standard_Integer num, | |
663 | const Standard_Real precsmall) | |
664 | { | |
665 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
666 | if ( ! IsLoaded() || NbEdges() <= 1 ) return Standard_False; | |
667 | ||
668 | //Standard_Integer n = ( num ? num : NbEdges() ); //szv#4:S4163:12Mar99 not needed | |
669 | TopoDS_Edge E = myWire->Edge ( num ? num : NbEdges() ); | |
670 | ShapeAnalysis_Edge sae; | |
671 | ||
672 | if ( BRep_Tool::Degenerated ( E ) ) { | |
673 | //:n2 abv 22 Jan 99: ma-test5.igs -> IGES (brep) -> read (pref3d): | |
674 | // degen edge with no pcurve should be removed | |
675 | if ( ! myFace.IsNull() && sae.HasPCurve ( E, Face() ) ) return Standard_False; | |
676 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
677 | } | |
678 | ||
679 | TopoDS_Vertex V1 = sae.FirstVertex (E); | |
680 | TopoDS_Vertex V2 = sae.LastVertex (E); | |
29582444 | 681 | if (V1.IsNull() || V2.IsNull()) |
682 | { | |
683 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
684 | return Standard_False; | |
685 | } | |
7fd59977 | 686 | gp_Pnt p1 = BRep_Tool::Pnt (V1); |
687 | gp_Pnt p2 = BRep_Tool::Pnt (V2); | |
688 | Standard_Real dist = p1.Distance(p2); | |
689 | Standard_Real prec = precsmall;//Min ( myPrecision, precsmall ); | |
690 | //Standard_Real prec = Min(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2)); //skl | |
691 | if (dist > prec) return Standard_False; // pas nulle | |
692 | ||
693 | // La courbe 3D a present : est-elle FERMEE ou DE LONGUEUR NULLE ... ??? | |
694 | // Pour cela on prend le point milieu (y a-t-il mieux) | |
695 | // Si pas de C3D, on essaie la C2D ... | |
696 | ||
697 | gp_Pnt Pm; | |
698 | Standard_Real cf,cl; | |
699 | Handle(Geom_Curve) c3d; | |
700 | if ( sae.Curve3d (E,c3d,cf,cl,Standard_False) ) Pm = c3d->Value ( (cf+cl)/2. ); | |
701 | else { | |
702 | Handle(Geom2d_Curve) c2d; | |
703 | if ( ! myFace.IsNull() && sae.PCurve (E,myFace,c2d,cf,cl,Standard_False)) { | |
704 | gp_Pnt2d p2m = c2d->Value ( (cf+cl)/2. ); | |
705 | Pm = mySurf->Value (p2m); | |
706 | } | |
707 | else { | |
708 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
709 | Pm = p1; | |
710 | //:n2 return Standard_False; | |
711 | } | |
712 | } | |
713 | if ( Pm.Distance(p1) > prec || Pm.Distance(p2) > prec ) return Standard_False; | |
714 | ||
715 | myStatus |= ShapeExtend::EncodeStatus ( V1.IsSame(V2) ? ShapeExtend_DONE1 : ShapeExtend_DONE2 ); | |
716 | return Standard_True; | |
717 | } | |
718 | ||
719 | //======================================================================= | |
720 | //function : CheckSeam | |
721 | //purpose : | |
722 | //======================================================================= | |
723 | ||
724 | Standard_Boolean ShapeAnalysis_Wire::CheckSeam(const Standard_Integer num, | |
725 | Handle(Geom2d_Curve)& C1, | |
726 | Handle(Geom2d_Curve)& C2, | |
727 | Standard_Real& cf, | |
728 | Standard_Real& cl) | |
729 | { | |
730 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
731 | if (!IsReady()) return Standard_False; | |
732 | Standard_Integer n = num; if (n == 0) n = NbEdges(); | |
733 | TopoDS_Edge E = myWire->Edge (n); | |
734 | if ( ! ShapeAnalysis_Edge().IsSeam ( E, myFace ) ) return Standard_False; | |
735 | // Extract the Two PCurves of the Seam | |
736 | TopoDS_Face ForwardFace = myFace; ForwardFace.Orientation (TopAbs_FORWARD); | |
737 | //szv#4:S4163:12Mar99 SGI warns | |
738 | TopoDS_Shape EF = E.Oriented(TopAbs_FORWARD); | |
739 | TopoDS_Shape ER = E.Oriented(TopAbs_REVERSED); | |
740 | C1 = BRep_Tool::CurveOnSurface(TopoDS::Edge(EF), ForwardFace, cf, cl); | |
741 | C2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(ER), ForwardFace, cf, cl); | |
742 | if (C1.IsNull() || C2.IsNull()) return Standard_False; | |
743 | ||
744 | // SelectForward est destine a devenir un outil distinct | |
745 | ||
746 | Standard_Integer theCurveIndice = ShapeAnalysis_Curve().SelectForwardSeam (C1,C2); | |
747 | if ( theCurveIndice != 2 ) return Standard_False; | |
748 | ||
749 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
750 | return Standard_True; | |
751 | } | |
752 | ||
753 | //======================================================================= | |
754 | //function : CheckSeam | |
755 | //purpose : | |
756 | //======================================================================= | |
757 | ||
758 | Standard_Boolean ShapeAnalysis_Wire::CheckSeam(const Standard_Integer num) | |
759 | { | |
760 | Handle(Geom2d_Curve) C1, C2; | |
761 | Standard_Real cf, cl; | |
762 | return CheckSeam (num, C1, C2, cf, cl); | |
763 | } | |
764 | ||
765 | //======================================================================= | |
766 | //function : CheckDegenerated | |
767 | //purpose : | |
768 | //======================================================================= | |
769 | ||
770 | Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer num, | |
771 | gp_Pnt2d& p2d1, gp_Pnt2d& p2d2) | |
772 | { | |
773 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
774 | if ( ! IsReady() || NbEdges() < 1 ) return Standard_False; | |
775 | ||
776 | Standard_Integer n2 = (num > 0)? num : NbEdges(); | |
777 | Standard_Integer n1 = (n2 > 1)? n2-1 : NbEdges(); | |
778 | Standard_Integer n3 = (n2 < NbEdges())? n2+1 : 1; | |
779 | TopoDS_Edge E1 = myWire->Edge ( n1 ); | |
780 | TopoDS_Edge E2 = myWire->Edge ( n2 ); | |
781 | TopoDS_Edge E3 = myWire->Edge ( n3 ); | |
782 | ||
783 | ShapeAnalysis_Edge sae; | |
784 | ||
785 | // skip if edge is already marked as degenerated and has pcurve | |
786 | if ( BRep_Tool::Degenerated ( E2 ) && sae.HasPCurve ( E2, Face() ) ) { | |
787 | // skl 30.12.2004 for OCC7630 - we have to check pcurve | |
788 | if( sae.HasPCurve(E1,Face()) && sae.HasPCurve(E3,Face()) ) { | |
789 | Handle(Geom2d_Curve) c2d; | |
790 | Standard_Real fp,lp; | |
791 | sae.PCurve ( E2, myFace, c2d, fp, lp, Standard_True ); | |
792 | gp_Pnt2d p21 = c2d->Value(fp); | |
793 | gp_Pnt2d p22 = c2d->Value(lp); | |
794 | sae.PCurve ( E1, myFace, c2d, fp, lp, Standard_True ); | |
795 | gp_Pnt2d p12 = c2d->Value(lp); | |
796 | sae.PCurve ( E3, myFace, c2d, fp, lp, Standard_True ); | |
797 | gp_Pnt2d p31 = c2d->Value(fp); | |
798 | if( fabs(p12.Distance(p31)-p21.Distance(p22)) > 2*Precision::PConfusion() ) { | |
799 | // pcurve is bad => we can remove this edge in ShapeFix | |
800 | // if set needed status | |
801 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
802 | } | |
803 | } | |
804 | return Standard_False; | |
805 | } | |
806 | ||
807 | //pdn allows to insert two sequences of degenerated edges (on separate bounds of surfaces) | |
808 | if ( n1 != n2 && BRep_Tool::Degenerated ( E1 ) && | |
809 | ! sae.HasPCurve ( E1, Face() ) ) { | |
316ea293 | 810 | //:abv 13.05.02: OCC320 - fail (to remove edge) if two consecutive degenerated edges w/o pcurves |
7fd59977 | 811 | if ( BRep_Tool::Degenerated ( E2 ) ) |
812 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
813 | return Standard_False; | |
814 | } | |
815 | //:i8 if ( BRep_Tool::Degenerated ( E1 ) || | |
816 | //:i8 BRep_Tool::Degenerated ( E2 ) ) return Standard_False; // deja OK | |
817 | ||
818 | TopoDS_Vertex Vp = sae.FirstVertex (E1); //:i9 | |
819 | TopoDS_Vertex V0 = sae.LastVertex (E1); | |
820 | TopoDS_Vertex V1 = sae.FirstVertex (E2); | |
821 | TopoDS_Vertex V2 = sae.LastVertex (E2); | |
46aed280 | 822 | |
823 | if (Vp.IsNull() || V0.IsNull() || V1.IsNull() || V2.IsNull()) | |
824 | return Standard_False; | |
825 | ||
7fd59977 | 826 | gp_Pnt pp = BRep_Tool::Pnt (Vp); //:i9 |
827 | gp_Pnt p0 = BRep_Tool::Pnt (V0); | |
828 | gp_Pnt p1 = BRep_Tool::Pnt (V1); | |
829 | gp_Pnt p2 = BRep_Tool::Pnt (V2); | |
830 | Standard_Real par1, par2; | |
831 | Standard_Boolean lack = Standard_False; | |
832 | Standard_Boolean dgnr = Standard_False; | |
833 | //pdn 12.03.99 minimal value processing first | |
834 | Standard_Real precFirst = Min(myPrecision,BRep_Tool::Tolerance(V1)); | |
835 | Standard_Real precFin = Max(myPrecision,BRep_Tool::Tolerance(V1)); | |
836 | Standard_Real precVtx = (myPrecision<BRep_Tool::Tolerance(V1) ? 2*precFin : precFin); | |
837 | // forward : si Edge <num> FWD/REV. Si LACK, toujours True | |
838 | Standard_Boolean forward = ( E2.Orientation() == TopAbs_FORWARD ); | |
839 | // FIX FEV 1998 : recompute singularity according precision | |
840 | ||
841 | if (p1.Distance(p2) <= precFirst) { // edge DGNR | |
842 | dgnr = mySurf->DegeneratedValues ( p1, precVtx, p2d1, p2d2, par1, par2, forward ); //smh#9 | |
843 | if ( dgnr ) { // abv 24 Feb 00: trj3_as1-ac-214.stp #6065: avoid making closed edge degenerated | |
844 | Standard_Real a, b; | |
845 | Handle(Geom_Curve) C3d = BRep_Tool::Curve ( E2, a, b ); | |
846 | if ( ! C3d.IsNull() ) { | |
847 | gp_Pnt p = C3d->Value ( 0.5 * ( a + b ) ); | |
848 | if ( p.SquareDistance ( p1 ) > precVtx * precVtx ) dgnr = Standard_False; | |
849 | } | |
850 | } | |
851 | } | |
852 | if ( ! dgnr ) { | |
853 | //:i9 abv 23 Sep 98: CTS20315-2 #63231: check that previous edge is not degenerated | |
854 | if ( n1 != n2 && p1.Distance(pp) <= precFirst && | |
855 | mySurf->IsDegenerated ( pp, precFirst ) && | |
856 | ! BRep_Tool::Degenerated ( E1 ) ) return Standard_False; | |
857 | //rln S4135 ShapeAnalysis_Surface new algorithms for singularities | |
858 | //:45 by abv 16 Dec 97: BUC60035 2659: precision increased to vertex tolerance | |
859 | //Standard_Real prec = Max ( myPrecision, BRep_Tool::Tolerance(V1) ); | |
860 | //:51 abv 22 Dec 97: recompute singularities if necessary | |
861 | //rln S4135 if ( prec > myPrecision ) mySurf->ComputeSingularities ( 2 * prec ); //:51 //:74 abv 15 Jan 97: *2 | |
862 | ||
863 | if ( p0.Distance ( p1 ) <= precFin ) {// ou DGNR manquante ? | |
864 | //rln S4135 singularity with precision = 2 * prec, but distance <= prec | |
865 | //lack = mySurf->DegeneratedValues ( p1, prec, p2d1, p2d2, par1, par2, forward); | |
866 | Standard_Real tmpPreci; | |
867 | gp_Pnt tmpP3d; | |
868 | Standard_Boolean tmpUIsoDeg; | |
869 | //#77 rln S4135: using singularity which has minimum gap between singular point and input 3D point | |
870 | Standard_Integer indMin = -1; | |
871 | Standard_Real gapMin2 = RealLast(); | |
872 | for (Standard_Integer i = 1; i <= mySurf->NbSingularities (precVtx); i++) { | |
873 | mySurf->Singularity (i, tmpPreci, tmpP3d, p2d1, p2d2, par1, par2, tmpUIsoDeg); | |
874 | Standard_Real gap2 = p1.SquareDistance (tmpP3d); | |
875 | if (gap2 <= precVtx * precVtx) | |
876 | if (gapMin2 > gap2) { | |
877 | gapMin2 = gap2; | |
878 | indMin = i; | |
879 | } | |
880 | } | |
881 | if (indMin >= 1) { | |
882 | mySurf->Singularity (indMin, tmpPreci, tmpP3d, p2d1, p2d2, par1, par2, tmpUIsoDeg); | |
883 | lack = Standard_True; | |
884 | } | |
885 | } | |
886 | ||
887 | //rln S4135 if ( prec > myPrecision ) mySurf->ComputeSingularities ( myPrecision ); //:51 | |
888 | } | |
889 | ||
890 | // voila, on a soit dgnr soit lack | |
891 | if ( ! lack && ! dgnr ) { | |
892 | //:abv 29.08.01: if singularity not detected but edge is marked | |
893 | // as degenerated, report fail | |
894 | if ( BRep_Tool::Degenerated ( E2 ) && ! sae.HasPCurve ( E2, Face() ) ) | |
895 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
896 | return Standard_False; | |
897 | } | |
898 | ||
899 | // OK, degenerated case detected; we will find its start and end in 2d | |
900 | ||
901 | if ( lack ) forward = Standard_True; | |
902 | ||
903 | //:24 by abv 28 Nov 97: | |
904 | // make degenerative pcurve parametrized exactly from end of pcurve of the | |
905 | // previous edge to the start of the next one | |
906 | if ( lack || n1 != n2 ) { //:i8 abv 18 Sep 98: ProSTEP TR9 r0501-ug.stp #182180: single degedge is a wire at apex of a cone | |
907 | Standard_Real a, b; | |
908 | Handle(Geom2d_Curve) c2d; | |
909 | if ( sae.PCurve ( E1, myFace, c2d, a, b, Standard_True ) ) { | |
910 | p2d1 = c2d->Value ( b ); | |
911 | //#84 rln gp_Pnt2d p2d = c2d->Value ( b ); | |
912 | //#84 rln par1 = ( p2d.XY() - aP2d.XY() ) * theDir2d.XY(); | |
913 | } | |
914 | else myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
915 | //pdn pcurves (fixing regression in f0 in degenerated case) | |
916 | if ( sae.PCurve ( ( dgnr ? E3 : E2 ), myFace, c2d, a, b, Standard_True ) ) { | |
917 | p2d2 = c2d->Value ( a ); | |
918 | //#84 rln gp_Pnt2d p2d = c2d->Value ( a ); | |
919 | //#84 rln par2 = ( p2d.XY() - aP2d.XY() ) * theDir2d.XY(); | |
920 | } | |
921 | else myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
922 | } | |
923 | /* | |
924 | if ( par2 < par1 ) { | |
925 | par1 = -par1; | |
926 | par2 = -par2; | |
927 | theDir2d.Reverse(); | |
928 | } | |
929 | */ | |
930 | ||
931 | //#84 rln 18.03.99 if pcurve is not degenerate anymore, the fix is postponned | |
932 | //to ShapeFix_Wire::FixLacking | |
933 | if ( ! mySurf->IsDegenerated ( p2d1, p2d2, precVtx, 10. ) ) { //:s1 abv 22 Apr 99: PRO7226 #489490 //smh#9 | |
316ea293 | 934 | //:abv 24.05.02: OCC320 - fail (to remove edge) if two consecutive degenerated edges w/o pcurves |
7fd59977 | 935 | if ( BRep_Tool::Degenerated ( E2 ) ) |
936 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
937 | return Standard_False; | |
938 | } | |
939 | ||
940 | //added by rln 18/12/97 CSR# CTS18544 entity 13638 | |
941 | //the situation when degenerated edge already exists but flag is not set | |
942 | //(i.e. the parametric space is closed) | |
c22b52d6 | 943 | GeomAdaptor_Surface& Ads = *mySurf->Adaptor3d(); |
7fd59977 | 944 | Standard_Real max = Max ( Ads.UResolution(myPrecision), |
945 | Ads.VResolution(myPrecision) ); | |
946 | if ( p2d1.Distance (p2d2) /*Abs (par1 - par2)*/ <= max + gp::Resolution() ) return Standard_False; | |
947 | ||
948 | //#84 rln p2d1 = aP2d.XY() + par1 * theDir2d.XY(); | |
949 | //#84 rln p2d2 = aP2d.XY() + par2 * theDir2d.XY(); | |
950 | myStatus = ShapeExtend::EncodeStatus ( dgnr ? ShapeExtend_DONE2 : ShapeExtend_DONE1 ); | |
951 | return Standard_True; | |
952 | } | |
953 | ||
954 | //======================================================================= | |
955 | //function : CheckDegenerated | |
956 | //purpose : | |
957 | //======================================================================= | |
958 | ||
959 | Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer num) | |
960 | { | |
961 | gp_Pnt2d p2d1, p2d2; | |
962 | return CheckDegenerated ( num, p2d1, p2d2 ); | |
963 | } | |
964 | ||
965 | //======================================================================= | |
966 | //function : CheckGap3d | |
967 | //purpose : | |
968 | //======================================================================= | |
969 | ||
970 | Standard_Boolean ShapeAnalysis_Wire::CheckGap3d(const Standard_Integer num) | |
971 | { | |
972 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
973 | //szv#4:S4163:12Mar99 optimized | |
974 | if ( !IsLoaded() || NbEdges() < 1 ) return Standard_False; //szvsh was nbedges < 2 | |
975 | Standard_Integer n2 = ( num >0 ? num : NbEdges() ); | |
976 | Standard_Integer n1 = ( n2 >1 ? n2-1 : NbEdges() ); | |
977 | TopoDS_Edge E1 = myWire->Edge(n1); | |
978 | TopoDS_Edge E2 = myWire->Edge(n2); | |
979 | Standard_Real uf1,ul1,uf2,ul2; | |
980 | Handle(Geom_Curve) C1,C2; | |
981 | ShapeAnalysis_Edge SAE; | |
982 | if (!SAE.Curve3d (E1,C1,uf1,ul1) || !SAE.Curve3d (E2,C2,uf2,ul2)) { | |
983 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
984 | return Standard_False; | |
985 | } | |
986 | gp_Pnt p1 = C1->Value (ul1); | |
987 | gp_Pnt p2 = C2->Value (uf2); | |
988 | myMin3d = myMax3d = p1.Distance (p2); | |
989 | if (myMin3d > myPrecision) | |
990 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
991 | return LastCheckStatus (ShapeExtend_DONE); | |
992 | } | |
993 | ||
994 | //======================================================================= | |
995 | //function : CheckGap2d | |
996 | //purpose : | |
997 | //======================================================================= | |
998 | ||
999 | Standard_Boolean ShapeAnalysis_Wire::CheckGap2d(const Standard_Integer num) | |
1000 | { | |
1001 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
1002 | //szv#4:S4163:12Mar99 optimized | |
1003 | if ( !IsReady() || NbEdges() < 1 ) return Standard_False; //szvsh was nbedges < 2 | |
1004 | Standard_Integer n2 = ( num >0 ? num : NbEdges() ); | |
1005 | Standard_Integer n1 = ( n2 >1 ? n2-1 : NbEdges() ); | |
1006 | TopoDS_Edge E1 = myWire->Edge(n1); | |
1007 | TopoDS_Edge E2 = myWire->Edge(n2); | |
1008 | Standard_Real uf1,ul1,uf2,ul2; | |
1009 | Handle(Geom2d_Curve) C1,C2; | |
1010 | ShapeAnalysis_Edge SAE; | |
1011 | if (!SAE.PCurve (E1,myFace,C1,uf1,ul1) || !SAE.PCurve (E2,myFace,C2,uf2,ul2)) { | |
1012 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
1013 | return Standard_False; | |
1014 | } | |
1015 | gp_Pnt2d p1 = C1->Value (ul1); | |
1016 | gp_Pnt2d p2 = C2->Value (uf2); | |
1017 | myMin2d = myMax2d = p1.Distance (p2); | |
c22b52d6 | 1018 | GeomAdaptor_Surface& SA = *mySurf->Adaptor3d(); |
7fd59977 | 1019 | if (myMin2d > (Max (SA.UResolution (myPrecision), SA.VResolution (myPrecision)) + Precision::PConfusion())) |
1020 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
1021 | return LastCheckStatus (ShapeExtend_DONE); | |
1022 | } | |
1023 | ||
1024 | //======================================================================= | |
1025 | //function : CheckCurveGap | |
1026 | //purpose : | |
1027 | //======================================================================= | |
1028 | ||
1029 | Standard_Boolean ShapeAnalysis_Wire::CheckCurveGap(const Standard_Integer num) | |
1030 | { | |
1031 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
1032 | if ( !IsLoaded() || NbEdges() < 1 ) return Standard_False; | |
1033 | Standard_Integer n = ( num >0 ? num : NbEdges() ); | |
1034 | TopoDS_Edge E = myWire->Edge(n); | |
1035 | Standard_Real cuf,cul,pcuf,pcul; | |
1036 | Handle(Geom_Curve) c; | |
1037 | ShapeAnalysis_Edge SAE; | |
1038 | if (!SAE.Curve3d (E,c,cuf,cul,Standard_False)) { | |
1039 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
1040 | return Standard_False; | |
1041 | } | |
1042 | Handle(Geom2d_Curve) pc; | |
1043 | if (!SAE.PCurve (E,myFace,pc,pcuf,pcul,Standard_False)) { | |
1044 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
1045 | return Standard_False; | |
1046 | } | |
c22b52d6 | 1047 | Handle(Geom2dAdaptor_Curve) AC = new Geom2dAdaptor_Curve(pc,pcuf,pcul); |
1048 | Handle(GeomAdaptor_Surface) AS = new GeomAdaptor_Surface(mySurf->Surface()); | |
7fd59977 | 1049 | Adaptor3d_CurveOnSurface ACS(AC,AS); |
1050 | gp_Pnt cpnt, pcpnt; | |
1051 | Standard_Integer nbp = 45; | |
1052 | Standard_Real dist, maxdist=0.; | |
1053 | for (Standard_Integer i=0; i<nbp; i++) { | |
1054 | cpnt = c->Value(cuf + i*(cul-cuf)/(nbp-1)); | |
1055 | pcpnt = ACS.Value(pcuf + i*(pcul-pcuf)/(nbp-1)); | |
1056 | dist = cpnt.SquareDistance(pcpnt); | |
1057 | if (maxdist<dist) maxdist = dist; | |
1058 | } | |
1059 | myMin3d = myMax3d = Sqrt(maxdist); | |
1060 | if (myMin3d > myPrecision) | |
1061 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
1062 | return LastCheckStatus (ShapeExtend_DONE); | |
1063 | } | |
1064 | ||
1065 | //======================================================================= | |
1066 | //function : CheckSelfIntersectingEdge | |
1067 | //purpose : | |
1068 | //======================================================================= | |
1069 | ||
1070 | // auxiliary function | |
1071 | //:h0 abv 29 May 98: PRO10105 1949: like in BRepCheck, point is to be taken | |
1072 | // from 3d curve (but only if edge is SameParameter) | |
1073 | static gp_Pnt GetPointOnEdge ( const TopoDS_Edge &edge, | |
1074 | const Handle(ShapeAnalysis_Surface) &surf, | |
94f71cad | 1075 | const Geom2dAdaptor_Curve &Crv2d, |
7fd59977 | 1076 | const Standard_Real param ) |
1077 | { | |
1078 | if ( BRep_Tool::SameParameter ( edge ) ) { | |
1079 | Standard_Real f,l; | |
1080 | TopLoc_Location L; | |
1081 | const Handle(Geom_Curve) ConS = BRep_Tool::Curve ( edge, L, f, l ); | |
1082 | if ( ! ConS.IsNull() ) | |
1083 | return ConS->Value ( param ).Transformed ( L.Transformation() ); | |
1084 | } | |
94f71cad | 1085 | gp_Pnt2d aP2d = Crv2d.Value(param); |
1086 | return surf->Adaptor3d()->Value(aP2d.X(), aP2d.Y()); | |
7fd59977 | 1087 | } |
1088 | ||
1089 | //======================================================================= | |
1090 | //function : CheckSelfIntersectingEdge | |
1091 | //purpose : | |
1092 | //======================================================================= | |
1093 | ||
1094 | Standard_Boolean ShapeAnalysis_Wire::CheckSelfIntersectingEdge (const Standard_Integer num, | |
1095 | IntRes2d_SequenceOfIntersectionPoint& points2d, | |
1096 | TColgp_SequenceOfPnt& points3d) | |
1097 | { | |
1098 | points2d.Clear(); | |
1099 | points3d.Clear(); | |
1100 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
1101 | if ( ! IsReady() ) return Standard_False; | |
1102 | ||
1103 | TopoDS_Edge edge = WireData()->Edge ( num >0 ? num : NbEdges() ); | |
1104 | ShapeAnalysis_Edge sae; | |
1105 | ||
1106 | Standard_Real a, b; | |
1107 | Handle(Geom2d_Curve) Crv; | |
1108 | if ( ! sae.PCurve ( edge, myFace, Crv, a, b, Standard_False ) ) { | |
1109 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
1110 | return Standard_False; | |
1111 | } | |
1112 | if ( Abs ( a - b ) <= ::Precision::PConfusion() ) return Standard_False; | |
1113 | ||
1114 | Standard_Real tolint = 1.0e-10; | |
1115 | //szv#4:S4163:12Mar99 warning | |
1116 | IntRes2d_Domain domain ( Crv->Value ( a ), a, tolint, Crv->Value ( b ), b, tolint ); | |
1117 | Geom2dAdaptor_Curve AC ( Crv ); | |
1118 | Geom2dInt_GInter Inter ( AC, domain, tolint, tolint ); | |
1119 | ||
1120 | if ( ! Inter.IsDone() ) return Standard_False; | |
1121 | ||
1122 | TopoDS_Vertex V1 = sae.FirstVertex ( edge ); | |
1123 | TopoDS_Vertex V2 = sae.LastVertex ( edge ); | |
1124 | if ( V1.IsNull() || V2.IsNull() ) { | |
1125 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
1126 | return Standard_False; | |
1127 | } | |
1128 | Standard_Real tol1 = BRep_Tool::Tolerance ( V1 ); | |
1129 | Standard_Real tol2 = BRep_Tool::Tolerance ( V2 ); | |
1130 | ||
1131 | gp_Pnt pnt1 = BRep_Tool::Pnt ( V1 ); | |
1132 | gp_Pnt pnt2 = BRep_Tool::Pnt ( V2 ); | |
1133 | ||
1134 | for ( Standard_Integer i=1; i <= Inter.NbPoints(); i++ ) { | |
1135 | const IntRes2d_IntersectionPoint &IP = Inter.Point ( i ); | |
1136 | const IntRes2d_Transition &Tr1 = IP.TransitionOfFirst(); | |
1137 | const IntRes2d_Transition &Tr2 = IP.TransitionOfSecond(); | |
1138 | if ( Tr1.PositionOnCurve() != IntRes2d_Middle && | |
1139 | Tr2.PositionOnCurve() != IntRes2d_Middle ) continue; | |
94f71cad | 1140 | gp_Pnt pint = GetPointOnEdge ( edge, mySurf, AC, IP.ParamOnFirst() ); |
7fd59977 | 1141 | Standard_Real dist21 = pnt1.SquareDistance ( pint ); |
1142 | Standard_Real dist22 = pnt2.SquareDistance ( pint ); | |
1143 | if ( dist21 > tol1 * tol1 && dist22 > tol2 * tol2 ) { | |
1144 | points2d.Append ( IP ); | |
1145 | points3d.Append ( pint ); | |
1146 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
1147 | } | |
1148 | } | |
1149 | ||
1150 | return LastCheckStatus ( ShapeExtend_DONE ); | |
1151 | } | |
1152 | ||
1153 | //======================================================================= | |
1154 | //function : CheckSelfIntersectingEdge | |
1155 | //purpose : | |
1156 | //======================================================================= | |
1157 | ||
1158 | Standard_Boolean ShapeAnalysis_Wire::CheckSelfIntersectingEdge (const Standard_Integer num) | |
1159 | { | |
1160 | IntRes2d_SequenceOfIntersectionPoint points2d; | |
1161 | TColgp_SequenceOfPnt points3d; | |
1162 | return CheckSelfIntersectingEdge ( num, points2d, points3d ); | |
1163 | } | |
1164 | ||
1165 | //======================================================================= | |
1166 | //function : CheckIntersectingEdges | |
1167 | //purpose : Test if two consequent edges are intersecting | |
1168 | // It is made in accordance with the following check in BRepCheck: | |
1169 | // - in BRepCheck_Wire::Orientation(), test for self-intersection | |
1170 | //======================================================================= | |
1171 | ||
1172 | Standard_Boolean ShapeAnalysis_Wire::CheckIntersectingEdges (const Standard_Integer num, | |
1173 | IntRes2d_SequenceOfIntersectionPoint& points2d, | |
1174 | TColgp_SequenceOfPnt& points3d, | |
1175 | TColStd_SequenceOfReal& errors) | |
1176 | { | |
1177 | points2d.Clear(); | |
1178 | points3d.Clear(); | |
1179 | errors.Clear(); | |
1180 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
1181 | if ( ! IsReady() || NbEdges() <2 ) return Standard_False; | |
1182 | ||
1183 | //szv#4:S4163:12Mar99 optimized | |
1184 | Standard_Integer n2 = (num > 0)? num : NbEdges(); | |
1185 | Standard_Integer n1 = (n2 > 1)? n2-1 : NbEdges(); | |
1186 | TopoDS_Edge edge1 = myWire->Edge ( n1 ); | |
1187 | TopoDS_Edge edge2 = myWire->Edge ( n2 ); | |
1188 | ||
1189 | ShapeAnalysis_Edge sae; | |
1190 | TopoDS_Vertex V1 = sae.LastVertex ( edge1 ); | |
1191 | TopoDS_Vertex V2 = sae.FirstVertex ( edge2 ); | |
1192 | if ( V1.IsNull() || V2.IsNull() ) { | |
1193 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
1194 | return Standard_False; | |
1195 | } | |
1196 | if ( ! BRepTools::Compare ( V1, V2 ) ) { | |
1197 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
1198 | return Standard_False; | |
1199 | } | |
1200 | ||
1201 | TopoDS_Vertex Vp = sae.FirstVertex ( edge1 ); | |
1202 | TopoDS_Vertex Vn = sae.LastVertex ( edge2 ); | |
1203 | ||
1204 | Standard_Real a1, b1, a2, b2; | |
1205 | Handle(Geom2d_Curve) Crv1, Crv2; | |
1206 | if ( ! sae.PCurve ( edge1, myFace, Crv1, a1, b1, Standard_False ) ) { | |
1207 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3); | |
1208 | return Standard_False; | |
1209 | } | |
1210 | if ( ! sae.PCurve ( edge2, myFace, Crv2, a2, b2, Standard_False ) ) { | |
1211 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3); | |
1212 | return Standard_False; | |
1213 | } | |
1214 | if ( Abs ( a1 - b1 ) <= ::Precision::PConfusion() || | |
1215 | Abs ( a2 - b2 ) <= ::Precision::PConfusion() ) return Standard_False; //:f7 abv 6 May 98: BUC50070 on #42276 | |
1216 | ||
1217 | Standard_Boolean isForward1 = ( edge1.Orientation() == TopAbs_FORWARD ); | |
1218 | Standard_Boolean isForward2 = ( edge2.Orientation() == TopAbs_FORWARD ); | |
1219 | ||
1220 | Standard_Real tol0 = Max ( BRep_Tool::Tolerance ( V1 ), BRep_Tool::Tolerance ( V2 ) ); | |
1221 | Standard_Real tol = tol0; | |
1222 | ||
1223 | gp_Pnt pnt = BRep_Tool::Pnt ( V1 ); | |
1224 | ||
1225 | // Standard_Boolean Status = Standard_False; | |
1226 | ||
1227 | Standard_Real tolint = 1.0e-10; | |
1228 | ||
1229 | //szv#4:S4163:12Mar99 warning | |
7fd59977 | 1230 | Geom2dAdaptor_Curve C1 ( Crv1 ), C2 ( Crv2 ); |
94f71cad | 1231 | IntRes2d_Domain d1 ( C1.Value ( a1 ), a1, tolint, |
1232 | C1.Value ( b1 ), b1, tolint ); | |
1233 | IntRes2d_Domain d2 ( C2.Value ( a2 ), a2, tolint, | |
1234 | C2.Value ( b2 ), b2, tolint ); | |
7fd59977 | 1235 | |
1236 | //:64 abv 25 Dec 97: Attention! | |
1237 | // Since Intersection algorithm is not symmetrical, for consistency with BRepCheck | |
316ea293 | 1238 | // edge with lower order number should be intersecting with edge with higher one |
7fd59977 | 1239 | // i.e., for intersection of last and first edges, they should go in reversed order |
1240 | // Example: entity #38285 from bug CSR #CTS17806 | |
1241 | // NOTE: Tr1 and Tr2 are not reordered because they are used in the same manner | |
1242 | Geom2dInt_GInter Inter; | |
1243 | if ( num ==1 ) Inter.Perform ( C2, d2, C1, d1, tolint, tolint ); | |
1244 | else Inter.Perform ( C1, d1, C2, d2, tolint, tolint ); | |
1245 | if ( ! Inter.IsDone() ) return Standard_False; | |
1246 | ||
1247 | //:86 abv 22 Jan 98: fix self-intersection even if tolerance of vertex is enough | |
1248 | // to annihilate it. This is done to prevent wrong effects if vertex tolerance | |
1249 | // will be decreased (e.g., in FixLacking) | |
1250 | Standard_Real tole = Max ( ( BRep_Tool::SameParameter ( edge1 ) ? | |
1251 | BRep_Tool::Tolerance ( edge1 ) : tol0 ), | |
1252 | ( BRep_Tool::SameParameter ( edge2 ) ? | |
1253 | BRep_Tool::Tolerance ( edge2 ) : tol0 ) ); | |
1254 | Standard_Real tolt = Min ( tol, Max ( tole, myPrecision ) ); | |
1255 | //Standard_Real prevRange1 = RealLast(), prevRange2 = RealLast(); //SK | |
1256 | Standard_Integer isLacking = -1; //:l0 abv: CATIA01 #1727: protect against adding lacking | |
1257 | //#83 rln 19.03.99 sim2.igs, entity 4292 | |
1258 | //processing also segments as in BRepCheck | |
1259 | Standard_Integer NbPoints = Inter.NbPoints(), NbSegments = Inter.NbSegments(); | |
1260 | for ( Standard_Integer i=1; i <= NbPoints + NbSegments; i++ ) { | |
1261 | IntRes2d_IntersectionPoint IP; | |
1262 | IntRes2d_Transition Tr1, Tr2; | |
1263 | if (i <= NbPoints) | |
1264 | IP = Inter.Point ( i ); | |
1265 | else { | |
1266 | const IntRes2d_IntersectionSegment &Seg = Inter.Segment ( i - NbPoints ); | |
1267 | if (!Seg.HasFirstPoint() || !Seg.HasLastPoint()) continue; | |
1268 | IP = Seg.FirstPoint(); | |
1269 | Tr1 = IP.TransitionOfFirst(); | |
1270 | Tr2 = IP.TransitionOfSecond(); | |
1271 | if (Tr1.PositionOnCurve() == IntRes2d_Middle || Tr2.PositionOnCurve() == IntRes2d_Middle) | |
1272 | IP = Seg.LastPoint(); | |
1273 | } | |
1274 | Tr1 = IP.TransitionOfFirst(); | |
1275 | Tr2 = IP.TransitionOfSecond(); | |
1276 | ||
1277 | if ( Tr1.PositionOnCurve() != IntRes2d_Middle && | |
1278 | Tr2.PositionOnCurve() != IntRes2d_Middle ) continue; | |
1279 | Standard_Real param1, param2; | |
1280 | param1 = ( num ==1 ? IP.ParamOnSecond() : IP.ParamOnFirst() ); | |
1281 | param2 = ( num ==1 ? IP.ParamOnFirst() : IP.ParamOnSecond() ); | |
1282 | ||
1283 | //:r6 abv 8 Apr 99: r_47-sd.stp #173850: protect against working out of curve range | |
1284 | if ( a1-param1 > ::Precision::PConfusion() || | |
1285 | param1-b1 > ::Precision::PConfusion() || | |
1286 | a2-param2 > ::Precision::PConfusion() || | |
1287 | param2-b2 > ::Precision::PConfusion() ) continue; | |
1288 | ||
1289 | //:82 abv 21 Jan 98: point of intersection on Crv1 and Crv2 is different | |
94f71cad | 1290 | gp_Pnt pi1 = GetPointOnEdge ( edge1, mySurf, C1, param1 ); //:h0: thesurf.Value ( Crv1->Value ( param1 ) ); |
1291 | gp_Pnt pi2 = GetPointOnEdge ( edge2, mySurf, C2, param2 ); //:h0: thesurf.Value ( Crv2->Value ( param2 ) ); | |
7fd59977 | 1292 | gp_Pnt pint = 0.5 * ( pi1.XYZ() + pi2.XYZ() ); |
1293 | Standard_Real di1 = pi1.SquareDistance ( pnt ); | |
1294 | Standard_Real di2 = pi2.SquareDistance ( pnt ); | |
1295 | Standard_Real dist2 = Max ( di1, di2 ); | |
1296 | ||
1297 | //rln 03/02/98: CSR#BUC50004 entity 56 (to avoid later inserting lacking edge) | |
1298 | if ( isLacking <0 ) { //:l0 | |
1299 | gp_Pnt2d end1 = Crv1->Value ( isForward1 ? b1 : a1 ); | |
1300 | gp_Pnt2d end2 = Crv2->Value ( isForward2 ? a2 : b2 ); | |
1301 | //:l0 Standard_Real distab2 = mySurf->Value ( end1 ).SquareDistance ( mySurf->Value ( end2 ) ); | |
1302 | //:l0: test like in BRepCheck | |
c22b52d6 | 1303 | GeomAdaptor_Surface& Ads = *mySurf->Adaptor3d(); |
7fd59977 | 1304 | Standard_Real tol2d = 2 * Max ( Ads.UResolution(tol), Ads.VResolution(tol) ); |
1305 | isLacking = ( end1.SquareDistance(end2) >= tol2d * tol2d ); | |
1306 | } | |
1307 | ||
1308 | if ( ( dist2 > tolt * tolt || //:86: tol -> tolt | |
1309 | isLacking ) && //:l0 | |
1310 | //:l0 distab2 > BRep_Tool::Tolerance ( edge1 ) + BRep_Tool::Tolerance ( edge2 ) ) && //rln | |
1311 | ( ! BRepTools::Compare ( Vp, Vn ) || //:63 | |
1312 | dist2 < pint.SquareDistance ( BRep_Tool::Pnt ( Vp ) ) ) ) { //:63 | |
1313 | points2d.Append ( IP ); | |
1314 | points3d.Append ( pint ); | |
1315 | errors.Append ( 0.5 * pi1.Distance ( pi2 ) ); | |
1316 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
1317 | } | |
1318 | } | |
1319 | ||
1320 | return LastCheckStatus ( ShapeExtend_DONE ); | |
1321 | } | |
1322 | ||
1323 | //======================================================================= | |
1324 | //function : CheckIntersectingEdges | |
1325 | //purpose : | |
1326 | //======================================================================= | |
1327 | ||
1328 | Standard_Boolean ShapeAnalysis_Wire::CheckIntersectingEdges (const Standard_Integer num) | |
1329 | { | |
1330 | IntRes2d_SequenceOfIntersectionPoint points2d; | |
1331 | TColgp_SequenceOfPnt points3d; | |
1332 | TColStd_SequenceOfReal errors; | |
1333 | return CheckIntersectingEdges ( num, points2d, points3d, errors ); | |
1334 | } | |
1335 | ||
1336 | //======================================================================= | |
1337 | //function : CheckIntersectingEdges | |
1338 | //purpose : | |
1339 | //======================================================================= | |
1340 | ||
1341 | Standard_Boolean ShapeAnalysis_Wire::CheckIntersectingEdges(const Standard_Integer num1, | |
1342 | const Standard_Integer num2, | |
1343 | IntRes2d_SequenceOfIntersectionPoint& points2d, | |
1344 | TColgp_SequenceOfPnt& points3d, | |
1345 | TColStd_SequenceOfReal& errors) | |
1346 | { | |
1347 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
1348 | if ( ! IsReady() ) return Standard_False; | |
1349 | Handle(ShapeExtend_WireData) sbwd = WireData(); | |
1350 | Standard_Integer n2 = ( num2 >0 ? num2 : sbwd->NbEdges() ); | |
1351 | Standard_Integer n1 = ( num1 >0 ? num1 : sbwd->NbEdges() ); | |
1352 | ||
1353 | TopoDS_Edge edge1 = sbwd->Edge ( n1 ); | |
1354 | TopoDS_Edge edge2 = sbwd->Edge ( n2 ); | |
1355 | ||
1356 | ShapeAnalysis_Edge sae; | |
1357 | Standard_Real a1, b1, a2, b2; | |
1358 | Handle(Geom2d_Curve) Crv1, Crv2; | |
1359 | if(!sae.PCurve ( edge1, myFace, Crv1, a1, b1, Standard_False )){ | |
1360 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3); | |
1361 | return Standard_False; | |
1362 | } | |
1363 | ||
1364 | if(!sae.PCurve ( edge2, myFace, Crv2, a2, b2, Standard_False )){ | |
1365 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3); | |
1366 | return Standard_False; | |
1367 | } | |
1368 | ||
1369 | if ( Abs ( a1 - b1 ) <= ::Precision::PConfusion() || | |
1370 | Abs ( a2 - b2 ) <= ::Precision::PConfusion() ) return Standard_False; | |
1371 | ||
1372 | points2d.Clear(); | |
1373 | points3d.Clear(); | |
1374 | errors.Clear(); | |
1375 | TColgp_Array1OfPnt vertexPoints(1,4); | |
1376 | TColStd_Array1OfReal vertexTolers(1,4); | |
1377 | vertexPoints(1) = BRep_Tool::Pnt(sae.FirstVertex(edge1)); | |
1378 | vertexTolers(1) = BRep_Tool::Tolerance(sae.FirstVertex(edge1)); | |
1379 | vertexPoints(2) = BRep_Tool::Pnt(sae.LastVertex(edge1)); | |
1380 | vertexTolers(2) = BRep_Tool::Tolerance(sae.LastVertex(edge1)); | |
1381 | vertexPoints(3) = BRep_Tool::Pnt(sae.FirstVertex(edge2)); | |
1382 | vertexTolers(3) = BRep_Tool::Tolerance(sae.FirstVertex(edge2)); | |
1383 | vertexPoints(4) = BRep_Tool::Pnt(sae.LastVertex(edge2)); | |
1384 | vertexTolers(4) = BRep_Tool::Tolerance(sae.LastVertex(edge2)); | |
1385 | ||
1386 | Standard_Real tolint = 1.0e-10; | |
1387 | ||
1388 | IntRes2d_Domain d1 ( Crv1->Value ( a1 ), a1, tolint, | |
1389 | Crv1->Value ( b1 ), b1, tolint ); | |
1390 | IntRes2d_Domain d2 ( Crv2->Value ( a2 ), a2, tolint, | |
1391 | Crv2->Value ( b2 ), b2, tolint ); | |
1392 | Geom2dAdaptor_Curve C1 ( Crv1 ), C2 ( Crv2 ); | |
1393 | ||
1394 | Geom2dInt_GInter Inter; | |
1395 | Inter.Perform ( C1, d1, C2, d2, tolint, tolint ); | |
1396 | if ( ! Inter.IsDone() ) return Standard_False; | |
1397 | ||
1398 | //#83 rln 19.03.99 sim2.igs, entity 4292 | |
1399 | //processing also segments as in BRepCheck | |
1400 | Standard_Integer NbPoints = Inter.NbPoints(), NbSegments = Inter.NbSegments(); | |
1401 | for ( Standard_Integer i=1; i <= NbPoints + NbSegments; i++ ) { | |
1402 | IntRes2d_IntersectionPoint IP; | |
1403 | IntRes2d_Transition Tr1, Tr2; | |
1404 | if (i <= NbPoints) | |
1405 | IP = Inter.Point ( i ); | |
1406 | else { | |
1407 | const IntRes2d_IntersectionSegment &Seg = Inter.Segment ( i - NbPoints ); | |
1408 | if (!Seg.HasFirstPoint() || !Seg.HasLastPoint()) continue; | |
1409 | IP = Seg.FirstPoint(); | |
1410 | Tr1 = IP.TransitionOfFirst(); | |
1411 | Tr2 = IP.TransitionOfSecond(); | |
1412 | if (Tr1.PositionOnCurve() == IntRes2d_Middle || Tr2.PositionOnCurve() == IntRes2d_Middle) | |
1413 | IP = Seg.LastPoint(); | |
1414 | } | |
1415 | Tr1 = IP.TransitionOfFirst(); | |
1416 | Tr2 = IP.TransitionOfSecond(); | |
1417 | if ( Tr1.PositionOnCurve() != IntRes2d_Middle && | |
1418 | Tr2.PositionOnCurve() != IntRes2d_Middle ) continue; | |
1419 | Standard_Real param1 = IP.ParamOnFirst(); | |
1420 | Standard_Real param2 = IP.ParamOnSecond(); | |
94f71cad | 1421 | gp_Pnt pi1 = GetPointOnEdge ( edge1, mySurf, C1, param1 ); //:h0: thesurf.Value ( Crv1->Value ( param1 ) ); |
1422 | gp_Pnt pi2 = GetPointOnEdge ( edge2, mySurf, C2, param2 ); | |
16a1f265 | 1423 | Standard_Boolean OK1 = Standard_False; |
1424 | Standard_Boolean OK2 = Standard_False; | |
1425 | ||
1426 | for(Standard_Integer j=1; (j<=2)&&!OK1; j++) { | |
7fd59977 | 1427 | Standard_Real di1 = pi1.SquareDistance (vertexPoints(j)); |
16a1f265 | 1428 | if(di1 < vertexTolers(j) * vertexTolers(j)) |
1429 | OK1 = Standard_True; | |
1430 | } | |
1431 | ||
1432 | for(Standard_Integer j=3; (j<=4)&&!OK2; j++) { | |
7fd59977 | 1433 | Standard_Real di2 = pi2.SquareDistance (vertexPoints(j)); |
16a1f265 | 1434 | if(di2 < vertexTolers(j) * vertexTolers(j)) |
1435 | OK2 = Standard_True; | |
7fd59977 | 1436 | } |
16a1f265 | 1437 | |
1438 | if(!OK1 || !OK2) { | |
7fd59977 | 1439 | gp_Pnt pint = 0.5 * ( pi1.XYZ() + pi2.XYZ() ); |
1440 | points2d.Append ( IP ); | |
1441 | points3d.Append ( pint ); | |
1442 | errors.Append ( 0.5 * pi1.Distance ( pi2 ) ); | |
1443 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
1444 | } | |
1445 | } | |
1446 | return LastCheckStatus ( ShapeExtend_DONE ); | |
1447 | } | |
1448 | ||
1449 | //======================================================================= | |
1450 | //function : CheckIntersectingEdges | |
1451 | //purpose : | |
1452 | //======================================================================= | |
1453 | ||
1454 | Standard_Boolean ShapeAnalysis_Wire::CheckIntersectingEdges (const Standard_Integer num1, | |
1455 | const Standard_Integer num2) | |
1456 | { | |
1457 | IntRes2d_SequenceOfIntersectionPoint points2d; | |
1458 | TColgp_SequenceOfPnt points3d; | |
1459 | TColStd_SequenceOfReal errors; | |
1460 | return CheckIntersectingEdges(num1, num2, points2d, points3d, errors); | |
1461 | } | |
1462 | ||
1463 | //======================================================================= | |
1464 | //function : CheckLacking | |
1465 | //purpose : Test if two edges are disconnected in 2d according to the | |
1466 | // Adaptor_Surface::Resolution | |
1467 | //======================================================================= | |
1468 | ||
1469 | Standard_Boolean ShapeAnalysis_Wire::CheckLacking (const Standard_Integer num, | |
1470 | const Standard_Real Tolerance, | |
1471 | gp_Pnt2d &p2d1, gp_Pnt2d &p2d2) | |
1472 | { | |
1473 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
1474 | if ( ! IsReady() ) return Standard_False; | |
1475 | ||
1476 | //szv#4:S4163:12Mar99 optimized | |
1477 | Standard_Integer n2 = (num > 0)? num : NbEdges(); | |
1478 | Standard_Integer n1 = (n2 > 1)? n2-1 : NbEdges(); | |
1479 | TopoDS_Edge E1 = myWire->Edge ( n1 ); | |
1480 | TopoDS_Edge E2 = myWire->Edge ( n2 ); | |
1481 | ||
1482 | ShapeAnalysis_Edge sae; | |
1483 | TopoDS_Vertex V1 = sae.LastVertex ( E1 ); | |
1484 | TopoDS_Vertex V2 = sae.FirstVertex ( E2 ); | |
1485 | // CKY 4 MAR 1998 : protection against null vertex | |
1486 | if ( V1.IsNull() || V2.IsNull() ) { | |
1487 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
1488 | return Standard_False; | |
1489 | } | |
1490 | if ( ! BRepTools::Compare ( V1, V2 ) ) { | |
1491 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
1492 | return Standard_False; | |
1493 | } | |
1494 | ||
1495 | Standard_Real a, b; | |
1496 | gp_Vec2d v1, v2, v12; | |
1497 | Handle(Geom2d_Curve) c2d; | |
1498 | if ( ! sae.PCurve ( E1, myFace, c2d, a, b, Standard_True ) ) { | |
1499 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3); | |
1500 | return Standard_False; | |
1501 | } | |
94f71cad | 1502 | Geom2dAdaptor_Curve anAdapt(c2d); |
1503 | anAdapt.D1(b, p2d1, v1); | |
7fd59977 | 1504 | if ( E1.Orientation() == TopAbs_REVERSED ) v1.Reverse(); |
1505 | if ( ! sae.PCurve ( E2, myFace, c2d, a, b, Standard_True ) ) { | |
1506 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3); | |
1507 | return Standard_False; | |
1508 | } | |
94f71cad | 1509 | anAdapt.Load(c2d); |
1510 | anAdapt.D1(a, p2d2, v2); | |
7fd59977 | 1511 | if ( E2.Orientation() == TopAbs_REVERSED ) v2.Reverse(); |
1512 | v12 = p2d2.XY() - p2d1.XY(); | |
1513 | myMax2d = v12.SquareMagnitude(); | |
1514 | ||
1515 | // test like in BRepCheck | |
1516 | Standard_Real tol = Max ( BRep_Tool::Tolerance ( V1 ), BRep_Tool::Tolerance ( V2 ) ); | |
1517 | tol = ( Tolerance > gp::Resolution() && Tolerance < tol ? Tolerance : tol ); | |
c22b52d6 | 1518 | GeomAdaptor_Surface& Ads = *mySurf->Adaptor3d(); |
7fd59977 | 1519 | Standard_Real tol2d = 2 * Max ( Ads.UResolution(tol), Ads.VResolution(tol) ); |
1520 | if ( // tol2d < gp::Resolution() || //#2 smh 26.03.99 S4163 Zero divide | |
1521 | myMax2d < tol2d * tol2d ) return Standard_False; | |
1522 | ||
1523 | myMax2d = Sqrt ( myMax2d ); | |
1524 | myMax3d = tol * myMax2d / Max ( tol2d, gp::Resolution() ); | |
1525 | myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 ); | |
1526 | ||
1527 | if ( myMax2d < Precision::PConfusion() || //:abv 03.06.02 CTS21866.stp | |
c6541a0c D |
1528 | ( v1.SquareMagnitude() > gp::Resolution() && Abs ( v12.Angle ( v1 ) ) > 0.9 * M_PI ) || |
1529 | ( v2.SquareMagnitude() > gp::Resolution() && Abs ( v12.Angle ( v2 ) ) > 0.9 * M_PI ) ) | |
7fd59977 | 1530 | myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 ); |
1531 | return Standard_True; | |
1532 | } | |
1533 | ||
1534 | //======================================================================= | |
1535 | //function : CheckLacking | |
1536 | //purpose : | |
1537 | // | |
1538 | //======================================================================= | |
1539 | ||
1540 | Standard_Boolean ShapeAnalysis_Wire::CheckLacking (const Standard_Integer num, | |
1541 | const Standard_Real Tolerance) | |
1542 | { | |
1543 | gp_Pnt2d p1, p2; | |
1544 | return CheckLacking (num, Tolerance, p1, p2); | |
1545 | } | |
1546 | ||
1547 | //======================================================================= | |
1548 | //function : CheckOuterBound | |
1549 | //purpose : | |
1550 | //======================================================================= | |
1551 | ||
1552 | Standard_Boolean ShapeAnalysis_Wire::CheckOuterBound(const Standard_Boolean APIMake) | |
1553 | { | |
1554 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
1555 | if ( ! IsReady() ) return Standard_False; | |
1556 | ||
1557 | TopoDS_Wire wire; | |
1558 | if (APIMake) wire = myWire->WireAPIMake(); | |
1559 | else wire = myWire->Wire(); | |
1560 | ||
1561 | TopoDS_Shape sh = myFace.EmptyCopied(); //szv#4:S4163:12Mar99 SGI warns | |
1562 | TopoDS_Face face = TopoDS::Face(sh); | |
1563 | BRep_Builder B; | |
1564 | B.Add (face, wire); | |
1565 | if (ShapeAnalysis::IsOuterBound (face)) return Standard_False; | |
1566 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
1567 | return Standard_True; | |
1568 | } | |
1569 | ||
1570 | //======================================================================= | |
1571 | //function : CheckNotchedEdges | |
1572 | //purpose : | |
1573 | //======================================================================= | |
1574 | ||
1575 | static Standard_Real ProjectInside(const Adaptor3d_CurveOnSurface AD, | |
1576 | const gp_Pnt pnt, | |
1577 | const Standard_Real preci, | |
1578 | gp_Pnt& proj, | |
1579 | Standard_Real& param, | |
1580 | const Standard_Boolean adjustToEnds = Standard_True) | |
1581 | { | |
1582 | ShapeAnalysis_Curve sac; | |
1583 | Standard_Real dist = sac.Project(AD,pnt,preci,proj,param,adjustToEnds); | |
1584 | Standard_Real uFirst = AD.FirstParameter(); | |
1585 | Standard_Real uLast = AD.LastParameter(); | |
1586 | if(param<uFirst) { | |
1587 | param = uFirst; | |
1588 | proj = AD.Value(uFirst); | |
1589 | return proj.Distance(pnt); | |
1590 | } | |
1591 | ||
1592 | if(param>uLast) { | |
1593 | param = uLast; | |
1594 | proj = AD.Value(uLast); | |
1595 | return proj.Distance(pnt); | |
1596 | } | |
1597 | return dist; | |
1598 | } | |
1599 | ||
1600 | Standard_Boolean ShapeAnalysis_Wire::CheckNotchedEdges(const Standard_Integer num, | |
1601 | Standard_Integer& shortNum, | |
1602 | Standard_Real& param, | |
1603 | const Standard_Real Tolerance) | |
1604 | { | |
1605 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); | |
1606 | if ( ! IsReady() ) return Standard_False; | |
1607 | ||
1608 | Standard_Integer n2 = (num > 0)? num : NbEdges(); | |
1609 | Standard_Integer n1 = (n2 > 1)? n2-1 : NbEdges(); | |
1610 | TopoDS_Edge E1 = myWire->Edge ( n1 ); | |
1611 | TopoDS_Edge E2 = myWire->Edge ( n2 ); | |
1612 | ||
1613 | if(BRep_Tool::Degenerated(E1)||BRep_Tool::Degenerated(E2)) | |
1614 | return Standard_False; | |
1615 | ||
1616 | ShapeAnalysis_Edge sae; | |
1617 | TopoDS_Vertex V1 = sae.LastVertex ( E1 ); | |
1618 | TopoDS_Vertex V2 = sae.FirstVertex ( E2 ); | |
1619 | ||
1620 | if ( V1.IsNull() || V2.IsNull() ) { | |
1621 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
1622 | return Standard_False; | |
1623 | } | |
1624 | if ( ! BRepTools::Compare ( V1, V2 ) ) { | |
1625 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
1626 | return Standard_False; | |
1627 | } | |
1628 | ||
1629 | Standard_Real a1, b1, a2, b2; | |
1630 | gp_Pnt2d p2d1, p2d2; | |
1631 | gp_Vec2d v1, v2; | |
1632 | Handle(Geom2d_Curve) c2d1, c2d2; | |
1633 | if ( ! sae.PCurve ( E1, myFace, c2d1, a1, b1, Standard_False ) ) { | |
1634 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3); | |
1635 | return Standard_False; | |
1636 | } | |
1637 | ||
1638 | if(E1.Orientation()==TopAbs_REVERSED) | |
1639 | c2d1->D1 ( a1, p2d1, v1 ); | |
1640 | else { | |
1641 | c2d1->D1 ( b1, p2d1, v1 ); | |
1642 | v1.Reverse(); | |
1643 | } | |
1644 | ||
1645 | if ( ! sae.PCurve ( E2, myFace, c2d2, a2, b2, Standard_False ) ) { | |
1646 | myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL3); | |
1647 | return Standard_False; | |
1648 | } | |
1649 | if(E2.Orientation()==TopAbs_REVERSED) { | |
1650 | c2d2->D1 ( b2, p2d2, v2 ); | |
1651 | v2.Reverse(); | |
1652 | } | |
1653 | else | |
1654 | c2d2->D1 ( a2, p2d2, v2 ); | |
1655 | ||
1656 | if ( v2.Magnitude() < gp::Resolution() || v1.Magnitude() < gp::Resolution()) | |
1657 | return Standard_False; | |
1658 | ||
1659 | if ( Abs ( v2.Angle ( v1 ) ) > 0.1 || p2d1.Distance(p2d2) > Tolerance) | |
1660 | return Standard_False; | |
1661 | ||
c22b52d6 | 1662 | Handle(Geom2dAdaptor_Curve) AC2d1 = new Geom2dAdaptor_Curve(c2d1,a1,b1); |
1663 | Handle(GeomAdaptor_Surface) AdS1 = new GeomAdaptor_Surface(new Geom_Plane(gp_Pln())); | |
7fd59977 | 1664 | Adaptor3d_CurveOnSurface Ad1(AC2d1,AdS1); |
1665 | ||
c22b52d6 | 1666 | Handle(Geom2dAdaptor_Curve) AC2d2 = new Geom2dAdaptor_Curve(c2d2,a2,b2); |
1667 | Handle(GeomAdaptor_Surface) AdS2 = new GeomAdaptor_Surface(new Geom_Plane(gp_Pln())); | |
7fd59977 | 1668 | Adaptor3d_CurveOnSurface Ad2(AC2d2,AdS2); |
1669 | ||
1670 | Adaptor3d_CurveOnSurface longAD, shortAD; | |
1671 | Standard_Real lenP, firstP; | |
1672 | ||
1673 | ShapeAnalysis_Curve sac; | |
1674 | ||
1675 | gp_Pnt Proj1, Proj2; | |
bbf32d01 | 1676 | Standard_Real param1 = 0., param2 = 0.; |
7fd59977 | 1677 | p2d2=c2d2->Value(E2.Orientation()==TopAbs_FORWARD ? b2 : a2); |
1678 | p2d1=c2d1->Value(E1.Orientation()==TopAbs_FORWARD ? a1 : b1); | |
1679 | Standard_Real dist1 = ProjectInside(Ad1,gp_Pnt(p2d2.X(),p2d2.Y(),0),Tolerance,Proj1,param1,Standard_False); | |
1680 | Standard_Real dist2 = ProjectInside(Ad2,gp_Pnt(p2d1.X(),p2d1.Y(),0),Tolerance,Proj2,param2,Standard_False); | |
1681 | ||
1682 | if ( dist1 > Tolerance && dist2 > Tolerance) | |
1683 | return Standard_False; | |
1684 | ||
1685 | if (dist1 < dist2 ) { | |
1686 | shortAD = Ad2; | |
1687 | longAD = Ad1; | |
1688 | lenP = b2 - a2; | |
1689 | firstP = a2; | |
1690 | shortNum=n2; | |
1691 | param=param1; | |
1692 | ||
1693 | } | |
1694 | else { | |
1695 | shortAD = Ad1; | |
1696 | longAD = Ad2; | |
1697 | lenP = b1 - a1; | |
1698 | firstP = a1; | |
1699 | shortNum=n1; | |
1700 | param=param2; | |
1701 | } | |
1702 | ||
1703 | Standard_Real step = lenP/23; | |
1704 | for (Standard_Integer i = 1; i < 23; i++,firstP+=step) { | |
1705 | Standard_Real d1 = sac.Project(longAD,shortAD.Value(firstP),Tolerance,Proj1,param1); | |
1706 | if (d1 > Tolerance) { | |
1707 | return Standard_False; | |
1708 | } | |
1709 | } | |
1710 | ||
1711 | return Standard_True; | |
1712 | } | |
1713 | ||
1714 | //======================================================================= | |
1715 | //function : CheckSmallArea | |
1716 | //purpose : | |
1717 | //======================================================================= | |
8b1e055f | 1718 | Standard_Boolean ShapeAnalysis_Wire::CheckSmallArea(const TopoDS_Wire& theWire) |
7fd59977 | 1719 | { |
1720 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
56a9db93 | 1721 | const Standard_Integer aNbControl = 23; |
1722 | const Standard_Integer NbEdges = myWire->NbEdges(); | |
1723 | if ( !IsReady() || NbEdges < 1 ) | |
1724 | return Standard_False; | |
7fd59977 | 1725 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); |
56a9db93 | 1726 | |
1727 | Standard_Real aF, aL, aLength(0.0); | |
1728 | const Standard_Real anInv = 1.0 / static_cast<Standard_Real>(aNbControl - 1); | |
1729 | gp_XY aCenter2d(0., 0.); | |
1730 | ||
1731 | // try to find mid point for closed contour | |
1732 | Handle(Geom2d_Curve) aCurve2d; | |
1733 | for (Standard_Integer j = 1; j <= NbEdges; ++j) | |
1734 | { | |
1735 | const ShapeAnalysis_Edge anAnalyzer; | |
1736 | if (!anAnalyzer.PCurve(myWire->Edge(j),myFace,aCurve2d,aF,aL)) | |
1737 | { | |
7fd59977 | 1738 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); |
1739 | return Standard_False; | |
1740 | } | |
56a9db93 | 1741 | |
1742 | for (Standard_Integer i = 1; i < aNbControl; ++i) | |
1743 | { | |
1744 | const Standard_Real aV = anInv * ((aNbControl - 1 - i) * aF+ i * aL); | |
1745 | aCenter2d += aCurve2d->Value(aV).XY(); | |
1746 | } | |
1747 | } | |
1748 | aCenter2d *= 1.0 / static_cast<Standard_Real>(NbEdges * (aNbControl - 1)); | |
1749 | ||
1750 | // check approximated area in 3D | |
1751 | gp_Pnt aPnt3d; | |
1752 | gp_XYZ aPrev3d, aCross(0., 0., 0.); | |
1753 | gp_XYZ aCenter(mySurf->Value(aCenter2d.X(), aCenter2d.Y()).XYZ()); | |
1754 | ||
1755 | Handle(Geom_Curve) aCurve3d; | |
1756 | for (Standard_Integer j = 1; j <= NbEdges; ++j) | |
1757 | { | |
1758 | const ShapeAnalysis_Edge anAnalizer; | |
1759 | if (!anAnalizer.Curve3d(myWire->Edge(j), aCurve3d, aF, aL)) | |
1760 | { | |
1761 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
1762 | return Standard_False; | |
7fd59977 | 1763 | } |
f4dee9bb | 1764 | if (Precision::IsInfinite(aF) || Precision::IsInfinite(aL)) |
1765 | { | |
1766 | continue; | |
1767 | } | |
56a9db93 | 1768 | |
1769 | Standard_Integer aBegin = 0; | |
1770 | if (j == 1) | |
1771 | { | |
1772 | aBegin = 1; | |
1773 | aPnt3d = aCurve3d->Value(aF); | |
1774 | aPrev3d = aPnt3d.XYZ() - aCenter; | |
1775 | } | |
1776 | for (Standard_Integer i = aBegin; i < aNbControl; ++i) | |
1777 | { | |
1778 | const Standard_Real anU = | |
1779 | anInv * ( (aNbControl - 1 - i) * aF + i * aL ); | |
1780 | const gp_Pnt aPnt = aCurve3d->Value(anU); | |
1781 | const gp_XYZ& aCurrent = aPnt.XYZ(); | |
1782 | const gp_XYZ aVec = aCurrent - aCenter; | |
1783 | ||
1784 | aCross += aPrev3d ^ aVec; | |
1785 | aLength += aPnt3d.Distance(aPnt); | |
1786 | ||
1787 | aPnt3d = aPnt; | |
1788 | aPrev3d = aVec; | |
7fd59977 | 1789 | } |
1790 | } | |
56a9db93 | 1791 | |
1792 | Standard_Real aTolerance = aLength * myPrecision; | |
1793 | if ( aCross.Modulus() < aTolerance ) | |
1794 | { | |
1795 | // check real area in 3D | |
1796 | GProp_GProps aProps; | |
1797 | GProp_GProps aLProps; | |
8b1e055f | 1798 | TopoDS_Face aFace = TopoDS::Face(myFace.EmptyCopied()); |
1799 | BRep_Builder().Add(aFace, theWire); | |
1800 | BRepGProp::SurfaceProperties(aFace, aProps); | |
1801 | BRepGProp::LinearProperties(aFace, aLProps); | |
56a9db93 | 1802 | |
1803 | Standard_Real aNewTolerance = aLProps.Mass() * myPrecision; | |
8b1e055f | 1804 | if ( Abs(aProps.Mass()) < 0.5 * aNewTolerance ) |
56a9db93 | 1805 | { |
1806 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
1807 | return Standard_True; | |
1808 | } | |
7fd59977 | 1809 | } |
56a9db93 | 1810 | |
7fd59977 | 1811 | return Standard_False; |
1812 | } | |
1813 | ||
1814 | //======================================================================= | |
1815 | //function : CheckShapeConnect | |
1816 | //purpose : | |
1817 | //======================================================================= | |
1818 | ||
1819 | Standard_Boolean ShapeAnalysis_Wire::CheckShapeConnect(const TopoDS_Shape& shape,const Standard_Real prec) | |
1820 | { | |
1821 | Standard_Real tailhead, tailtail, headhead, headtail; | |
1822 | return CheckShapeConnect (tailhead, tailtail, headtail, headhead, shape, prec); | |
1823 | } | |
1824 | ||
1825 | //======================================================================= | |
1826 | //function : CheckShapeConnect | |
1827 | //purpose : | |
1828 | //======================================================================= | |
1829 | ||
1830 | Standard_Boolean ShapeAnalysis_Wire::CheckShapeConnect(Standard_Real& tailhead, Standard_Real& tailtail, | |
1831 | Standard_Real& headtail, Standard_Real& headhead, | |
1832 | const TopoDS_Shape& shape, const Standard_Real prec) | |
1833 | { | |
1834 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1); | |
1835 | if (!IsLoaded () || shape.IsNull()) return Standard_False; | |
1836 | TopoDS_Vertex V1,V2; | |
1837 | TopoDS_Edge E; TopoDS_Wire W; | |
1838 | ShapeAnalysis_Edge SAE; | |
1839 | if (shape.ShapeType() == TopAbs_EDGE) { | |
1840 | E = TopoDS::Edge (shape); | |
1841 | V1 = SAE.FirstVertex (E); V2 = SAE.LastVertex (E); | |
1842 | } else if (shape.ShapeType() == TopAbs_WIRE) { | |
1843 | W = TopoDS::Wire (shape); | |
1844 | ShapeAnalysis::FindBounds (W,V1,V2); | |
1845 | } | |
1846 | else return Standard_False; | |
1847 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
1848 | // on va comparer les points avec ceux de thevfirst et thevlast | |
1849 | gp_Pnt p1 = BRep_Tool::Pnt(V1); | |
1850 | gp_Pnt p2 = BRep_Tool::Pnt(V2); | |
1851 | ||
1852 | TopoDS_Vertex vfirst = SAE.FirstVertex (myWire->Edge (1)), | |
1853 | vlast = SAE.LastVertex (myWire->Edge (NbEdges())); | |
1854 | gp_Pnt pf = BRep_Tool::Pnt(vfirst); | |
1855 | gp_Pnt pl = BRep_Tool::Pnt(vlast); | |
1856 | ||
1857 | tailhead = p1.Distance(pl); | |
1858 | tailtail = p2.Distance(pl); | |
1859 | headhead = p1.Distance(pf); | |
1860 | headtail = p2.Distance(pf); | |
1861 | Standard_Real dm1 = tailhead, dm2 = headtail; | |
1862 | Standard_Integer res1 = 0, res2 = 0; | |
1863 | ||
1864 | if (tailhead > tailtail) {res1 = 1; dm1 = tailtail;} | |
1865 | if (headtail > headhead) {res2 = 1; dm2 = headhead;} | |
1866 | Standard_Integer result = res1; | |
1867 | myMin3d = Min (dm1, dm2); | |
1868 | myMax3d = Max (dm1, dm2); | |
1869 | if (dm1 > dm2) {dm1 = dm2; result = res2 + 2;} | |
1870 | switch (result) { | |
1871 | case 1: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); break; | |
1872 | case 2: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE3); break; | |
1873 | case 3: myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE4); break; | |
1874 | } | |
1875 | if (!res1) myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE5); | |
1876 | if (!res2) myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE6); | |
1877 | ||
1878 | if (myMin3d > Max (myPrecision, prec)) | |
1879 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
1880 | return LastCheckStatus (ShapeExtend_DONE); | |
1881 | } | |
1882 | ||
1883 | //======================================================================= | |
1884 | //function : CheckLoop | |
1885 | //purpose : | |
1886 | //======================================================================= | |
1887 | Standard_Boolean isMultiVertex(const TopTools_ListOfShape& alshape, | |
1888 | const TopTools_MapOfShape& aMapSmallEdges, | |
1889 | const TopTools_MapOfShape& aMapSeemEdges) | |
1890 | { | |
1891 | TopTools_ListIteratorOfListOfShape lIt1(alshape); | |
1892 | Standard_Integer nbNotAccount =0; | |
1893 | ||
1894 | for( ; lIt1.More() ; lIt1.Next()) | |
1895 | { | |
1896 | if(aMapSmallEdges.Contains(lIt1.Value())) | |
1897 | nbNotAccount++; | |
1898 | else if(aMapSeemEdges.Contains(lIt1.Value())) | |
1899 | nbNotAccount++; | |
1900 | } | |
1901 | return ((alshape.Extent() -nbNotAccount) >2); | |
1902 | } | |
1903 | Standard_Boolean ShapeAnalysis_Wire::CheckLoop(TopTools_IndexedMapOfShape& aMapLoopVertices, | |
1904 | TopTools_DataMapOfShapeListOfShape& aMapVertexEdges, | |
1905 | TopTools_MapOfShape& aMapSmallEdges, | |
1906 | TopTools_MapOfShape& aMapSeemEdges) | |
1907 | { | |
1908 | myStatus = ShapeExtend::EncodeStatus(ShapeExtend_OK); | |
1909 | if (!IsLoaded() || NbEdges() < 2) return Standard_False; | |
1910 | Standard_Real aSavPreci = Precision(); | |
1911 | SetPrecision(Precision::Infinite()); | |
1912 | Standard_Integer i =1; | |
1913 | ||
1914 | for( ; i <= myWire->NbEdges(); i++) { | |
1915 | TopoDS_Edge aedge = myWire->Edge(i); | |
1916 | TopoDS_Vertex aV1,aV2; | |
1917 | TopExp::Vertices(aedge,aV1,aV2); | |
29582444 | 1918 | if (aV1.IsNull() || aV2.IsNull()) |
1919 | { | |
1920 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2); | |
1921 | return Standard_False; | |
1922 | } | |
7fd59977 | 1923 | Standard_Boolean isSame = aV1.IsSame(aV2); |
1924 | if(myWire->IsSeam(i)) | |
1925 | aMapSeemEdges.Add(aedge); ///continue; | |
1926 | else if(BRep_Tool::Degenerated(aedge)) | |
1927 | aMapSmallEdges.Add(aedge); | |
1928 | else if(isSame && CheckSmall(i,BRep_Tool::Tolerance(aV1))) | |
1929 | aMapSmallEdges.Add(aedge); | |
1930 | ||
1931 | if(!aMapVertexEdges.IsBound(aV1)) { | |
1932 | TopTools_ListOfShape alshape; | |
1933 | aMapVertexEdges.Bind(aV1,alshape); | |
1934 | } | |
1935 | if(!aMapVertexEdges.IsBound(aV2)) { | |
1936 | TopTools_ListOfShape alshape; | |
1937 | aMapVertexEdges.Bind(aV2,alshape); | |
1938 | } | |
1939 | if(isSame) | |
1940 | { | |
1941 | TopTools_ListOfShape& alshape = aMapVertexEdges.ChangeFind(aV1); | |
1942 | alshape.Append(aedge); | |
1943 | alshape.Append(aedge); | |
1944 | if(alshape.Extent() >2 && isMultiVertex( alshape,aMapSmallEdges,aMapSeemEdges)) | |
1945 | aMapLoopVertices.Add(aV1); | |
1946 | } | |
1947 | else { | |
1948 | TopTools_ListOfShape& alshape = aMapVertexEdges.ChangeFind(aV1); | |
1949 | alshape.Append(aedge); | |
1950 | if(alshape.Extent() >2 && isMultiVertex( alshape,aMapSmallEdges,aMapSeemEdges)) | |
1951 | aMapLoopVertices.Add(aV1); | |
1952 | TopTools_ListOfShape& alshape2 = aMapVertexEdges.ChangeFind(aV2); | |
1953 | alshape2.Append(aedge); | |
1954 | if(alshape2.Extent() >2 && isMultiVertex( alshape2,aMapSmallEdges,aMapSeemEdges)) | |
1955 | aMapLoopVertices.Add(aV2); | |
1956 | } | |
1957 | } | |
1958 | SetPrecision(aSavPreci); | |
1959 | if(aMapLoopVertices.Extent()) | |
1960 | { | |
1961 | myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); | |
1962 | myStatusLoop |= myStatus; | |
1963 | return Standard_True; | |
1964 | } | |
1965 | return Standard_False; | |
1966 | } | |
fbf3becf | 1967 | |
1968 | //======================================================================= | |
1969 | //function : Project | |
1970 | //purpose : | |
1971 | //======================================================================= | |
1972 | static Standard_Real Project( | |
1973 | const Handle(Geom_Curve)& theCurve, | |
1974 | const Standard_Real theFirstParameter, | |
1975 | const Standard_Real theLastParameter, | |
1976 | const gp_Pnt& thePoint, | |
1977 | const Standard_Real thePrecision, | |
1978 | Standard_Real& theParameter, | |
1979 | gp_Pnt& theProjection) | |
1980 | { | |
1981 | const Standard_Real aDist = ShapeAnalysis_Curve().Project(theCurve, thePoint, | |
1982 | thePrecision, theProjection, theParameter, theFirstParameter, | |
1983 | theLastParameter); | |
1984 | if (theParameter >= theFirstParameter && theParameter <= theLastParameter) | |
1985 | { | |
1986 | return aDist; | |
1987 | } | |
1988 | ||
1989 | const Standard_Real aParams[] = {theFirstParameter, theLastParameter}; | |
1990 | const gp_Pnt aPrjs[] = | |
1991 | {theCurve->Value(aParams[0]), theCurve->Value(aParams[1])}; | |
1992 | const Standard_Real aDists[] = | |
1993 | {thePoint.Distance(aPrjs[0]), thePoint.Distance(aPrjs[1])}; | |
1994 | const Standard_Integer aPI = (aDists[0] <= aDists[1]) ? 0 : 1; | |
1995 | theParameter = aParams[aPI]; | |
1996 | theProjection = aPrjs[aPI]; | |
1997 | return aDists[aPI]; | |
1998 | } | |
1999 | ||
2000 | //======================================================================= | |
2001 | //function : CheckTail | |
2002 | //purpose : | |
2003 | //======================================================================= | |
2004 | Standard_Boolean ShapeAnalysis_Wire::CheckTail( | |
2005 | const TopoDS_Edge& theEdge1, | |
2006 | const TopoDS_Edge& theEdge2, | |
2007 | const Standard_Real theMaxSine, | |
2008 | const Standard_Real theMaxWidth, | |
2009 | const Standard_Real theMaxTolerance, | |
2010 | TopoDS_Edge& theEdge11, | |
2011 | TopoDS_Edge& theEdge12, | |
2012 | TopoDS_Edge& theEdge21, | |
2013 | TopoDS_Edge& theEdge22) | |
2014 | { | |
2015 | const TopoDS_Edge aEs[] = {theEdge1, theEdge2}; | |
2016 | if (!IsReady() || BRep_Tool::Degenerated(aEs[0]) || | |
2017 | BRep_Tool::Degenerated(aEs[1])) | |
2018 | { | |
2019 | return Standard_False; | |
2020 | } | |
2021 | ||
2022 | // Check the distance between the edge common ends. | |
2023 | const Standard_Real aTol2 = theMaxWidth + 0.5 * Precision::Confusion(); | |
2024 | const Standard_Real aTol3 = theMaxWidth + Precision::Confusion(); | |
2025 | const Standard_Real aTol4 = theMaxWidth + 1.5 * Precision::Confusion(); | |
2026 | const Standard_Real aSqTol2 = aTol2 * aTol2; | |
2027 | const Standard_Real aSqTol3 = aTol3 * aTol3; | |
2028 | Handle(Geom_Curve) aCs[2]; | |
2029 | Standard_Real aLs[2][2]; | |
2030 | Standard_Integer aVIs[2]; | |
2031 | gp_Pnt aVPs[2]; | |
2032 | { | |
2033 | for (Standard_Integer aEI = 0; aEI < 2; ++aEI) | |
2034 | { | |
2035 | if (!ShapeAnalysis_Edge().Curve3d( | |
2036 | aEs[aEI], aCs[aEI], aLs[aEI][0], aLs[aEI][1], Standard_False)) | |
2037 | { | |
2038 | return Standard_False; | |
2039 | } | |
2040 | ||
2041 | aVIs[aEI] = (aEs[aEI].Orientation() == TopAbs_REVERSED) ? aEI : 1 - aEI; | |
2042 | aVPs[aEI] = aCs[aEI]->Value(aLs[aEI][aVIs[aEI]]); | |
2043 | } | |
2044 | if (aVPs[0].SquareDistance(aVPs[1]) > aSqTol2) | |
2045 | { | |
2046 | return Standard_False; | |
2047 | } | |
2048 | } | |
2049 | ||
2050 | // Check the angle between the edges. | |
2051 | if (theMaxSine >= 0) | |
2052 | { | |
2053 | const Standard_Real aSqMaxSine = theMaxSine * theMaxSine; | |
2054 | gp_XYZ aDs[2]; | |
2055 | Standard_Integer aReverse = 0; | |
2056 | for (Standard_Integer aEI = 0; aEI < 2; ++aEI) | |
2057 | { | |
2058 | GeomAdaptor_Curve aCA(aCs[aEI]); | |
2059 | if (GCPnts_AbscissaPoint::Length(aCA, aLs[aEI][0], aLs[aEI][1], | |
2060 | 0.25 * Precision::Confusion()) < 0.5 * Precision::Confusion()) | |
2061 | { | |
2062 | return Standard_False; | |
2063 | } | |
2064 | ||
2065 | GCPnts_AbscissaPoint aAP(0.25 * Precision::Confusion(), aCA, | |
2066 | 0.5 * Precision::Confusion() * (1 - 2 * aVIs[aEI]), | |
2067 | aLs[aEI][aVIs[aEI]]); | |
2068 | if (!aAP.IsDone()) | |
2069 | { | |
2070 | return Standard_False; | |
2071 | } | |
2072 | ||
2073 | gp_XYZ aPs[2]; | |
2074 | aPs[aVIs[aEI]] = aVPs[aEI].XYZ(); | |
2075 | aPs[1 - aVIs[aEI]] = aCs[aEI]->Value(aAP.Parameter()).XYZ(); | |
2076 | aDs[aEI] = aPs[1] - aPs[0]; | |
2077 | const Standard_Real aDN = aDs[aEI].Modulus(); | |
2078 | if (aDN < 0.1 * Precision::Confusion()) | |
2079 | { | |
2080 | return Standard_False; | |
2081 | } | |
2082 | ||
2083 | aDs[aEI] *= 1 / aDN; | |
2084 | aReverse ^= aVIs[aEI]; | |
2085 | } | |
2086 | if (aReverse) | |
2087 | { | |
2088 | aDs[0].Reverse(); | |
2089 | } | |
2090 | if (aDs[0] * aDs[1] < 0 || aDs[0].CrossSquareMagnitude(aDs[1]) > aSqMaxSine) | |
2091 | { | |
2092 | return Standard_False; | |
2093 | } | |
2094 | } | |
2095 | ||
2096 | // Calculate the tail bounds. | |
2097 | gp_Pnt aPs[2], aPrjs[2]; | |
2098 | Standard_Real aParams1[2], aParams2[2]; | |
2099 | Standard_Real aDists[2]; | |
2100 | Standard_Boolean isWholes[] = {Standard_True, Standard_True}; | |
2101 | for (Standard_Integer aEI = 0; aEI < 2; ++aEI) | |
2102 | { | |
2103 | Standard_Real aParam1 = aLs[aEI][aVIs[aEI]]; | |
2104 | aParams1[aEI] = aLs[aEI][1 - aVIs[aEI]]; | |
2105 | aCs[aEI]->D0(aParams1[aEI], aPs[aEI]); | |
2106 | aDists[aEI] = Project(aCs[1 - aEI], aLs[1 - aEI][0], aLs[1 - aEI][1], | |
2107 | aPs[aEI], 0.25 * Precision::Confusion(), aParams2[aEI], aPrjs[aEI]); | |
2108 | if (aDists[aEI] <= aTol2) | |
2109 | { | |
2110 | continue; | |
2111 | } | |
2112 | ||
2113 | isWholes[aEI] = Standard_False; | |
2114 | for (;;) | |
2115 | { | |
2116 | const Standard_Real aParam = (aParam1 + aParams1[aEI]) * 0.5; | |
2117 | aCs[aEI]->D0(aParam, aPs[aEI]); | |
2118 | const Standard_Real aDist = Project(aCs[1 - aEI], aLs[1 - aEI][0], | |
2119 | aLs[1 - aEI][1], aPs[aEI], 0.25 * Precision::Confusion(), aParams2[aEI], | |
2120 | aPrjs[aEI]); | |
2121 | if (aDist <= aTol2) | |
2122 | { | |
2123 | aParam1 = aParam; | |
2124 | } | |
2125 | else | |
2126 | { | |
2127 | aParams1[aEI] = aParam; | |
2128 | if (aDist <= aTol3) | |
2129 | { | |
2130 | break; | |
2131 | } | |
2132 | } | |
2133 | } | |
2134 | } | |
2135 | ||
2136 | // Check the tail bounds. | |
2137 | for (Standard_Integer aEI = 0; aEI < 2; ++aEI) | |
2138 | { | |
2139 | const Standard_Real aParam1 = aLs[aEI][aVIs[aEI]]; | |
2140 | const Standard_Real aParam2 = aParams1[aEI]; | |
2141 | const Standard_Real aStepL = (aParam2 - aParam1) / 23; | |
2142 | for (Standard_Integer aStepN = 1; aStepN < 23; ++aStepN) | |
2143 | { | |
2144 | Standard_Real aParam = aParam1 + aStepN * aStepL; | |
2145 | gp_Pnt aP = aCs[aEI]->Value(aParam), aPrj; | |
2146 | if (Project(aCs[1 - aEI], aLs[1 - aEI][0], aLs[1 - aEI][1], aP, | |
2147 | 0.25 * Precision::Confusion(), aParam, aPrj) > aTol4) | |
2148 | { | |
2149 | return Standard_False; | |
2150 | } | |
2151 | } | |
2152 | } | |
2153 | ||
2154 | // Check whether both edges must be removed. | |
2155 | if (isWholes[0] && isWholes[1] && aPs[0].SquareDistance(aPs[1]) <= aSqTol3) | |
2156 | { | |
2157 | theEdge11 = theEdge1; | |
2158 | theEdge21 = theEdge2; | |
2159 | return Standard_True; | |
2160 | } | |
2161 | ||
2162 | // Cut and remove the edges. | |
2163 | Standard_Integer aFI = 0; | |
2164 | if (isWholes[0] || isWholes[1]) | |
2165 | { | |
2166 | // Determine an edge to remove and the other one to cut. | |
2167 | aFI = isWholes[0] ? 0 : 1; | |
2168 | if (aDists[1 - aFI] < aDists[aFI] && isWholes[1 - aFI]) | |
2169 | { | |
2170 | aFI = 1 - aFI; | |
2171 | } | |
2172 | } | |
2173 | Standard_Real aParams[2]; | |
2174 | aParams[aFI] = aParams1[aFI]; | |
2175 | aParams[1 - aFI] = aParams2[aFI]; | |
2176 | ||
2177 | // Correct the cut for the parametrization tolerance. | |
2178 | TopoDS_Edge* aEParts[][2] = | |
2179 | {{&theEdge11, &theEdge12}, {&theEdge21, &theEdge22}}; | |
2180 | Standard_Integer aResults[] = {1, 1}; | |
2181 | for (Standard_Integer aEI = 0; aEI < 2; ++aEI) | |
2182 | { | |
2183 | if (Abs(aParams[aEI] - aLs[aEI][1 - aVIs[aEI]]) <= Precision::PConfusion()) | |
2184 | { | |
2185 | aResults[aEI] = 2; | |
2186 | *aEParts[aEI][0] = aEs[aEI]; | |
2187 | } | |
2188 | else if (Abs(aParams[aEI] - aLs[aEI][aVIs[aEI]]) <= Precision::PConfusion()) | |
2189 | { | |
2190 | aResults[aEI] = 0; | |
2191 | } | |
2192 | } | |
2193 | ||
2194 | // Correct the cut for the distance tolerance. | |
2195 | for (Standard_Integer aEI = 0; aEI < 2; ++aEI) | |
2196 | { | |
2197 | if (aResults[aEI] != 1) | |
2198 | { | |
2199 | continue; | |
2200 | } | |
2201 | ||
2202 | // Create the parts of the edge. | |
2203 | TopoDS_Edge aFE = TopoDS::Edge(aEs[aEI].Oriented(TopAbs_FORWARD)); | |
2204 | ShapeAnalysis_TransferParametersProj aSATPP(aFE, TopoDS_Face()); | |
2205 | aSATPP.SetMaxTolerance(theMaxTolerance); | |
2206 | TopoDS_Vertex aSplitV; | |
2207 | BRep_Builder().MakeVertex( | |
2208 | aSplitV, aCs[aEI]->Value(aParams[aEI]), Precision::Confusion()); | |
2209 | TopoDS_Edge aEParts2[] = { | |
2210 | ShapeBuild_Edge().CopyReplaceVertices(aFE, TopoDS_Vertex(), | |
2211 | TopoDS::Vertex(aSplitV.Oriented(TopAbs_REVERSED))), | |
2212 | ShapeBuild_Edge().CopyReplaceVertices(aFE, aSplitV, TopoDS_Vertex())}; | |
2213 | ShapeBuild_Edge().CopyPCurves(aEParts2[0], aFE); | |
2214 | ShapeBuild_Edge().CopyPCurves(aEParts2[1], aFE); | |
2215 | BRep_Builder().SameRange(aEParts2[0], Standard_False); | |
2216 | BRep_Builder().SameRange(aEParts2[1], Standard_False); | |
2217 | BRep_Builder().SameParameter(aEParts2[0], Standard_False); | |
2218 | BRep_Builder().SameParameter(aEParts2[1], Standard_False); | |
2219 | aSATPP.TransferRange( | |
2220 | aEParts2[0], aLs[aEI][0], aParams[aEI], Standard_False); | |
2221 | aSATPP.TransferRange( | |
2222 | aEParts2[1], aParams[aEI], aLs[aEI][1], Standard_False); | |
2223 | GProp_GProps aLinProps; | |
2224 | BRepGProp::LinearProperties(aEParts2[1 - aVIs[aEI]], aLinProps); | |
2225 | if (aLinProps.Mass() <= Precision::Confusion()) | |
2226 | { | |
2227 | aResults[aEI] = 2; | |
2228 | *aEParts[aEI][0] = aEs[aEI]; | |
2229 | } | |
2230 | else | |
2231 | { | |
2232 | BRepGProp::LinearProperties(aEParts2[aVIs[aEI]], aLinProps); | |
2233 | if (aLinProps.Mass() <= Precision::Confusion()) | |
2234 | { | |
2235 | aResults[aEI] = 0; | |
2236 | } | |
2237 | else | |
2238 | { | |
2239 | *aEParts[aEI][0] = aEParts2[0]; | |
2240 | *aEParts[aEI][1] = aEParts2[1]; | |
2241 | } | |
2242 | } | |
2243 | } | |
2244 | ||
2245 | return aResults[0] + aResults[1] != 0; | |
2246 | } |