// Copyright (c) 1999-2012 OPEN CASCADE SAS // // The content of this file is subject to the Open CASCADE Technology Public // License Version 6.5 (the "License"). You may not use the content of this file // except in compliance with the License. Please obtain a copy of the License // at http://www.opencascade.org and read it completely before using this file. // // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. // // The Original Code and all software distributed under the License is // distributed on an "AS IS" basis, without warranty of any kind, and the // Initial Developer hereby disclaims all such warranties, including without // limitation, any warranties of merchantability, fitness for a particular // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //======================================================= //function : ShapeAnalysis_CheckSmallFace //purpose : //======================================================================= ShapeAnalysis_CheckSmallFace::ShapeAnalysis_CheckSmallFace() { myStatusSpot = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); myStatusStrip = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); myStatusPin = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); myStatusTwisted = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); myStatusSplitVert = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); } static void MinMaxPnt (const gp_Pnt& p, Standard_Integer& nb, Standard_Real& minx, Standard_Real& miny, Standard_Real& minz, Standard_Real& maxx, Standard_Real& maxy, Standard_Real& maxz) { Standard_Real x,y,z; p.Coord (x,y,z); if (nb < 1) { minx = maxx = x; miny = maxy = y; minz = maxz = z; } else { if (minx > x) minx = x; if (maxx < x) maxx = x; if (miny > y) miny = y; if (maxy < y) maxy = y; if (minz > z) minz = z; if (maxz < z) maxz = z; } nb ++; } static Standard_Boolean MinMaxSmall (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) { Standard_Real dx = maxx - minx; Standard_Real dy = maxy - miny; Standard_Real dz = maxz - minz; if ((dx > toler && !Precision::IsInfinite (dx)) || (dy > toler && !Precision::IsInfinite (dy)) || (dz > toler && !Precision::IsInfinite (dz))) return Standard_False; return Standard_True; } //======================================================================= //function : IsSpotFace //purpose : //======================================================================= Standard_Integer ShapeAnalysis_CheckSmallFace::IsSpotFace(const TopoDS_Face& F,gp_Pnt& spot,Standard_Real& spotol,const Standard_Real tol) const { Standard_Real toler = tol; Standard_Real tolv = tol; // Compute tolerance to get : from greatest tol of vertices // In addition, also computes min-max of vertices // To finally compare mini-max box with tolerance // gka Mar2000 Protection against faces without wires // but they occur due to bugs in the algorithm itself, it needs to be fixed Standard_Boolean isWir = Standard_False; for(TopoDS_Iterator itw(F,Standard_False) ; itw.More();itw.Next()) { if(itw.Value().ShapeType() != TopAbs_WIRE) continue; TopoDS_Wire w1 = TopoDS::Wire(itw.Value()); if (!w1.IsNull()) {isWir = Standard_True; break;} } if(!isWir) return Standard_True; Standard_Integer nbv = 0; Standard_Real minx =0 ,miny = 0 ,minz = 0,maxx = Precision::Infinite(), maxy = Precision::Infinite(),maxz = Precision::Infinite(); TopoDS_Vertex V0; Standard_Boolean same = Standard_True; for (TopExp_Explorer iv(F,TopAbs_VERTEX); iv.More(); iv.Next()) { TopoDS_Vertex V = TopoDS::Vertex (iv.Current()); if (V0.IsNull()) V0 = V; else if (same) { if (!V0.IsSame(V)) same = Standard_False; } gp_Pnt pnt = BRep_Tool::Pnt (V); // Standard_Real x,y,z; MinMaxPnt (pnt, nbv, minx,miny,minz, maxx,maxy,maxz); if (tol < 0) { tolv = BRep_Tool::Tolerance (V); if (tolv > toler) toler = tolv; } } // Now, testing if (!MinMaxSmall(minx,miny,minz,maxx,maxy,maxz,toler)) return 0; // All vertices are confused // Check edges (a closed edge may be a non-null length edge !) // By picking intermediate point on each one for (TopExp_Explorer ie(F,TopAbs_EDGE); ie.More(); ie.Next()) { TopoDS_Edge E = TopoDS::Edge (ie.Current()); Standard_Real cf,cl; Handle(Geom_Curve) C3D = BRep_Tool::Curve (E,cf,cl); if (C3D.IsNull()) continue; gp_Pnt debut = C3D->Value (cf); gp_Pnt milieu = C3D->Value ( (cf+cl)/2); if (debut.SquareDistance(milieu) > toler*toler) return 0; } spot.SetCoord ( (minx+maxx)/2. , (miny+maxy)/2. , (minz+maxz)/2. ); spotol = maxx-minx; spotol = Max (spotol, maxy-miny); spotol = Max (spotol, maxz-minz); spotol = spotol/2.; return (same ? 2 : 1); } //======================================================================= //function : CheckSpotFace //purpose : //======================================================================= Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckSpotFace(const TopoDS_Face& F,const Standard_Real tol) { gp_Pnt spot; Standard_Real spotol; Standard_Integer stat = IsSpotFace (F,spot,spotol,tol); if(!stat) return Standard_False; switch(stat) { case 1: myStatusSpot = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); break; case 2: myStatusSpot = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); break; default : break; } return Standard_True; } //======================================================================= //function : IsStripSupport //purpose : //======================================================================= Standard_Boolean ShapeAnalysis_CheckSmallFace::IsStripSupport(const TopoDS_Face& F,const Standard_Real tol) { Standard_Real toler = tol; if (toler < 0) toler = 1.e-07; // ?? better to compute tolerance zones TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface (F,loc); if (surf.IsNull()) return 0; // Checking on poles for bezier-bspline // A more general way is to check Values by scanning ISOS (slower) Handle(Geom_BSplineSurface) bs = Handle(Geom_BSplineSurface)::DownCast(surf); Handle(Geom_BezierSurface) bz = Handle(Geom_BezierSurface)::DownCast(surf); // Standard_Integer stat = 2; // 2 : small in V direction if (!bs.IsNull() || !bz.IsNull()) { Standard_Boolean cbz = (!bz.IsNull()); Standard_Integer iu,iv, nbu, nbv; if (cbz) { nbu = bz->NbUPoles(), nbv = bz->NbVPoles(); } else { nbu = bs->NbUPoles(), nbv = bs->NbVPoles(); } // Standard_Real dx = 0, dy = 0, dz = 0; // Standard_Real x,y,z; Standard_Real minx,miny,minz,maxx,maxy,maxz; Standard_Boolean issmall = Standard_True; for (iu = 1; iu <= nbu; iu ++) { // for each U line, scan poles in V (V direction) Standard_Integer nb = 0; for (iv = 1; iv <= nbv; iv ++) { gp_Pnt unp = (cbz ? bz->Pole(iu,iv) : bs->Pole(iu,iv)); MinMaxPnt (unp, nb, minx,miny,minz, maxx,maxy,maxz); } if (!MinMaxSmall(minx,miny,minz,maxx,maxy,maxz,toler)) { issmall = Standard_False; break; } // small in V ? } if (issmall) { myStatusStrip = ShapeExtend::EncodeStatus ( ShapeExtend_DONE2); return issmall; // OK, small in V } issmall = Standard_True; for (iv = 1; iv <= nbv; iv ++) { // for each V line, scan poles in U (U direction) Standard_Integer nb = 0; for (iu = 1; iu <= nbu; iu ++) { gp_Pnt unp = (cbz ? bz->Pole(iu,iv) : bs->Pole(iu,iv)); MinMaxPnt (unp, nb, minx,miny,minz, maxx,maxy,maxz); } if (!MinMaxSmall(minx,miny,minz,maxx,maxy,maxz,toler)) { issmall = Standard_False; break; } // small in U ? } if (issmall) { myStatusStrip = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); return issmall; }// OK, small in U } return Standard_False; } //======================================================================= //function : CheckStripEdges //purpose : //======================================================================= Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckStripEdges(const TopoDS_Edge& E1,const TopoDS_Edge& E2,const Standard_Real tol,Standard_Real& dmax) const { // We have the topological configuration OK : 2 edges, 2 vertices // But, are these two edges well confused ? Standard_Real toler = tol; if (tol < 0) { Standard_Real tole = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2); if (toler < tole / 2.) toler = tole/2.; } // We project a list of points from each curve, on the opposite one, // we check the distance Standard_Integer nbint = 10; ShapeAnalysis_Curve SAC; Standard_Real cf1,cl1,cf2,cl2,u; dmax = 0; Handle(Geom_Curve) C1,C2; C1 = BRep_Tool::Curve (E1,cf1,cl1); C2 = BRep_Tool::Curve (E2,cf2,cl2); if(C1.IsNull() || C2.IsNull()) return Standard_False; cf1 = Max(cf1, C1->FirstParameter()); cl1 = Min(cl1, C1->LastParameter()); Handle(Geom_TrimmedCurve) C1T = new Geom_TrimmedCurve(C1,cf1,cl1,Standard_True); //pdn protection against feature in Trimmed_Curve cf1 = C1T->FirstParameter(); cl1 = C1T->LastParameter(); Handle(Geom_TrimmedCurve) CC; cf2 = Max(cf2, C2->FirstParameter()); cl2 = Min(cl2, C2->LastParameter()); Handle(Geom_TrimmedCurve) C2T = new Geom_TrimmedCurve(C2,cf2,cl2, Standard_True); cf2 = C2T->FirstParameter(); cl2 = C2T->LastParameter(); Standard_Real cd1 = (cl1 - cf1)/nbint; Standard_Real cd2 = (cl2 - cf2)/nbint; Standard_Real f,l; f = cf2; l = cl2; for (int numcur = 0; numcur < 2; numcur ++) { u = cf1; if (numcur) { CC = C1T; C1T = C2T; C2T = CC; cd1 = cd2; //smh added replacing step and replacing first u = cf2; //parameter f = cf1; l = cl1; } for (int nump = 0; nump <= nbint; nump ++) { gp_Pnt p2, p1 = C1T->Value (u); Standard_Real para; //pdn Adaptor curve is used to avoid of enhancing of domain. GeomAdaptor_Curve GAC(C2T); Standard_Real dist = SAC.Project (GAC,p1,toler,p2,para); //pdn check if parameter of projection is in the domain of the edge. if (para < f || para > l) return Standard_False; if (dist > dmax) dmax = dist; if (dist > toler) return Standard_False; u += cd1; } } return (dmax < toler); } //======================================================================= //function : FindStripEdges //purpose : //======================================================================= Standard_Boolean ShapeAnalysis_CheckSmallFace::FindStripEdges(const TopoDS_Face& F,TopoDS_Edge& E1,TopoDS_Edge& E2,const Standard_Real tol,Standard_Real& dmax) { E1.Nullify(); E2.Nullify(); Standard_Integer nb = 0; for (TopExp_Explorer ex(F,TopAbs_EDGE); ex.More(); ex.Next()) { TopoDS_Edge E = TopoDS::Edge (ex.Current()); if (nb == 1 && E.IsSame(E1)) continue; // ignore seam edge TopoDS_Vertex V1,V2; TopExp::Vertices (E,V1,V2); gp_Pnt p1,p2; p1 = BRep_Tool::Pnt (V1); p2 = BRep_Tool::Pnt (V2); Standard_Real toler = tol; if (toler <= 0) toler = (BRep_Tool::Tolerance(V1) + BRep_Tool::Tolerance(V2) ) / 2.; // Extremities Standard_Real dist = p1.Distance(p2); // Middle point Standard_Real cf,cl; Handle(Geom_Curve) CC; CC = BRep_Tool::Curve (E,cf,cl); Standard_Boolean isNullLength = Standard_True; if (!CC.IsNull()) { gp_Pnt pp = CC->Value ( (cf+cl)/2.); if (pp.Distance(p1) < toler && pp.Distance(p2) < toler) continue; isNullLength = Standard_False; } if (dist <= toler && isNullLength) continue; //smh nb ++; if (nb == 1) E1 = E; else if (nb == 2) E2 = E; else return Standard_False; } // Now, check these two edge to define a strip ! if (!E1.IsNull()&&!E2.IsNull()) if(!CheckStripEdges (E1,E2,tol,dmax)) return Standard_False; else { myStatusStrip = ShapeExtend::EncodeStatus (ShapeExtend_DONE3); return Standard_True ; } return Standard_False; } //======================================================================= //function : CheckSingleStrip //purpose : //======================================================================= Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckSingleStrip(const TopoDS_Face& F, TopoDS_Edge& E1, TopoDS_Edge& E2,const Standard_Real tol) { Standard_Real toler = tol; Standard_Real minx,miny,minz,maxx,maxy,maxz; // In this case, we have 2 vertices and 2 great edges. Plus possibly 2 small // edges, one on each vertex TopoDS_Vertex V1,V2; Standard_Integer nb = 0; for (TopExp_Explorer itv (F,TopAbs_VERTEX); itv.More(); itv.Next()) { TopoDS_Vertex V = TopoDS::Vertex (itv.Current()); if (V1.IsNull()) V1 = V; else if (V1.IsSame(V)) continue; else if (V2.IsNull()) V2 = V; else if (V2.IsSame(V)) continue; else return 0; } // Checking edges //TopoDS_Edge E1,E2; nb = 0; for (TopExp_Explorer ite (F,TopAbs_EDGE); ite.More(); ite.Next()) { TopoDS_Edge E = TopoDS::Edge (ite.Current()); if (nb == 1 && E.IsSame(E1)) continue; // ignore seam edge TopoDS_Vertex VA,VB; TopExp::Vertices (E,VA,VB); if (tol < 0) { Standard_Real tolv; tolv = BRep_Tool::Tolerance (VA); if (toler < tolv) toler = tolv; tolv = BRep_Tool::Tolerance (VB); if (toler < tolv) toler = tolv; } // Edge on same vertex : small one ? if (VA.IsSame(VB)) { Standard_Real cf,cl; Handle(Geom_Curve) C3D; if (!BRep_Tool::Degenerated(E)) C3D = BRep_Tool::Curve (E,cf,cl); if (C3D.IsNull()) continue; // DGNR Standard_Integer np = 0; gp_Pnt deb = C3D->Value(cf); MinMaxPnt (deb,np,minx,miny,minz,maxx,maxy,maxz); gp_Pnt fin = C3D->Value(cl); MinMaxPnt (fin,np,minx,miny,minz,maxx,maxy,maxz); gp_Pnt mid = C3D->Value( (cf+cl)/2. ); MinMaxPnt (mid,np,minx,miny,minz,maxx,maxy,maxz); if (!MinMaxSmall (minx,miny,minz,maxx,maxy,maxz,toler)) return Standard_False; } else { // Other case : two maximum allowed nb ++; if (nb > 2) return Standard_False; if (nb == 1) { V1 = VA; V2 = VB; E1 = E; } else if (nb == 2) { if (V1.IsSame(VA) && !V2.IsSame(VB)) return Standard_False; if (V1.IsSame(VB) && !V2.IsSame(VA)) return Standard_False; E2 = E; } else return Standard_False; } } if (nb < 2) return Standard_False; // only one vertex : cannot be a strip ... // Checking if E1 and E2 define a Strip Standard_Real dmax; if (!CheckStripEdges (E1,E2,tol,dmax)) return Standard_False; myStatusStrip = ShapeExtend::EncodeStatus (ShapeExtend_DONE3); return Standard_True; } //======================================================================= //function : CheckStripFace //purpose : //======================================================================= Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckStripFace(const TopoDS_Face& F, TopoDS_Edge& E1, TopoDS_Edge& E2,const Standard_Real tol) { // Standard_Integer stat; if(CheckSingleStrip (F,E1,E2,tol)) return Standard_True ; // it is a strip // IsStripSupport used as rejection. But this kind of test may be done // on ANY face, once we are SURE that FindStripEdges is reliable (and fast // enough) // ?? record a diagnostic StripFace, but without yet lists of edges // ?? Record Diagnostic "StripFace", no data (should be "Edges1" "Edges2") // but direction is known (1:U 2:V) // TopoDS_Edge E1,E2; Standard_Real dmax; if(FindStripEdges (F,E1,E2,tol,dmax)) return Standard_True; // Now, trying edges : if there are 2 and only 2 edges greater than tolerance // (given or sum of vertex tolerances), do they define a strip // Warning : if yes, they bring different vertices ... return Standard_False; } //======================================================================= //function : CheckSplittingVertices //purpose : //======================================================================= Standard_Integer ShapeAnalysis_CheckSmallFace::CheckSplittingVertices(const TopoDS_Face& F, TopTools_DataMapOfShapeListOfShape& MapEdges, ShapeAnalysis_DataMapOfShapeListOfReal& MapParam, TopoDS_Compound& theAllVert) { // Prepare array of vertices with their locations //TopTools Standard_Integer nbv = 0, nbp = 0; //TopoDS_Compound theAllVert; BRep_Builder theBuilder; //theBuilder.MakeCompound(theAllVert); TopExp_Explorer itv; // svv Jan11 2000 : porting on DEC for (itv.Init(F,TopAbs_VERTEX); itv.More(); itv.Next()) nbv ++; if (nbv == 0) return 0; TopTools_Array1OfShape vtx (1,nbv); TColgp_Array1OfPnt vtp (1,nbv); TColStd_Array1OfReal vto (1,nbv); nbp = 0; for (itv.Init(F,TopAbs_VERTEX); itv.More(); itv.Next()) { nbp ++; TopoDS_Vertex unv = TopoDS::Vertex (itv.Current()); vtx.SetValue (nbp,unv); gp_Pnt unp = BRep_Tool::Pnt (unv); vtp.SetValue (nbp,unp); Standard_Real unt = myPrecision; if (unt < 0) unt =BRep_Tool::Tolerance (unv); vto.SetValue (nbp,unt); } nbv = nbp; nbp = 0; // now, counting splitting vertices // Check edges : are vertices (other than extremities) confused with it ? ShapeAnalysis_Curve SAC; for (Standard_Integer iv = 1; iv <= nbv; iv ++) { TopoDS_Vertex V = TopoDS::Vertex (vtx.Value(iv)); TopTools_ListOfShape listEdge; TColStd_ListOfReal listParam; Standard_Boolean issplit = Standard_False; for (TopExp_Explorer ite(F,TopAbs_EDGE); ite.More(); ite.Next()) { TopoDS_Edge E = TopoDS::Edge (ite.Current()); TopoDS_Vertex V1,V2; TopExp::Vertices (E,V1,V2); Standard_Real cf,cl; Handle(Geom_Curve) C3D = BRep_Tool::Curve (E,cf,cl); if (C3D.IsNull()) continue; if (V.IsSame(V1) || V.IsSame(V2)) continue; gp_Pnt unp = vtp.Value(iv); Standard_Real unt = vto.Value(iv); gp_Pnt proj; Standard_Real param; Standard_Real dist = SAC.Project (C3D,unp,unt*10.,proj,param,cf,cl); if (dist == 0.0) continue; //smh // Splitting Vertex to record ? if (dist < unt) { // If Split occurs at beginning or end, it is not a split ... Standard_Real fpar, lpar, eps = 1.e-06; if (param >=cl || param <= cf) continue; // Out of range fpar = param - cf; lpar = param - cl; if ((Abs(fpar) < eps) || (Abs(lpar) < eps)) continue; // Near end or start listEdge.Append(E); listParam.Append(param); issplit = Standard_True; } } if(issplit) { nbp ++; theBuilder.Add(theAllVert, V); MapEdges.Bind(V,listEdge); MapParam.Bind(V,listParam); } } if(nbp != 0) myStatusSplitVert = ShapeExtend::EncodeStatus (ShapeExtend_DONE); return nbp; } static Standard_Integer IsoStat (const TColgp_Array2OfPnt& poles, const Standard_Integer uorv, const Standard_Integer rank, const Standard_Real tolpin, const Standard_Real toler) { Standard_Integer i, np = 0; Standard_Integer i0 = (uorv == 1 ? poles.LowerCol() : poles.LowerRow()); Standard_Integer i1 = (uorv == 1 ? poles.UpperCol() : poles.UpperRow()); Standard_Real xmin,ymin,zmin, xmax,ymax,zmax; for (i = i0; i <= i1; i ++) { if (uorv == 1) MinMaxPnt (poles(rank,i),np,xmin,ymin,zmin, xmax,ymax,zmax); else MinMaxPnt (poles(i,rank), np, xmin,ymin,zmin, xmax,ymax,zmax); } if (MinMaxSmall (xmin,ymin,zmin, xmax,ymax,zmax, tolpin)) return 0; if (MinMaxSmall (xmin,ymin,zmin, xmax,ymax,zmax, toler)) return 1; return 2; } static Standard_Boolean CheckPoles(const TColgp_Array2OfPnt& poles, Standard_Integer uorv, Standard_Integer rank) { Standard_Integer i0 = (uorv == 1 ? poles.LowerCol() : poles.LowerRow()); Standard_Integer i1 = (uorv == 1 ? poles.UpperCol() : poles.UpperRow()); for (Standard_Integer i = i0; i <= i1-1; i ++) { if (uorv == 1) { if(poles(rank,i).IsEqual(poles(rank, i+1), 1e-15)) return Standard_True; } else if(poles(i,rank).IsEqual(poles(i+1,rank), 1e-15)) return Standard_True; } return Standard_False; } //======================================================================= //function : CheckPin //purpose : //======================================================================= Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckPin (const TopoDS_Face& F, Standard_Integer& whatrow,Standard_Integer& sens) { TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface (F,loc); if (surf->IsKind(STANDARD_TYPE(Geom_ElementarySurface))) return Standard_False; Standard_Real toler = myPrecision; if (toler < 0) toler = 1.e-4; Standard_Real tolpin = 1.e-9; // for sharp sharp pin // Checking the poles // Take the poles : they give good idea of sharpness of a pin Standard_Integer nbu = 0 , nbv = 0; Handle(Geom_BSplineSurface) bs = Handle(Geom_BSplineSurface)::DownCast(surf); Handle(Geom_BezierSurface) bz = Handle(Geom_BezierSurface)::DownCast(surf); if (!bs.IsNull()) { nbu = bs->NbUPoles(); nbv = bs->NbVPoles(); } if (!bz.IsNull()) { nbu = bz->NbUPoles(); nbv = bz->NbVPoles(); } if (nbu == 0 || nbv == 0) return Standard_False; TColgp_Array2OfPnt allpoles (1,nbu,1,nbv); if (!bs.IsNull()) bs->Poles (allpoles); if (!bz.IsNull()) bz->Poles (allpoles); // Check each natural bound if it is a singularity (i.e. a pin) sens = 0; Standard_Integer stat = 0; // 0 none, 1 in U, 2 in V whatrow = 0; // 0 no row, else rank of row stat = IsoStat(allpoles,1, 1,tolpin,toler); if (stat) { sens = 1; whatrow = nbu; } stat = IsoStat(allpoles,1,nbu,tolpin,toler); if (stat) { sens = 1; whatrow = nbu; } stat = IsoStat(allpoles,2, 1,tolpin,toler); if (stat) { sens = 2; whatrow = 1; } stat = IsoStat(allpoles,2,nbv,tolpin,toler); if (stat) { sens = 2; whatrow = nbv; } if (!sens) return Standard_False; // no pin switch(stat) { case 1: myStatusPin = ShapeExtend::EncodeStatus (ShapeExtend_DONE1); break; case 2: myStatusPin = ShapeExtend::EncodeStatus (ShapeExtend_DONE2); break; default : break; } // cout<<(whatstat == 1 ? "Smooth" : "Sharp")<<" Pin on "<<(sens == 1 ? "U" : "V")<<" Row n0 "<IsKind(STANDARD_TYPE(Geom_ElementarySurface))) return Standard_False; Standard_Real toler = myPrecision; if (toler < 0) toler = 1.e-4; //// GeomLProp_SLProps GLS (surf,2,toler); GeomAdaptor_Surface GAS (surf); // to be done : on isos of the surface // and on edges, at least of outer wire Standard_Integer nbint = 5; TColStd_Array2OfReal nx (1,nbint+1,1,nbint+1); TColStd_Array2OfReal ny (1,nbint+1,1,nbint+1); TColStd_Array2OfReal nz (1,nbint+1,1,nbint+1); Standard_Integer iu,iv; Standard_Real umin,umax,vmin,vmax; surf->Bounds (umin,umax,vmin,vmax); Standard_Real u = umin, du = (umax-umin)/nbint; Standard_Real v = vmin, dv = (umax-umin)/nbint; // gp_Dir norm; for (iu = 1; iu <= nbint; iu ++) { for (iv = 1; iv <= nbint; iv ++) { // GLS.SetParameters (u,v); // if (GLS.IsNormalDefined()) norm = GLS.Normal(); gp_Pnt curp; gp_Vec V1,V2,VXnorm; GAS.D1 (u,v,curp,V1,V2); VXnorm = V1.Crossed(V2); nx.SetValue (iu,iv,VXnorm.X()); ny.SetValue (iu,iv,VXnorm.Y()); nz.SetValue (iu,iv,VXnorm.Z()); v += dv; } u += du; v = vmin; } // Now, comparing normals on support surface, in both senses // In principle, it suffuces to check within outer bound for (iu = 1; iu < nbint; iu ++) { for (iv = 1; iv < nbint; iv ++) { // We here check each normal (iu,iv) with (iu,iv+1) and with (iu+1,iv) // if for each test, we have negative scalar product, this means angle > 90deg // it is the criterion to say it is twisted if (TwistedNorm ( nx(iu,iv),ny(iu,iv),nz(iu,iv) , nx(iu,iv+1),ny(iu,iv+1),nz(iu,iv+1) ) < 0. || TwistedNorm ( nx(iu,iv),ny(iu,iv),nz(iu,iv) , nx(iu+1,iv),ny(iu+1,iv),nz(iu+1,iv) ) < 0. ) { myStatusTwisted = ShapeExtend::EncodeStatus (ShapeExtend_DONE); paramu = umin+du*iu-du/2; paramv = vmin+dv*iv-dv/2; return Standard_True; } } } // Now, comparing normals on edges ... to be done return Standard_False; } //======================================================================= //function : CheckPinFace //purpose : //======================================================================= // Warning: This function not tested on many examples Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckPinFace(const TopoDS_Face& F, TopTools_DataMapOfShapeShape& mapEdges,const Standard_Real toler) { //ShapeFix_Wire sfw; TopExp_Explorer exp_w (F,TopAbs_WIRE); exp_w.More(); Standard_Real coef1=0, coef2; // =0 for deleting warning (skl) TopoDS_Wire theCurWire = TopoDS::Wire (exp_w.Current()); ShapeAnalysis_WireOrder wi; ShapeAnalysis_Wire sfw; Handle(ShapeExtend_WireData) sbwd = new ShapeExtend_WireData(theCurWire); sfw.Load(sbwd); sfw.CheckOrder(wi); Handle(TopTools_HSequenceOfShape) newedges = new TopTools_HSequenceOfShape(); Standard_Integer nb = wi.NbEdges(); Standard_Integer i = 0; for ( i=1; i <= nb; i++ ) newedges->Append ( sbwd->Edge ( wi.Ordered(i) ) ); for ( i=1; i <= nb; i++ ) sbwd->Set ( TopoDS::Edge ( newedges->Value(i) ), i ); //sfw.Init(theCurWire, F, Precision::Confusion()); //sfw.FixReorder(); //theCurWire = sfw.Wire(); theCurWire = sbwd->Wire(); i=1; Standard_Boolean done = Standard_False; Standard_Real tol = Precision::Confusion(); TopoDS_Edge theFirstEdge, theSecondEdge; Standard_Real d1=0,d2=0; for (TopExp_Explorer exp_e (F,TopAbs_EDGE); exp_e.More(); exp_e.Next()) { TopoDS_Vertex V1,V2; gp_Pnt p1, p2; if (i==1) { theFirstEdge = TopoDS::Edge (exp_e.Current()); V1 = TopExp::FirstVertex(theFirstEdge); V2 = TopExp::LastVertex(theFirstEdge); p1 = BRep_Tool::Pnt(V1); p2 = BRep_Tool::Pnt(V2); tol = Max(BRep_Tool::Tolerance(V1), BRep_Tool::Tolerance(V2)); if (toler > 0) //tol = Max(tol, toler); gka tol = toler; d1 = p1.Distance(p2); if (d1 == 0) return Standard_False; if (d1/tol>=1) coef1 = d1/tol; else continue; if (coef1<=3) continue; i++; continue; } //Check the length of edge theSecondEdge = TopoDS::Edge (exp_e.Current()); V1 = TopExp::FirstVertex(theSecondEdge); V2 = TopExp::LastVertex(theSecondEdge); p1 = BRep_Tool::Pnt(V1); p2 = BRep_Tool::Pnt(V2); if (toler == -1) tol = Max(BRep_Tool::Tolerance(V1), BRep_Tool::Tolerance(V2)); else tol= toler; if (p1.Distance(p2)> tol) continue; //If there are two pin edges, record them in diagnostic d2 = p1.Distance(p2); //gka if (d2 == 0) return Standard_False; if (d2/tol >= 1) coef2 = d2/tol; else continue; if (coef2<=3) continue; if (coef1>coef2*10) continue; if (coef2>coef1*10) { theFirstEdge = theSecondEdge; coef1 = coef2; continue; } if (CheckPinEdges(theFirstEdge, theSecondEdge, coef1, coef2,toler)) { mapEdges.Bind(theFirstEdge,theSecondEdge); myStatusPinFace = ShapeExtend::EncodeStatus (ShapeExtend_DONE); done = Standard_True; } theFirstEdge = theSecondEdge; coef1 = coef2; //d1 = d2; } return done; } //======================================================================= //function : CheckPinEdges //purpose : //======================================================================= // Warning: This function not tested on many examples Standard_Boolean ShapeAnalysis_CheckSmallFace::CheckPinEdges(const TopoDS_Edge& theFirstEdge,const TopoDS_Edge& theSecondEdge,const Standard_Real coef1, const Standard_Real coef2,const Standard_Real toler) const { Standard_Real cf1,cl1,cf2,cl2; Handle(Geom_Curve) C1,C2,C3; C1 = BRep_Tool::Curve (theFirstEdge,cf1,cl1); C2 = BRep_Tool::Curve (theSecondEdge,cf2,cl2); gp_Pnt p1, p2, pp1, pp2, pv; Standard_Real d1 = (cf1-cl1)/coef1; Standard_Real d2 = (cf2-cl2)/coef2; //Standard_Real d1 = cf1-cl1/30; //10; gka //Standard_Real d2 = cf2-cl2/30; //10; p1 = C1->Value(cf1); p2 = C1->Value(cl1); pp1 = C2->Value(cf2); pp2 = C2->Value(cl2); Standard_Real tol; Standard_Real paramc1=0, paramc2=0; // =0 for deleting warning (skl) TopoDS_Vertex theSharedV = TopExp::LastVertex(theFirstEdge); if (toler == -1) tol = BRep_Tool::Tolerance(theSharedV); else tol = toler; pv = BRep_Tool::Pnt(theSharedV); if (pv.Distance(p1)<=tol) paramc1 = cf1; else if(pv.Distance(p2)<=tol) paramc1 = cl1; if (pv.Distance(pp1)<=tol) paramc2 = cf2; else if(pv.Distance(pp2)<=tol) paramc2 = cl2; //Computing first derivative vectors and compare angle // gp_Vec V11, V12, V21, V22; // gp_Pnt tmp; // C1->D2(paramc1, tmp, V11, V21); // C2->D2(paramc2, tmp, V12, V22); // Standard_Real angle1, angle2; // try{ // angle1 = V11.Angle(V12); // angle2 = V21.Angle(V22); // } // catch (Standard_Failure) // { // cout << "Couldn't compute angle between derivative vectors" <Value(paramc1 + (coef1-3)*d1); else proj = C1->Value(paramc1-3*d1); //proj = C1->Value(paramc1 + 9*d1); //else proj = C1->Value(paramc1-d1); } else { C3=C2; if (paramc2==cf2) proj = C2->Value(paramc2 + (coef2-3)*d2); else proj = C2->Value(paramc2 -3*d2); //proj = C2->Value(paramc2 + 9*d2); //else proj = C2->Value(paramc2 -d2); } Standard_Real param; GeomAdaptor_Curve GAC(C3); Standard_Real f = C3->FirstParameter(); Standard_Real l = C3->LastParameter(); gp_Pnt result; ShapeAnalysis_Curve SAC; Standard_Real dist = SAC.Project (GAC,proj,tol,result,param); //pdn check if parameter of projection is in the domain of the edge. if (param < f || param > l) return Standard_False; if (dist > tol) return Standard_False; if (dist <= tol) { //Computing first derivative vectors and compare angle gp_Vec V11, V12, V21, V22; gp_Pnt tmp; C1->D2(paramc1, tmp, V11, V21); C2->D2(paramc2, tmp, V12, V22); Standard_Real angle1=0, angle2=0; try{ angle1 = V11.Angle(V12); angle2 = V21.Angle(V22); } catch (Standard_Failure) { cout << "Couldn't compute angle between derivative vectors" <