0033018: Coding - get rid of unused headers [Plugin to ShapeAnalysis]
[occt.git] / src / ShapeAnalysis / ShapeAnalysis.cxx
1 // Created on: 2000-01-20
2 // Created by: data exchange team
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <ShapeAnalysis.hxx>
17
18 #include <Bnd_Box2d.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Surface.hxx>
22 #include <BRepGProp.hxx>
23 #include <BRepTools.hxx>
24 #include <BRepTopAdaptor_FClass2d.hxx>
25 #include <Geom2d_Curve.hxx>
26 #include <Geom_Surface.hxx>
27 #include <gp_Pnt2d.hxx>
28 #include <GProp_GProps.hxx>
29 #include <ShapeAnalysis_Curve.hxx>
30 #include <ShapeAnalysis_Edge.hxx>
31 #include <ShapeExtend_WireData.hxx>
32 #include <TColgp_SequenceOfPnt.hxx>
33 #include <TColgp_SequenceOfPnt2d.hxx>
34 #include <TopExp.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <TopoDS.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <TopoDS_Iterator.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Vertex.hxx>
42 #include <TopoDS_Wire.hxx>
43
44 // PLANTAGE IsOuterBound, 15-SEP-1998
45 //static Standard_Integer numpb = 0;
46 //=======================================================================
47 //function : AdjustByPeriod
48 //purpose  : 
49 //=======================================================================
50 Standard_Real ShapeAnalysis::AdjustByPeriod(const Standard_Real Val,
51                                             const Standard_Real ToVal,
52                                             const Standard_Real Period)
53 {
54   Standard_Real diff = Val - ToVal;
55   Standard_Real D = Abs ( diff );
56   Standard_Real P = Abs ( Period );
57   if ( D <= 0.5 * P ) return 0.;
58   if ( P < 1e-100 ) return diff;
59   return ( diff >0 ? -P : P ) * floor( D / P + 0.5 );
60 }
61
62 //=======================================================================
63 //function : AdjustToPeriod
64 //purpose  : 
65 //=======================================================================
66
67 Standard_Real ShapeAnalysis::AdjustToPeriod(const Standard_Real Val,
68                                             const Standard_Real ValMin,
69                                             const Standard_Real ValMax)
70 {
71   return AdjustByPeriod ( Val, 0.5 * ( ValMin + ValMax ), ValMax - ValMin );
72 }
73
74 //=======================================================================
75 //function : FindBounds
76 //purpose  : 
77 //=======================================================================
78
79  void ShapeAnalysis::FindBounds(const TopoDS_Shape& shape,TopoDS_Vertex& V1,TopoDS_Vertex& V2) 
80 {
81   V1.Nullify();
82   V2.Nullify();
83   ShapeAnalysis_Edge EA;
84   if (shape.ShapeType() == TopAbs_WIRE) {
85     TopoDS_Wire W = TopoDS::Wire(shape);
86     //invalid work with reversed wires replaced on TopExp
87     TopExp::Vertices(W,V1,V2);
88     //invalid work with reversed wires
89     /*TopoDS_Iterator iterWire(W);
90     //szv#4:S4163:12Mar99 optimized
91     if (iterWire.More()) {
92       TopoDS_Edge E = TopoDS::Edge (iterWire.Value());
93       V1 = EA.FirstVertex (E); iterWire.Next();
94       for ( ; iterWire.More(); iterWire.Next() ) E = TopoDS::Edge (iterWire.Value());
95       V2 = EA.LastVertex (E);
96     }*/
97   }
98   else if (shape.ShapeType() == TopAbs_EDGE) {
99     V1 = EA.FirstVertex (TopoDS::Edge (shape));
100     V2 = EA.LastVertex (TopoDS::Edge (shape));
101   }
102   else if (shape.ShapeType() == TopAbs_VERTEX)
103     V1 = V2 = TopoDS::Vertex (shape);
104 }
105
106
107 //=======================================================================
108 //function : ReverceSeq
109 //purpose  : auxiliary
110 //=======================================================================
111 template<class HSequence> 
112 static inline void ReverseSeq (HSequence& Seq)
113 {
114   Standard_Integer j=Seq.Length();
115   for(Standard_Integer i=1; i<Seq.Length(); i++) {
116     if(i>=j) break;
117     Seq.Exchange(i,j);
118     j--;
119   }
120 }
121 //=======================================================================
122 //function : TotCross2D
123 //purpose  : 
124 //=======================================================================
125
126 Standard_Real ShapeAnalysis::TotCross2D(const Handle(ShapeExtend_WireData)& sewd,
127                                         const TopoDS_Face& aFace)
128 {
129   Standard_Integer i, nbc = 0;
130   gp_Pnt2d fuv,luv, uv0;
131   Standard_Real totcross=0;
132   for(i=1; i<=sewd->NbEdges(); i++) {
133     TopoDS_Edge edge = sewd->Edge(i);
134     Standard_Real f2d, l2d;
135     Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(edge,aFace,f2d,l2d);
136     if ( !c2d.IsNull() ) {
137       nbc++;
138       TColgp_SequenceOfPnt2d SeqPnt;
139       ShapeAnalysis_Curve::GetSamplePoints (c2d, f2d, l2d, SeqPnt);
140       if( edge.Orientation()==1 )
141         ReverseSeq(SeqPnt);
142       if(nbc==1)  {
143         fuv=SeqPnt.Value(1);
144         uv0=fuv;
145       }
146       Standard_Integer j=1;
147       for( ; j<=SeqPnt.Length(); j++) {
148         luv = SeqPnt.Value(j);
149         totcross += (fuv.X()-luv.X())*(fuv.Y()+luv.Y())/2;
150         fuv=luv;
151       }
152     }
153   }
154   totcross += (fuv.X()-uv0.X())*(fuv.Y()+uv0.Y())/2;
155   return totcross;
156 }
157
158 //=======================================================================
159 //function : ContourArea
160 //purpose  : 
161 //=======================================================================
162
163 Standard_Real ShapeAnalysis::ContourArea(const TopoDS_Wire& theWire)
164                                          //const Handle(ShapeExtend_WireData)& sewd)
165                                         
166 {
167   Standard_Integer nbc = 0;
168   gp_Pnt fuv,luv, uv0;
169   //Standard_Real totcross=0;
170   gp_XYZ aTotal(0.,0.,0.);
171   TopoDS_Iterator aIte(theWire,Standard_False);
172   //for(i=1; i<=sewd->NbEdges(); i++) {
173   for( ; aIte.More(); aIte.Next()) {
174     TopoDS_Edge edge = TopoDS::Edge(aIte.Value()); //sewd->Edge(i);
175     Standard_Real first, last;
176     Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first, last);
177     if ( !c3d.IsNull() ) {
178       
179       TColgp_SequenceOfPnt aSeqPnt;
180       if(!ShapeAnalysis_Curve::GetSamplePoints (c3d, first, last, aSeqPnt))
181         continue;
182       nbc++;
183       if( edge.Orientation()==TopAbs_REVERSED )
184         ReverseSeq(aSeqPnt);
185       if(nbc==1)  {
186         fuv=aSeqPnt.Value(1);
187         uv0=fuv;
188       }
189       Standard_Integer j=1;
190       for( ; j<=aSeqPnt.Length(); j++) {
191         luv = aSeqPnt.Value(j);
192         aTotal += luv.XYZ()^ fuv.XYZ();//
193         fuv=luv;
194       }
195     }
196   }
197   aTotal += uv0.XYZ()^fuv.XYZ();//
198   Standard_Real anArea = aTotal.Modulus()*0.5;
199   return anArea;
200 }
201 //=======================================================================
202 //function : IsOuterBound
203 //purpose  : 
204 //=======================================================================
205
206 Standard_Boolean ShapeAnalysis::IsOuterBound(const TopoDS_Face& face) 
207 {
208   TopoDS_Face F = face;
209   TopoDS_Wire W;
210   F.Orientation(TopAbs_FORWARD);
211   Standard_Integer nbw = 0;
212   for (TopExp_Explorer exp(F,TopAbs_WIRE); exp.More(); exp.Next()) {
213     W = TopoDS::Wire   (exp.Current());  nbw ++;
214   }
215   //skl 08.04.2002
216   if (nbw == 1) {
217     Handle(ShapeExtend_WireData) sewd = new ShapeExtend_WireData(W);
218     Standard_Real totcross = TotCross2D(sewd,F);
219     return (totcross >= 0);
220   }
221   else {
222     BRepAdaptor_Surface Ads ( F, Standard_False ); 
223     Standard_Real tol = BRep_Tool::Tolerance(F);
224     Standard_Real toluv = Min ( Ads.UResolution(tol), Ads.VResolution(tol) );
225     BRepTopAdaptor_FClass2d fcl (F,toluv);
226     Standard_Boolean rescl = (fcl.PerformInfinitePoint () == TopAbs_OUT);
227     return rescl;
228   }
229 }
230
231 //=======================================================================
232 //function : OuterBound
233 //purpose  : replacement of bad BRepTools::OuterBound(), to be merged
234 // - skips internal vertices in face, if any, without exception
235 // - returns positively oriented wire rather than greater one
236 //=======================================================================
237
238 TopoDS_Wire ShapeAnalysis::OuterWire(const TopoDS_Face& face) 
239 {
240   TopoDS_Face F = face;
241   F.Orientation(TopAbs_FORWARD);
242
243   BRep_Builder B;
244   TopoDS_Iterator anIt (F, Standard_False);
245   while (anIt.More())
246   {
247     TopoDS_Shape aWire = anIt.Value();
248     anIt.Next();
249
250     // skip possible internal vertices in face
251     if (aWire.ShapeType() != TopAbs_WIRE)
252       continue;
253
254     // if current wire is the last one, return it without analysis
255     if (! anIt.More())
256       return TopoDS::Wire (aWire);
257
258     TopoDS_Shape aTestFace = F.EmptyCopied();
259     B.Add (aTestFace, aWire);
260     if (ShapeAnalysis::IsOuterBound (TopoDS::Face (aTestFace)))
261       return TopoDS::Wire (aWire);
262   }
263   return TopoDS_Wire();
264 }
265
266 //=======================================================================
267 //function : GetFaceUVBounds
268 //purpose  : 
269 //=======================================================================
270
271 void ShapeAnalysis::GetFaceUVBounds (const TopoDS_Face& F, 
272                                      Standard_Real& UMin, Standard_Real& UMax, 
273                                      Standard_Real& VMin, Standard_Real& VMax) 
274 {
275   TopoDS_Face FF = F;
276   FF.Orientation(TopAbs_FORWARD);
277   TopExp_Explorer ex(FF,TopAbs_EDGE);
278   if (!ex.More()) {
279     TopLoc_Location L;
280     BRep_Tool::Surface(F,L)->Bounds(UMin,UMax,VMin,VMax);
281     return;
282   }
283   
284   Bnd_Box2d B;
285   ShapeAnalysis_Edge sae;
286   ShapeAnalysis_Curve sac;
287   for (;ex.More();ex.Next()) {
288     TopoDS_Edge edge = TopoDS::Edge(ex.Current());
289     Handle(Geom2d_Curve) c2d;
290     Standard_Real f, l;
291     if ( ! sae.PCurve ( edge, F, c2d, f, l, Standard_False ) ) continue;
292     sac.FillBndBox ( c2d, f, l, 20, Standard_True, B );
293   }
294   B.Get(UMin,VMin,UMax,VMax);
295 }