1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
15 #include <BRep_Builder.hxx>
16 #include <BRep_Tool.hxx>
17 #include <BRepLib.hxx>
18 #include <BRepTools.hxx>
20 #include <Geom2d_Curve.hxx>
21 #include <Geom_BezierSurface.hxx>
22 #include <Geom_BSplineSurface.hxx>
23 #include <Geom_Curve.hxx>
24 #include <Geom_ElementarySurface.hxx>
25 #include <Geom_Line.hxx>
26 #include <Geom_Surface.hxx>
27 #include <Geom_TrimmedCurve.hxx>
28 #include <GeomAdaptor_Curve.hxx>
29 #include <GeomAdaptor_Surface.hxx>
30 #include <GeomLib.hxx>
34 #include <Poly_Polygon3D.hxx>
35 #include <Precision.hxx>
36 #include <ShapeAnalysis_CheckSmallFace.hxx>
37 #include <ShapeAnalysis_Curve.hxx>
38 #include <ShapeAnalysis_Wire.hxx>
39 #include <ShapeAnalysis_WireOrder.hxx>
40 #include <ShapeExtend.hxx>
41 #include <ShapeExtend_WireData.hxx>
42 #include <Standard_ErrorHandler.hxx>
43 #include <TColgp_Array1OfPnt.hxx>
44 #include <TColgp_Array2OfPnt.hxx>
45 #include <TColgp_SequenceOfXYZ.hxx>
46 #include <TColStd_Array1OfReal.hxx>
47 #include <TColStd_Array2OfReal.hxx>
48 #include <TColStd_ListOfReal.hxx>
50 #include <TopExp_Explorer.hxx>
52 #include <TopoDS_Builder.hxx>
53 #include <TopoDS_Compound.hxx>
54 #include <TopoDS_Edge.hxx>
55 #include <TopoDS_Face.hxx>
56 #include <TopoDS_Iterator.hxx>
57 #include <TopoDS_Shell.hxx>
58 #include <TopoDS_Vertex.hxx>
59 #include <TopoDS_Wire.hxx>
60 #include <TopTools_Array1OfShape.hxx>
61 #include <TopTools_HSequenceOfShape.hxx>
62 #include <TopTools_ListOfShape.hxx>
64 //#include <GeomLProp_SLProps.hxx>
65 //#include <ShapeFix_Wire.hxx>
66 //=======================================================
67 //function : ShapeAnalysis_CheckSmallFace
69 //=======================================================================
70 ShapeAnalysis_CheckSmallFace::ShapeAnalysis_CheckSmallFace()
72 myStatusSpot = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
73 myStatusStrip = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
74 myStatusPin = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
75 myStatusTwisted = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
76 myStatusSplitVert = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
80 (const gp_Pnt& p, Standard_Integer& nb,
81 Standard_Real& minx, Standard_Real& miny, Standard_Real& minz,
82 Standard_Real& maxx, Standard_Real& maxy, Standard_Real& maxz)
86 if (nb < 1) { minx = maxx = x; miny = maxy = y; minz = maxz = z; }
88 if (minx > x) minx = x; if (maxx < x) maxx = x;
89 if (miny > y) miny = y; if (maxy < y) maxy = y;
90 if (minz > z) minz = z; if (maxz < z) maxz = z;
95 static Standard_Boolean MinMaxSmall
96 (const Standard_Real minx, const Standard_Real miny, const Standard_Real minz, const Standard_Real maxx, const Standard_Real maxy, const Standard_Real maxz, const Standard_Real toler)
98 Standard_Real dx = maxx - minx;
99 Standard_Real dy = maxy - miny;
100 Standard_Real dz = maxz - minz;
102 if ((dx > toler && !Precision::IsInfinite (dx)) ||
103 (dy > toler && !Precision::IsInfinite (dy)) ||
104 (dz > toler && !Precision::IsInfinite (dz)))
105 return Standard_False;
106 return Standard_True;
109 //=======================================================================
110 //function : IsSpotFace
112 //=======================================================================
114 Standard_Integer ShapeAnalysis_CheckSmallFace::IsSpotFace(const TopoDS_Face& F,gp_Pnt& spot,Standard_Real& spotol,const Standard_Real tol) const
117 Standard_Real toler = tol; Standard_Real tolv = tol;
118 // Compute tolerance to get : from greatest tol of vertices
119 // In addition, also computes min-max of vertices
120 // To finally compare mini-max box with tolerance
121 // gka Mar2000 Protection against faces without wires
122 // but they occur due to bugs in the algorithm itself, it needs to be fixed
123 Standard_Boolean isWir = Standard_False;
124 for(TopoDS_Iterator itw(F,Standard_False) ; itw.More();itw.Next()) {
125 if(itw.Value().ShapeType() != TopAbs_WIRE)
127 TopoDS_Wire w1 = TopoDS::Wire(itw.Value());
128 if (!w1.IsNull()) {isWir = Standard_True; break;}
130 if(!isWir) return Standard_True;
131 Standard_Integer nbv = 0;
132 Standard_Real minx =0 ,miny = 0 ,minz = 0,maxx = Precision::Infinite(), maxy = Precision::Infinite(),maxz = Precision::Infinite();
134 Standard_Boolean same = Standard_True;
135 for (TopExp_Explorer iv(F,TopAbs_VERTEX); iv.More(); iv.Next()) {
136 TopoDS_Vertex V = TopoDS::Vertex (iv.Current());
137 if (V0.IsNull()) V0 = V;
138 else if (same) { if (!V0.IsSame(V)) same = Standard_False; }
140 gp_Pnt pnt = BRep_Tool::Pnt (V);
141 // Standard_Real x,y,z;
142 MinMaxPnt (pnt, nbv, minx,miny,minz, maxx,maxy,maxz);
145 tolv = BRep_Tool::Tolerance (V);
146 if (tolv > toler) toler = tolv;
151 if (!MinMaxSmall(minx,miny,minz,maxx,maxy,maxz,toler)) return 0;
153 // All vertices are confused
154 // Check edges (a closed edge may be a non-null length edge !)
155 // By picking intermediate point on each one
156 for (TopExp_Explorer ie(F,TopAbs_EDGE); ie.More(); ie.Next()) {
157 TopoDS_Edge E = TopoDS::Edge (ie.Current());
159 Handle(Geom_Curve) C3D = BRep_Tool::Curve (E,cf,cl);
160 if (C3D.IsNull()) continue;
161 gp_Pnt debut = C3D->Value (cf);
162 gp_Pnt milieu = C3D->Value ( (cf+cl)/2);
163 if (debut.SquareDistance(milieu) > toler*toler) return 0;
166 spot.SetCoord ( (minx+maxx)/2. , (miny+maxy)/2. , (minz+maxz)/2. );
168 spotol = Max (spotol, maxy-miny);
169 spotol = Max (spotol, maxz-minz);
172 return (same ? 2 : 1);
175 //=======================================================================
176 //function : CheckSpotFace
178 //=======================================================================
180 Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckSpotFace(const TopoDS_Face& F,const Standard_Real tol)
183 Standard_Real spotol;
184 Standard_Integer stat = IsSpotFace (F,spot,spotol,tol);
185 if(!stat) return Standard_False;
187 case 1: myStatusSpot = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); break;
188 case 2: myStatusSpot = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); break;
192 return Standard_True;
195 //=======================================================================
196 //function : IsStripSupport
198 //=======================================================================
200 Standard_Boolean ShapeAnalysis_CheckSmallFace::IsStripSupport(const TopoDS_Face& F,const Standard_Real tol)
203 Standard_Real toler = tol;
204 if (toler < 0) toler = 1.e-07; // ?? better to compute tolerance zones
207 Handle(Geom_Surface) surf = BRep_Tool::Surface (F,loc);
208 if (surf.IsNull()) return 0;
210 // Checking on poles for bezier-bspline
211 // A more general way is to check Values by scanning ISOS (slower)
213 Handle(Geom_BSplineSurface) bs = Handle(Geom_BSplineSurface)::DownCast(surf);
214 Handle(Geom_BezierSurface) bz = Handle(Geom_BezierSurface)::DownCast(surf);
216 // Standard_Integer stat = 2; // 2 : small in V direction
217 if (!bs.IsNull() || !bz.IsNull()) {
218 Standard_Boolean cbz = (!bz.IsNull());
219 Standard_Integer iu,iv, nbu, nbv;
220 if (cbz) { nbu = bz->NbUPoles(), nbv = bz->NbVPoles(); }
221 else { nbu = bs->NbUPoles(), nbv = bs->NbVPoles(); }
222 // Standard_Real dx = 0, dy = 0, dz = 0;
223 // Standard_Real x,y,z;
224 Standard_Real minx = 0.,miny = 0.,minz = 0.,maxx = 0.,maxy = 0.,maxz = 0.;
225 Standard_Boolean issmall = Standard_True;
227 for (iu = 1; iu <= nbu; iu ++) {
228 // for each U line, scan poles in V (V direction)
229 Standard_Integer nb = 0;
230 for (iv = 1; iv <= nbv; iv ++) {
231 gp_Pnt unp = (cbz ? bz->Pole(iu,iv) : bs->Pole(iu,iv));
232 MinMaxPnt (unp, nb, minx,miny,minz, maxx,maxy,maxz);
234 if (!MinMaxSmall(minx,miny,minz,maxx,maxy,maxz,toler))
235 { issmall = Standard_False; break; } // small in V ?
238 myStatusStrip = ShapeExtend::EncodeStatus ( ShapeExtend_DONE2);
239 return issmall; // OK, small in V
241 issmall = Standard_True;
242 for (iv = 1; iv <= nbv; iv ++) {
243 // for each V line, scan poles in U (U direction)
244 Standard_Integer nb = 0;
245 for (iu = 1; iu <= nbu; iu ++) {
246 gp_Pnt unp = (cbz ? bz->Pole(iu,iv) : bs->Pole(iu,iv));
247 MinMaxPnt (unp, nb, minx,miny,minz, maxx,maxy,maxz);
249 if (!MinMaxSmall(minx,miny,minz,maxx,maxy,maxz,toler))
250 { issmall = Standard_False; break; } // small in U ?
253 myStatusStrip = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
258 return Standard_False;
261 //=======================================================================
262 //function : CheckStripEdges
264 //=======================================================================
266 Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckStripEdges(const TopoDS_Edge& E1,const TopoDS_Edge& E2,const Standard_Real tol,Standard_Real& dmax) const
268 // We have the topological configuration OK : 2 edges, 2 vertices
269 // But, are these two edges well confused ?
270 Standard_Real toler = tol;
272 Standard_Real tole = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
273 if (toler < tole / 2.) toler = tole/2.;
276 // We project a list of points from each curve, on the opposite one,
277 // we check the distance
278 Standard_Integer nbint = 10;
280 ShapeAnalysis_Curve SAC;
281 Standard_Real cf1,cl1,cf2,cl2,u; dmax = 0;
282 Handle(Geom_Curve) C1,C2;
283 C1 = BRep_Tool::Curve (E1,cf1,cl1);
284 C2 = BRep_Tool::Curve (E2,cf2,cl2);
285 if(C1.IsNull() || C2.IsNull()) return Standard_False;
286 cf1 = Max(cf1, C1->FirstParameter());
287 cl1 = Min(cl1, C1->LastParameter());
288 Handle(Geom_TrimmedCurve) C1T = new Geom_TrimmedCurve(C1,cf1,cl1,Standard_True);
289 //pdn protection against feature in Trimmed_Curve
290 cf1 = C1T->FirstParameter();
291 cl1 = C1T->LastParameter();
292 Handle(Geom_TrimmedCurve) CC;
293 cf2 = Max(cf2, C2->FirstParameter());
294 cl2 = Min(cl2, C2->LastParameter());
295 Handle(Geom_TrimmedCurve) C2T = new Geom_TrimmedCurve(C2,cf2,cl2, Standard_True);
296 cf2 = C2T->FirstParameter();
297 cl2 = C2T->LastParameter();
299 Standard_Real cd1 = (cl1 - cf1)/nbint;
300 Standard_Real cd2 = (cl2 - cf2)/nbint;
303 for (int numcur = 0; numcur < 2; numcur ++) {
305 if (numcur) { CC = C1T; C1T = C2T; C2T = CC;
306 cd1 = cd2; //smh added replacing step and replacing first
310 for (int nump = 0; nump <= nbint; nump ++) {
311 gp_Pnt p2, p1 = C1T->Value (u);
313 //pdn Adaptor curve is used to avoid of enhancing of domain.
314 GeomAdaptor_Curve GAC(C2T);
315 Standard_Real dist = SAC.Project (GAC,p1,toler,p2,para);
316 //pdn check if parameter of projection is in the domain of the edge.
317 if (para < f || para > l) return Standard_False;
318 if (dist > dmax) dmax = dist;
319 if (dist > toler) return Standard_False;
323 return (dmax < toler);
326 //=======================================================================
327 //function : FindStripEdges
329 //=======================================================================
331 Standard_Boolean ShapeAnalysis_CheckSmallFace::FindStripEdges(const TopoDS_Face& F,TopoDS_Edge& E1,TopoDS_Edge& E2,const Standard_Real tol,Standard_Real& dmax)
333 E1.Nullify(); E2.Nullify();
334 Standard_Integer nb = 0;
335 for (TopExp_Explorer ex(F,TopAbs_EDGE); ex.More(); ex.Next()) {
336 TopoDS_Edge E = TopoDS::Edge (ex.Current());
337 if (nb == 1 && E.IsSame(E1))
338 continue; // ignore seam edge
340 TopExp::Vertices (E,V1,V2);
342 p1 = BRep_Tool::Pnt (V1);
343 p2 = BRep_Tool::Pnt (V2);
344 Standard_Real toler = tol;
345 if (toler <= 0) toler = (BRep_Tool::Tolerance(V1) + BRep_Tool::Tolerance(V2) ) / 2.;
348 Standard_Real dist = p1.Distance(p2);
351 Handle(Geom_Curve) CC;
352 CC = BRep_Tool::Curve (E,cf,cl);
353 Standard_Boolean isNullLength = Standard_True;
355 gp_Pnt pp = CC->Value ( (cf+cl)/2.);
356 if (pp.Distance(p1) < toler && pp.Distance(p2) < toler) continue;
357 isNullLength = Standard_False;
359 if (dist <= toler && isNullLength) continue; //smh
362 else if (nb == 2) E2 = E;
363 else return Standard_False;
365 // Now, check these two edge to define a strip !
366 if (!E1.IsNull()&&!E2.IsNull()) {
367 if(!CheckStripEdges (E1,E2,tol,dmax)) return Standard_False;
369 myStatusStrip = ShapeExtend::EncodeStatus (ShapeExtend_DONE3);
370 return Standard_True ;
373 return Standard_False;
376 //=======================================================================
377 //function : CheckSingleStrip
379 //=======================================================================
381 Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckSingleStrip(const TopoDS_Face& F,
382 TopoDS_Edge& E1, TopoDS_Edge& E2,const Standard_Real tol)
384 Standard_Real toler = tol;
385 Standard_Real minx,miny,minz,maxx,maxy,maxz;
387 // In this case, we have 2 vertices and 2 great edges. Plus possibly 2 small
388 // edges, one on each vertex
390 Standard_Integer nb = 0;
391 for (TopExp_Explorer itv (F,TopAbs_VERTEX); itv.More(); itv.Next()) {
392 TopoDS_Vertex V = TopoDS::Vertex (itv.Current());
393 if (V1.IsNull()) V1 = V;
394 else if (V1.IsSame(V)) continue;
395 else if (V2.IsNull()) V2 = V;
396 else if (V2.IsSame(V)) continue;
403 for (TopExp_Explorer ite (F,TopAbs_EDGE); ite.More(); ite.Next()) {
404 TopoDS_Edge E = TopoDS::Edge (ite.Current());
405 if (nb == 1 && E.IsSame(E1))
406 continue; // ignore seam edge
408 TopExp::Vertices (E,VA,VB);
411 tolv = BRep_Tool::Tolerance (VA);
412 if (toler < tolv) toler = tolv;
413 tolv = BRep_Tool::Tolerance (VB);
414 if (toler < tolv) toler = tolv;
417 // Edge on same vertex : small one ?
419 Standard_Real cf = 0.,cl = 0.;
420 Handle(Geom_Curve) C3D;
421 if (!BRep_Tool::Degenerated(E)) C3D = BRep_Tool::Curve (E,cf,cl);
422 if (C3D.IsNull()) continue; // DGNR
423 Standard_Integer np = 0;
424 gp_Pnt deb = C3D->Value(cf);
425 MinMaxPnt (deb,np,minx,miny,minz,maxx,maxy,maxz);
426 gp_Pnt fin = C3D->Value(cl);
427 MinMaxPnt (fin,np,minx,miny,minz,maxx,maxy,maxz);
428 gp_Pnt mid = C3D->Value( (cf+cl)/2. );
429 MinMaxPnt (mid,np,minx,miny,minz,maxx,maxy,maxz);
430 if (!MinMaxSmall (minx,miny,minz,maxx,maxy,maxz,toler)) return Standard_False;
432 // Other case : two maximum allowed
434 if (nb > 2) return Standard_False;
435 if (nb == 1) { V1 = VA; V2 = VB; E1 = E; }
437 if (V1.IsSame(VA) && !V2.IsSame(VB)) return Standard_False;
438 if (V1.IsSame(VB) && !V2.IsSame(VA)) return Standard_False;
441 else return Standard_False;
445 if (nb < 2) return Standard_False; // only one vertex : cannot be a strip ...
447 // Checking if E1 and E2 define a Strip
449 if (!CheckStripEdges (E1,E2,tol,dmax)) return Standard_False;
450 myStatusStrip = ShapeExtend::EncodeStatus (ShapeExtend_DONE3);
451 return Standard_True;
454 //=======================================================================
455 //function : CheckStripFace
457 //=======================================================================
459 Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckStripFace(const TopoDS_Face& F,
460 TopoDS_Edge& E1, TopoDS_Edge& E2,const Standard_Real tol)
463 // Standard_Integer stat;
464 if(CheckSingleStrip (F,E1,E2,tol)) return Standard_True ; // it is a strip
466 // IsStripSupport used as rejection. But this kind of test may be done
467 // on ANY face, once we are SURE that FindStripEdges is reliable (and fast
470 // ?? record a diagnostic StripFace, but without yet lists of edges
471 // ?? Record Diagnostic "StripFace", no data (should be "Edges1" "Edges2")
472 // but direction is known (1:U 2:V)
473 // TopoDS_Edge E1,E2;
475 if(FindStripEdges (F,E1,E2,tol,dmax)) return Standard_True;
477 // Now, trying edges : if there are 2 and only 2 edges greater than tolerance
478 // (given or sum of vertex tolerances), do they define a strip
479 // Warning : if yes, they bring different vertices ...
481 return Standard_False;
485 //=======================================================================
486 //function : CheckSplittingVertices
488 //=======================================================================
490 Standard_Integer ShapeAnalysis_CheckSmallFace::CheckSplittingVertices(const TopoDS_Face& F,
491 TopTools_DataMapOfShapeListOfShape& MapEdges,
492 ShapeAnalysis_DataMapOfShapeListOfReal& MapParam,
493 TopoDS_Compound& theAllVert)
496 // Prepare array of vertices with their locations //TopTools
497 Standard_Integer nbv = 0, nbp = 0;
498 //TopoDS_Compound theAllVert;
499 BRep_Builder theBuilder;
500 //theBuilder.MakeCompound(theAllVert);
501 TopExp_Explorer itv; // svv Jan11 2000 : porting on DEC
502 for (itv.Init(F,TopAbs_VERTEX); itv.More(); itv.Next()) nbv ++;
504 if (nbv == 0) return 0;
505 TopTools_Array1OfShape vtx (1,nbv);
506 TColgp_Array1OfPnt vtp (1,nbv);
507 TColStd_Array1OfReal vto (1,nbv);
510 for (itv.Init(F,TopAbs_VERTEX); itv.More(); itv.Next()) {
512 TopoDS_Vertex unv = TopoDS::Vertex (itv.Current());
513 vtx.SetValue (nbp,unv);
514 gp_Pnt unp = BRep_Tool::Pnt (unv);
515 vtp.SetValue (nbp,unp);
516 Standard_Real unt = myPrecision;
517 if (unt < 0) unt =BRep_Tool::Tolerance (unv);
518 vto.SetValue (nbp,unt);
520 nbv = nbp; nbp = 0; // now, counting splitting vertices
522 // Check edges : are vertices (other than extremities) confused with it ?
523 ShapeAnalysis_Curve SAC;
524 for (Standard_Integer iv = 1; iv <= nbv; iv ++) {
525 TopoDS_Vertex V = TopoDS::Vertex (vtx.Value(iv));
526 TopTools_ListOfShape listEdge;
527 TColStd_ListOfReal listParam;
528 Standard_Boolean issplit = Standard_False;
529 for (TopExp_Explorer ite(F,TopAbs_EDGE); ite.More(); ite.Next()) {
530 TopoDS_Edge E = TopoDS::Edge (ite.Current());
532 TopExp::Vertices (E,V1,V2);
534 Handle(Geom_Curve) C3D = BRep_Tool::Curve (E,cf,cl);
535 if (C3D.IsNull()) continue;
536 if (V.IsSame(V1) || V.IsSame(V2)) continue;
537 gp_Pnt unp = vtp.Value(iv);
538 Standard_Real unt = vto.Value(iv);
541 Standard_Real dist = SAC.Project (C3D,unp,unt*10.,proj,param,cf,cl);
542 if (dist == 0.0) continue; //smh
543 // Splitting Vertex to record ?
545 // If Split occurs at beginning or end, it is not a split ...
546 Standard_Real fpar, lpar, eps = 1.e-06;
547 if (param >=cl || param <= cf) continue; // Out of range
548 fpar = param - cf; lpar = param - cl;
549 if ((Abs(fpar) < eps) || (Abs(lpar) < eps)) continue; // Near end or start
551 listParam.Append(param);
552 issplit = Standard_True;
558 theBuilder.Add(theAllVert, V);
559 MapEdges.Bind(V,listEdge);
560 MapParam.Bind(V,listParam);
564 myStatusSplitVert = ShapeExtend::EncodeStatus (ShapeExtend_DONE);
569 static Standard_Integer IsoStat
570 (const TColgp_Array2OfPnt& poles,
571 const Standard_Integer uorv, const Standard_Integer rank,
572 const Standard_Real tolpin, const Standard_Real toler)
574 Standard_Integer i, np = 0;
575 Standard_Integer i0 = (uorv == 1 ? poles.LowerCol() : poles.LowerRow());
576 Standard_Integer i1 = (uorv == 1 ? poles.UpperCol() : poles.UpperRow());
577 Standard_Real xmin = 0.,ymin = 0.,zmin = 0., xmax = 0.,ymax = 0.,zmax = 0.;
578 for (i = i0; i <= i1; i ++) {
579 if (uorv == 1) MinMaxPnt (poles(rank,i),np,xmin,ymin,zmin, xmax,ymax,zmax);
580 else MinMaxPnt (poles(i,rank), np, xmin,ymin,zmin, xmax,ymax,zmax);
582 if (MinMaxSmall (xmin,ymin,zmin, xmax,ymax,zmax, tolpin)) return 0;
583 if (MinMaxSmall (xmin,ymin,zmin, xmax,ymax,zmax, toler)) return 1;
587 static Standard_Boolean CheckPoles(const TColgp_Array2OfPnt& poles, Standard_Integer uorv, Standard_Integer rank)
589 Standard_Integer i0 = (uorv == 1 ? poles.LowerCol() : poles.LowerRow());
590 Standard_Integer i1 = (uorv == 1 ? poles.UpperCol() : poles.UpperRow());
591 for (Standard_Integer i = i0; i <= i1-1; i ++) {
593 if(poles(rank,i).IsEqual(poles(rank, i+1), 1e-15)) return Standard_True;
595 if(poles(i,rank).IsEqual(poles(i+1,rank), 1e-15)) return Standard_True;
597 return Standard_False;
599 //=======================================================================
600 //function : CheckPin
602 //=======================================================================
604 Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckPin (const TopoDS_Face& F, Standard_Integer& whatrow,Standard_Integer& sens)
607 Handle(Geom_Surface) surf = BRep_Tool::Surface (F,loc);
608 if (surf->IsKind(STANDARD_TYPE(Geom_ElementarySurface))) return Standard_False;
610 Standard_Real toler = myPrecision;
611 if (toler < 0) toler = 1.e-4;
612 Standard_Real tolpin = 1.e-9; // for sharp sharp pin
614 // Checking the poles
616 // Take the poles : they give good idea of sharpness of a pin
617 Standard_Integer nbu = 0 , nbv = 0;
618 Handle(Geom_BSplineSurface) bs = Handle(Geom_BSplineSurface)::DownCast(surf);
619 Handle(Geom_BezierSurface) bz = Handle(Geom_BezierSurface)::DownCast(surf);
620 if (!bs.IsNull()) { nbu = bs->NbUPoles(); nbv = bs->NbVPoles(); }
621 if (!bz.IsNull()) { nbu = bz->NbUPoles(); nbv = bz->NbVPoles(); }
622 if (nbu == 0 || nbv == 0) return Standard_False;
624 TColgp_Array2OfPnt allpoles (1,nbu,1,nbv);
625 if (!bs.IsNull()) bs->Poles (allpoles);
626 if (!bz.IsNull()) bz->Poles (allpoles);
628 // Check each natural bound if it is a singularity (i.e. a pin)
631 Standard_Integer stat = 0; // 0 none, 1 in U, 2 in V
632 whatrow = 0; // 0 no row, else rank of row
633 stat = IsoStat(allpoles,1, 1,tolpin,toler);
634 if (stat) { sens = 1; whatrow = nbu; }
636 stat = IsoStat(allpoles,1,nbu,tolpin,toler);
637 if (stat) { sens = 1; whatrow = nbu; }
639 stat = IsoStat(allpoles,2, 1,tolpin,toler);
640 if (stat) { sens = 2; whatrow = 1; }
642 stat = IsoStat(allpoles,2,nbv,tolpin,toler);
643 if (stat) { sens = 2; whatrow = nbv; }
645 if (!sens) return Standard_False; // no pin
648 case 1: myStatusPin = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); break;
649 case 2: myStatusPin = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); break;
652 // cout<<(whatstat == 1 ? "Smooth" : "Sharp")<<" Pin on "<<(sens == 1 ? "U" : "V")<<" Row n0 "<<whatrow<<endl;
655 // Standard_Boolean EqualPoles = Standard_False;
656 if(CheckPoles(allpoles, 2, nbv)|| CheckPoles(allpoles, 2, 1)
657 ||CheckPoles(allpoles, 1, nbu)|| CheckPoles(allpoles, 1, 1))
658 myStatusPin = ShapeExtend::EncodeStatus (ShapeExtend_DONE3);
662 return Standard_True;
665 static Standard_Real TwistedNorm
666 (const Standard_Real x1, const Standard_Real y1, const Standard_Real z1, const Standard_Real x2, const Standard_Real y2, const Standard_Real z2)
667 { return (x1*x2) + (y1*y2) + (z1*z2); }
669 //=======================================================================
670 //function : CheckTwisted
672 //=======================================================================
674 Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckTwisted (const TopoDS_Face& F, Standard_Real& paramu,
675 Standard_Real& paramv)
678 Handle(Geom_Surface) surf = BRep_Tool::Surface (F,loc);
679 if (surf->IsKind(STANDARD_TYPE(Geom_ElementarySurface))) return Standard_False;
681 Standard_Real toler = myPrecision;
682 if (toler < 0) toler = 1.e-4;
683 //// GeomLProp_SLProps GLS (surf,2,toler);
684 GeomAdaptor_Surface GAS (surf);
686 // to be done : on isos of the surface
687 // and on edges, at least of outer wire
688 Standard_Integer nbint = 5;
689 TColStd_Array2OfReal nx (1,nbint+1,1,nbint+1);
690 TColStd_Array2OfReal ny (1,nbint+1,1,nbint+1);
691 TColStd_Array2OfReal nz (1,nbint+1,1,nbint+1);
692 Standard_Integer iu,iv;
693 Standard_Real umin,umax,vmin,vmax;
694 surf->Bounds (umin,umax,vmin,vmax);
695 Standard_Real u = umin, du = (umax-umin)/nbint;
696 Standard_Real v = vmin, dv = (umax-umin)/nbint;
699 for (iu = 1; iu <= nbint; iu ++) {
700 for (iv = 1; iv <= nbint; iv ++) {
701 // GLS.SetParameters (u,v);
702 // if (GLS.IsNormalDefined()) norm = GLS.Normal();
703 gp_Pnt curp; gp_Vec V1,V2,VXnorm;
704 GAS.D1 (u,v,curp,V1,V2);
705 VXnorm = V1.Crossed(V2);
706 nx.SetValue (iu,iv,VXnorm.X());
707 ny.SetValue (iu,iv,VXnorm.Y());
708 nz.SetValue (iu,iv,VXnorm.Z());
715 // Now, comparing normals on support surface, in both senses
716 // In principle, it suffuces to check within outer bound
718 for (iu = 1; iu < nbint; iu ++) {
719 for (iv = 1; iv < nbint; iv ++) {
720 // We here check each normal (iu,iv) with (iu,iv+1) and with (iu+1,iv)
721 // if for each test, we have negative scalar product, this means angle > 90deg
722 // it is the criterion to say it is twisted
723 if (TwistedNorm ( nx(iu,iv),ny(iu,iv),nz(iu,iv) , nx(iu,iv+1),ny(iu,iv+1),nz(iu,iv+1) ) < 0. ||
724 TwistedNorm ( nx(iu,iv),ny(iu,iv),nz(iu,iv) , nx(iu+1,iv),ny(iu+1,iv),nz(iu+1,iv) ) < 0. ) {
725 myStatusTwisted = ShapeExtend::EncodeStatus (ShapeExtend_DONE);
726 paramu = umin+du*iu-du/2;
727 paramv = vmin+dv*iv-dv/2;
728 return Standard_True;
733 // Now, comparing normals on edges ... to be done
735 return Standard_False;
739 //=======================================================================
740 //function : CheckPinFace
742 //=======================================================================
743 // Warning: This function not tested on many examples
745 Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckPinFace(const TopoDS_Face& F,
746 TopTools_DataMapOfShapeShape& mapEdges,const Standard_Real toler)
749 TopExp_Explorer exp_w (F,TopAbs_WIRE);
751 Standard_Real coef1=0, coef2; // =0 for deleting warning (skl)
752 TopoDS_Wire theCurWire = TopoDS::Wire (exp_w.Current());
753 ShapeAnalysis_WireOrder wi;
754 ShapeAnalysis_Wire sfw;
755 Handle(ShapeExtend_WireData) sbwd = new ShapeExtend_WireData(theCurWire);
758 Handle(TopTools_HSequenceOfShape) newedges = new TopTools_HSequenceOfShape();
759 Standard_Integer nb = wi.NbEdges();
760 Standard_Integer i = 0;
761 for ( i=1; i <= nb; i++ )
762 newedges->Append ( sbwd->Edge ( wi.Ordered(i) ) );
763 for ( i=1; i <= nb; i++ )
764 sbwd->Set ( TopoDS::Edge ( newedges->Value(i) ), i );
765 //sfw.Init(theCurWire, F, Precision::Confusion());
767 //theCurWire = sfw.Wire();
768 theCurWire = sbwd->Wire();
770 Standard_Boolean done = Standard_False;
771 Standard_Real tol = Precision::Confusion();
772 TopoDS_Edge theFirstEdge, theSecondEdge;
773 Standard_Real d1=0,d2=0;
774 for (TopExp_Explorer exp_e (F,TopAbs_EDGE); exp_e.More(); exp_e.Next())
780 theFirstEdge = TopoDS::Edge (exp_e.Current());
781 V1 = TopExp::FirstVertex(theFirstEdge);
782 V2 = TopExp::LastVertex(theFirstEdge);
783 p1 = BRep_Tool::Pnt(V1);
784 p2 = BRep_Tool::Pnt(V2);
785 tol = Max(BRep_Tool::Tolerance(V1), BRep_Tool::Tolerance(V2));
786 if (toler > 0) //tol = Max(tol, toler); gka
788 d1 = p1.Distance(p2);
789 if (d1 == 0) return Standard_False;
790 if (d1/tol>=1) coef1 = d1/tol; else continue;
791 if (coef1<=3) continue;
795 //Check the length of edge
796 theSecondEdge = TopoDS::Edge (exp_e.Current());
797 V1 = TopExp::FirstVertex(theSecondEdge);
798 V2 = TopExp::LastVertex(theSecondEdge);
800 p1 = BRep_Tool::Pnt(V1);
801 p2 = BRep_Tool::Pnt(V2);
802 if (toler == -1) tol = Max(BRep_Tool::Tolerance(V1), BRep_Tool::Tolerance(V2));
804 if (p1.Distance(p2)> tol) continue;
805 //If there are two pin edges, record them in diagnostic
806 d2 = p1.Distance(p2); //gka
807 if (d2 == 0) return Standard_False;
808 if (d2/tol >= 1) coef2 = d2/tol; else continue;
809 if (coef2<=3) continue;
810 if (coef1>coef2*10) continue;
813 theFirstEdge = theSecondEdge;
818 if (CheckPinEdges(theFirstEdge, theSecondEdge, coef1, coef2,toler))
820 mapEdges.Bind(theFirstEdge,theSecondEdge);
821 myStatusPinFace = ShapeExtend::EncodeStatus (ShapeExtend_DONE);
822 done = Standard_True;
825 theFirstEdge = theSecondEdge;
833 //=======================================================================
834 //function : CheckPinEdges
836 //=======================================================================
837 // Warning: This function not tested on many examples
839 Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckPinEdges(const TopoDS_Edge& theFirstEdge,const TopoDS_Edge& theSecondEdge,const Standard_Real coef1,
840 const Standard_Real coef2,const Standard_Real toler) const
843 Standard_Real cf1,cl1,cf2,cl2;
844 Handle(Geom_Curve) C1,C2,C3;
845 C1 = BRep_Tool::Curve (theFirstEdge,cf1,cl1);
846 C2 = BRep_Tool::Curve (theSecondEdge,cf2,cl2);
847 gp_Pnt p1, p2, pp1, pp2, pv;
848 Standard_Real d1 = (cf1-cl1)/coef1;
849 Standard_Real d2 = (cf2-cl2)/coef2;
850 //Standard_Real d1 = cf1-cl1/30; //10; gka
851 //Standard_Real d2 = cf2-cl2/30; //10;
854 pp1 = C2->Value(cf2);
855 pp2 = C2->Value(cl2);
857 Standard_Real paramc1=0, paramc2=0; // =0 for deleting warning (skl)
858 TopoDS_Vertex theSharedV = TopExp::LastVertex(theFirstEdge);
859 if (toler == -1) tol = BRep_Tool::Tolerance(theSharedV); else tol = toler;
860 pv = BRep_Tool::Pnt(theSharedV);
861 if (pv.Distance(p1)<=tol) paramc1 = cf1;
862 else if(pv.Distance(p2)<=tol) paramc1 = cl1;
863 if (pv.Distance(pp1)<=tol) paramc2 = cf2;
864 else if(pv.Distance(pp2)<=tol) paramc2 = cl2;
865 //Computing first derivative vectors and compare angle
866 // gp_Vec V11, V12, V21, V22;
868 // C1->D2(paramc1, tmp, V11, V21);
869 // C2->D2(paramc2, tmp, V12, V22);
870 // Standard_Real angle1, angle2;
872 // angle1 = V11.Angle(V12);
873 // angle2 = V21.Angle(V22);
875 // catch (Standard_Failure)
877 // cout << "Couldn't compute angle between derivative vectors" <<endl;
878 // return Standard_False;
880 // cout << "angle1 " << angle1<< endl;
881 // cout << "angle2 " << angle2<< endl;
882 // if (angle1<=0.0001) return Standard_True;
884 if (p1.Distance(p2)<pp1.Distance(pp2))
888 proj = C1->Value(paramc1 + (coef1-3)*d1);
889 else proj = C1->Value(paramc1-3*d1);
890 //proj = C1->Value(paramc1 + 9*d1);
891 //else proj = C1->Value(paramc1-d1);
897 proj = C2->Value(paramc2 + (coef2-3)*d2);
898 else proj = C2->Value(paramc2 -3*d2);
899 //proj = C2->Value(paramc2 + 9*d2);
900 //else proj = C2->Value(paramc2 -d2);
903 GeomAdaptor_Curve GAC(C3);
904 Standard_Real f = C3->FirstParameter();
905 Standard_Real l = C3->LastParameter();
907 ShapeAnalysis_Curve SAC;
908 Standard_Real dist = SAC.Project (GAC,proj,tol,result,param);
909 //pdn check if parameter of projection is in the domain of the edge.
910 if (param < f || param > l) return Standard_False;
911 if (dist > tol) return Standard_False;
913 //Computing first derivative vectors and compare angle
914 gp_Vec V11, V12, V21, V22;
916 C1->D2(paramc1, tmp, V11, V21);
917 C2->D2(paramc2, tmp, V12, V22);
918 Standard_Real angle1=0, angle2=0;
920 angle1 = V11.Angle(V12);
921 angle2 = V21.Angle(V22);
923 catch (Standard_Failure)
926 cout << "Couldn't compute angle between derivative vectors" <<endl;
928 return Standard_False;
930 // cout << "angle1 " << angle1<< endl;
931 // cout << "angle2 " << angle2<< endl;
932 if ((angle1<=0.001 && angle2<=0.01) || ((M_PI-angle2)<= 0.001 && (M_PI-angle2)<= 0.01)) return Standard_True;
933 else return Standard_False;
936 return Standard_False;