0027961: Visualization - remove unused and no more working OpenGl_AVIWriter
[occt.git] / src / ShapeAnalysis / ShapeAnalysis_FreeBoundsProperties.cxx
1 // Created on: 1998-08-04
2 // Created by: Pavel DURANDIN
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // 25.12.98 pdn renaming of ShapeAnalysis_FreeBounds and ShapeAnalysis_Wire methods
18 //szv#4 S4163
19
20 #include <BRep_Builder.hxx>
21 #include <BRepTools_WireExplorer.hxx>
22 #include <Geom_Curve.hxx>
23 #include <GeomAPI_ProjectPointOnCurve.hxx>
24 #include <gp_Pnt.hxx>
25 #include <gp_Vec.hxx>
26 #include <gp_XYZ.hxx>
27 #include <Precision.hxx>
28 #include <ShapeAnalysis_Edge.hxx>
29 #include <ShapeAnalysis_FreeBoundData.hxx>
30 #include <ShapeAnalysis_FreeBounds.hxx>
31 #include <ShapeAnalysis_FreeBoundsProperties.hxx>
32 #include <ShapeAnalysis_Wire.hxx>
33 #include <ShapeExtend_Explorer.hxx>
34 #include <ShapeExtend_WireData.hxx>
35 #include <TopoDS.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Shape.hxx>
38 #include <TopoDS_Wire.hxx>
39 #include <TopTools_HSequenceOfShape.hxx>
40
41 #define NbControl 23
42
43 static void ContourProperties(TopoDS_Wire wire,
44                               Standard_Real& countourArea,
45                               Standard_Real& countourLength)
46 {
47   Standard_Integer nbe = 0;
48   Standard_Real length = 0.0;
49   gp_XYZ area(.0,.0,.0);
50   gp_XYZ prev, cont;
51   
52   for (BRepTools_WireExplorer exp(wire); exp.More(); exp.Next()) {
53     TopoDS_Edge Edge = exp.Current();  nbe++;
54       
55     Standard_Real First, Last;
56     Handle(Geom_Curve) c3d;
57     ShapeAnalysis_Edge sae;
58     if (!sae.Curve3d(Edge,c3d,First,Last)) continue;
59       
60     Standard_Integer ibeg = 0;
61     if ( nbe == 1 ) {
62       gp_Pnt pntIni = c3d->Value(First);
63       prev = pntIni.XYZ();
64       cont = prev;
65       ibeg = 1;
66     }
67
68     for ( Standard_Integer i = ibeg; i < NbControl; i++) {
69       Standard_Real prm = ((NbControl-1-i)*First + i*Last)/(NbControl-1);
70       gp_Pnt pntCurr = c3d->Value(prm);
71       gp_XYZ curr = pntCurr.XYZ();
72       gp_XYZ delta = curr - prev;
73       length += delta.Modulus();
74       area += curr ^ prev;
75       prev = curr;
76     }
77   }
78
79   area +=  cont ^ prev;
80   countourArea = area.Modulus()/2;
81   countourLength = length;
82 }
83
84 //=======================================================================
85 //function : ShapeAnalysis_FreeBoundsProperties
86 //purpose  : Empty constructor
87 //=======================================================================
88
89 ShapeAnalysis_FreeBoundsProperties::ShapeAnalysis_FreeBoundsProperties()
90 {
91   myClosedFreeBounds = new ShapeAnalysis_HSequenceOfFreeBounds();
92   myOpenFreeBounds   = new ShapeAnalysis_HSequenceOfFreeBounds();
93   myTolerance = 0.;
94 }
95
96 //=======================================================================
97 //function : ShapeAnalysis_FreeBoundsProperties
98 //purpose  : Creates the object and calls corresponding Init.
99 //           <shape> should be a compound of faces.
100 //=======================================================================
101
102 ShapeAnalysis_FreeBoundsProperties::ShapeAnalysis_FreeBoundsProperties(const TopoDS_Shape& shape,
103                                                                        const Standard_Real tolerance,
104                                                                        const Standard_Boolean splitclosed,
105                                                                        const Standard_Boolean splitopen)
106 {
107   myClosedFreeBounds = new ShapeAnalysis_HSequenceOfFreeBounds();
108   myOpenFreeBounds   = new ShapeAnalysis_HSequenceOfFreeBounds();
109   Init(shape, tolerance, splitclosed, splitopen);
110 }
111
112 //=======================================================================
113 //function : ShapeAnalysis_FreeBoundsProperties
114 //purpose  : Creates the object and calls corresponding Init.
115 //           <shape> should be a compound of shells.
116 //=======================================================================
117
118 ShapeAnalysis_FreeBoundsProperties::ShapeAnalysis_FreeBoundsProperties(const TopoDS_Shape& shape,
119                                                                        const Standard_Boolean splitclosed,
120                                                                        const Standard_Boolean splitopen)
121 {
122   myClosedFreeBounds = new ShapeAnalysis_HSequenceOfFreeBounds();
123   myOpenFreeBounds   = new ShapeAnalysis_HSequenceOfFreeBounds();
124   myTolerance =0.;
125   Init(shape, splitclosed, splitopen);
126 }
127
128 //=======================================================================
129 //function : Init
130 //purpose  : Initializes the object with given parameters.
131 //           <shape> should be a compound of faces.
132 //=======================================================================
133
134 void ShapeAnalysis_FreeBoundsProperties::Init(const TopoDS_Shape& shape,
135                                               const Standard_Real tolerance,
136                                               const Standard_Boolean splitclosed,
137                                               const Standard_Boolean splitopen) 
138 {
139   Init(shape, splitclosed, splitopen);
140   myTolerance = tolerance;
141 }
142
143
144 //=======================================================================
145 //function : Init
146 //purpose  : Initializes the object with given parameters.
147 //           <shape> should be a compound of shells.
148 //=======================================================================
149
150 void ShapeAnalysis_FreeBoundsProperties::Init(const TopoDS_Shape& shape,
151                                               const Standard_Boolean splitclosed,
152                                               const Standard_Boolean splitopen) 
153 {
154   myShape = shape;
155   mySplitClosed = splitclosed;
156   mySplitOpen = splitopen;
157 }
158
159
160 //=======================================================================
161 //function : Perform
162 //purpose  : Builds and analyzes free bounds of the shape.
163 //           First calls ShapeAnalysis_FreeBounds for building free 
164 //           bounds.
165 //           Then on each free bound computes its properties:
166 //           - area of the contour,
167 //           - perimeter of the contour,
168 //           - ratio of average length to average width of the contour,
169 //           - average width of contour,
170 //           - notches on the contour and for each notch
171 //            - maximum width of the notch.
172 //returns:   True  - if no fails and free bounds are found,
173 //           False - if fail or no free bounds are found
174 //=======================================================================
175
176 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::Perform() 
177 {
178   Standard_Boolean result = Standard_False;
179   result |= DispatchBounds();
180   result |= CheckNotches();
181   result |= CheckContours();
182   return result;
183 }    
184
185
186 //=======================================================================
187 //function : DispatchBounds
188 //purpose  : 
189 //=======================================================================
190
191 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::DispatchBounds() 
192 {
193   if (!IsLoaded()) return Standard_False;
194
195   TopoDS_Compound tmpClosedBounds, tmpOpenBounds;
196   if ( myTolerance > 0.) {
197     ShapeAnalysis_FreeBounds safb(myShape, myTolerance, mySplitClosed, mySplitOpen);
198     tmpClosedBounds = safb.GetClosedWires();
199     tmpOpenBounds   = safb.GetOpenWires();
200   }
201   else {
202     ShapeAnalysis_FreeBounds safb(myShape, mySplitClosed, mySplitOpen);
203     tmpClosedBounds = safb.GetClosedWires();
204     tmpOpenBounds   = safb.GetOpenWires();
205   }
206   
207   ShapeExtend_Explorer shexpl;
208   Handle(TopTools_HSequenceOfShape) tmpSeq = shexpl.SeqFromCompound(tmpClosedBounds,Standard_False);
209   Standard_Integer i; // svv Jan11 2000 : porting on DEC
210   for (i = 1; i<=tmpSeq->Length(); i++) { 
211     TopoDS_Wire wire = TopoDS::Wire(tmpSeq->Value(i));
212     Handle(ShapeAnalysis_FreeBoundData) fbData= new ShapeAnalysis_FreeBoundData() ;
213     fbData->SetFreeBound(wire);
214     myClosedFreeBounds -> Append(fbData);
215   }                       
216   
217   Handle(TopTools_HSequenceOfShape) tmpSeq2 = shexpl.SeqFromCompound(tmpOpenBounds,Standard_False);
218   for(i = 1; i<=tmpSeq2->Length(); i++) {
219     TopoDS_Wire wire = TopoDS::Wire(tmpSeq2->Value(i));
220     Handle(ShapeAnalysis_FreeBoundData) fbData = new ShapeAnalysis_FreeBoundData;
221     fbData->SetFreeBound(wire);
222     myOpenFreeBounds -> Append(fbData); 
223   }
224
225   return Standard_True;
226 }
227
228
229 //=======================================================================
230 //function : CheckNotches
231 //purpose  : 
232 //=======================================================================
233
234 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::CheckNotches(const Standard_Real prec) 
235 {
236   Standard_Integer i; // svv Jan11 2000 : porting on DEC
237   for(i = 1; i <= myClosedFreeBounds->Length(); i++) {
238     Handle(ShapeAnalysis_FreeBoundData) fbData = myClosedFreeBounds->Value(i);
239     CheckNotches(fbData, prec);
240   }
241   for( i = 1; i <= myOpenFreeBounds->Length(); i++) {
242     Handle(ShapeAnalysis_FreeBoundData) fbData = myOpenFreeBounds->Value(i);
243     CheckNotches(fbData, prec);
244   }
245
246   return Standard_True;
247 }
248
249 //=======================================================================
250 //function : CheckNotches
251 //purpose  : 
252 //=======================================================================
253
254 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::CheckNotches(Handle(ShapeAnalysis_FreeBoundData)& fbData,
255                                                                   const Standard_Real prec)
256 {
257   ShapeExtend_WireData swd(fbData->FreeBound());
258   if (swd.NbEdges() > 1)
259     for (Standard_Integer j=1; j <= swd.NbEdges(); j++) {
260       TopoDS_Wire notch;
261       Standard_Real dMax;
262       if (CheckNotches(fbData->FreeBound(), j, notch, dMax, prec))
263         fbData->AddNotch(notch, dMax);
264     }
265
266   return Standard_True;
267 }  
268
269 //=======================================================================
270 //function : CheckContours
271 //purpose  : 
272 //=======================================================================
273
274 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::CheckContours(const Standard_Real prec) 
275 {
276   Standard_Boolean status = Standard_False;
277   Standard_Integer i; // svv Jan11 2000 : porting on DEC
278   for( i = 1; i <= myClosedFreeBounds->Length(); i++) {
279     Handle(ShapeAnalysis_FreeBoundData) fbData = myClosedFreeBounds->Value(i);
280     status |= FillProperties(fbData,prec);
281   }
282   for ( i = 1; i <= myOpenFreeBounds->Length(); i++) {
283     Handle(ShapeAnalysis_FreeBoundData) fbData = myOpenFreeBounds->Value(i);
284     status |= FillProperties(fbData,prec);
285   }
286
287   return status;
288 }
289
290
291 //=======================================================================
292 //function : CheckNotches
293 //purpose  : 
294 //=======================================================================
295
296 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::CheckNotches(const TopoDS_Wire& wire,
297                                                                   const Standard_Integer num,
298                                                                   TopoDS_Wire& notch,
299                                                                   Standard_Real& distMax, 
300                                                                   const Standard_Real /*prec*/) 
301 {
302   Standard_Real tol = Max ( myTolerance, Precision::Confusion());
303   Handle(ShapeExtend_WireData) wdt = new ShapeExtend_WireData(wire);
304   BRep_Builder B;
305   B.MakeWire(notch);
306   
307   if ( (num <= 0)||(num > wdt->NbEdges()) ) return Standard_False;
308   
309   Standard_Integer n1 = ( num > 0 ? num : wdt->NbEdges() );
310   Standard_Integer n2 = ( n1  < wdt->NbEdges() ? n1+1 : 1 );
311   
312   TopoDS_Edge E1 = wdt->Edge(n1);
313   B.Add(notch,E1);
314
315   Handle(ShapeAnalysis_Wire) saw = new ShapeAnalysis_Wire;
316   saw->Load(wdt);
317   saw->SetPrecision(myTolerance);
318   if ( saw->CheckSmall( n2, tol ) ) {
319     B.Add(notch,wdt->Edge(n2));
320     n2 = ( n2 < wdt->NbEdges() ? n2+1 : 1); 
321   }
322
323   TopoDS_Edge E2 = wdt->Edge(n2);
324   B.Add(notch,E2);
325   
326   Standard_Real First1, Last1, First2, Last2;
327   Handle(Geom_Curve) c3d1, c3d2;
328   ShapeAnalysis_Edge sae;
329   //szv#4:S4163:12Mar99 optimized
330   if ( !sae.Curve3d(E1, c3d1, First1, Last1) ||
331        !sae.Curve3d(E2, c3d2, First2, Last2) ) return Standard_False;
332   
333   gp_Pnt pnt;
334   gp_Vec vec1, vec2;
335   c3d1->D1(Last1, pnt, vec1);
336   c3d2->D1(First2,pnt, vec2);
337   if ( E1.Orientation() == TopAbs_REVERSED ) vec1.Reverse();
338   if ( E2.Orientation() == TopAbs_REVERSED ) vec2.Reverse();
339   
340   Standard_Real angl = Abs( vec1.Angle(vec2));
341   if (angl > 0.95*M_PI) {
342     distMax = .0;
343     for (Standard_Integer i = 0; i < NbControl; i++) {
344       Standard_Real prm = ((NbControl-1-i)*First1 + i*Last1)/(NbControl-1);
345       gp_Pnt pntCurr = c3d1->Value(prm);
346
347       Standard_Real p1, p2;
348       if ( First2 < Last2 ) {
349         p1 = First2;
350         p2 = Last2;
351       }
352       else {
353         p1 = Last2;
354         p2 = First2;
355       }
356
357       //szv#4:S4163:12Mar99 warning
358       GeomAPI_ProjectPointOnCurve ppc(pntCurr, c3d2, p1, p2);
359       Standard_Real newDist = (ppc.NbPoints() ? ppc.LowerDistance() : 0);
360       if ( newDist > distMax ) distMax = newDist;
361     }
362
363     return Standard_True;  
364   }
365
366   return Standard_False;
367 }
368
369
370 //=======================================================================
371 //function : FillProperties
372 //purpose  : 
373 //=======================================================================
374
375 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::FillProperties(Handle(ShapeAnalysis_FreeBoundData)& fbData,
376                                                                     const Standard_Real /*prec*/) 
377 {  
378   Standard_Real area, length;
379   ContourProperties(fbData->FreeBound(), area, length);
380
381   Standard_Real r = 0;
382   Standard_Real aver = 0;
383
384   if ( length != 0. ) { //szv#4:S4163:12Mar99 anti-exception
385     Standard_Real k =  area /(length*length); //szv#4:S4163:12Mar99
386     //szv#4:S4163:12Mar99 optimized
387     if ( k != 0. ) { //szv#4:S4163:12Mar99 anti-exception
388       Standard_Real aux =  1. - 16.*k;
389       if ( aux >= 0.) {
390         r = (1. + sqrt(aux))/(8.*k);
391         aver = length/(2.*r);
392         r -= 1.;
393       }
394     }
395   }
396   
397   fbData->SetArea(area);
398   fbData->SetPerimeter(length);
399   fbData->SetRatio(r);
400   fbData->SetWidth(aver);
401
402   return Standard_True;
403 }