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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // 25.12.98 pdn renaming of ShapeAnalysis_FreeBounds and ShapeAnalysis_Wire methods
20 #include <BRep_Builder.hxx>
21 #include <BRepTools_WireExplorer.hxx>
22 #include <Geom_Curve.hxx>
23 #include <GeomAPI_ProjectPointOnCurve.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>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Shape.hxx>
38 #include <TopoDS_Wire.hxx>
39 #include <TopTools_HSequenceOfShape.hxx>
43 static void ContourProperties(TopoDS_Wire wire,
44 Standard_Real& countourArea,
45 Standard_Real& countourLength)
47 Standard_Integer nbe = 0;
48 Standard_Real length = 0.0;
49 gp_XYZ area(.0,.0,.0);
52 for (BRepTools_WireExplorer exp(wire); exp.More(); exp.Next()) {
53 TopoDS_Edge Edge = exp.Current(); nbe++;
55 Standard_Real First, Last;
56 Handle(Geom_Curve) c3d;
57 ShapeAnalysis_Edge sae;
58 if (!sae.Curve3d(Edge,c3d,First,Last)) continue;
60 Standard_Integer ibeg = 0;
62 gp_Pnt pntIni = c3d->Value(First);
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();
80 countourArea = area.Modulus()/2;
81 countourLength = length;
84 //=======================================================================
85 //function : ShapeAnalysis_FreeBoundsProperties
86 //purpose : Empty constructor
87 //=======================================================================
89 ShapeAnalysis_FreeBoundsProperties::ShapeAnalysis_FreeBoundsProperties()
91 myClosedFreeBounds = new ShapeAnalysis_HSequenceOfFreeBounds();
92 myOpenFreeBounds = new ShapeAnalysis_HSequenceOfFreeBounds();
96 //=======================================================================
97 //function : ShapeAnalysis_FreeBoundsProperties
98 //purpose : Creates the object and calls corresponding Init.
99 // <shape> should be a compound of faces.
100 //=======================================================================
102 ShapeAnalysis_FreeBoundsProperties::ShapeAnalysis_FreeBoundsProperties(const TopoDS_Shape& shape,
103 const Standard_Real tolerance,
104 const Standard_Boolean splitclosed,
105 const Standard_Boolean splitopen)
107 myClosedFreeBounds = new ShapeAnalysis_HSequenceOfFreeBounds();
108 myOpenFreeBounds = new ShapeAnalysis_HSequenceOfFreeBounds();
109 Init(shape, tolerance, splitclosed, splitopen);
112 //=======================================================================
113 //function : ShapeAnalysis_FreeBoundsProperties
114 //purpose : Creates the object and calls corresponding Init.
115 // <shape> should be a compound of shells.
116 //=======================================================================
118 ShapeAnalysis_FreeBoundsProperties::ShapeAnalysis_FreeBoundsProperties(const TopoDS_Shape& shape,
119 const Standard_Boolean splitclosed,
120 const Standard_Boolean splitopen)
122 myClosedFreeBounds = new ShapeAnalysis_HSequenceOfFreeBounds();
123 myOpenFreeBounds = new ShapeAnalysis_HSequenceOfFreeBounds();
125 Init(shape, splitclosed, splitopen);
128 //=======================================================================
130 //purpose : Initializes the object with given parameters.
131 // <shape> should be a compound of faces.
132 //=======================================================================
134 void ShapeAnalysis_FreeBoundsProperties::Init(const TopoDS_Shape& shape,
135 const Standard_Real tolerance,
136 const Standard_Boolean splitclosed,
137 const Standard_Boolean splitopen)
139 Init(shape, splitclosed, splitopen);
140 myTolerance = tolerance;
144 //=======================================================================
146 //purpose : Initializes the object with given parameters.
147 // <shape> should be a compound of shells.
148 //=======================================================================
150 void ShapeAnalysis_FreeBoundsProperties::Init(const TopoDS_Shape& shape,
151 const Standard_Boolean splitclosed,
152 const Standard_Boolean splitopen)
155 mySplitClosed = splitclosed;
156 mySplitOpen = splitopen;
160 //=======================================================================
162 //purpose : Builds and analyzes free bounds of the shape.
163 // First calls ShapeAnalysis_FreeBounds for building free
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 //=======================================================================
176 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::Perform()
178 Standard_Boolean result = Standard_False;
179 result |= DispatchBounds();
180 result |= CheckNotches();
181 result |= CheckContours();
186 //=======================================================================
187 //function : DispatchBounds
189 //=======================================================================
191 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::DispatchBounds()
193 if (!IsLoaded()) return Standard_False;
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();
202 ShapeAnalysis_FreeBounds safb(myShape, mySplitClosed, mySplitOpen);
203 tmpClosedBounds = safb.GetClosedWires();
204 tmpOpenBounds = safb.GetOpenWires();
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);
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);
225 return Standard_True;
229 //=======================================================================
230 //function : CheckNotches
232 //=======================================================================
234 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::CheckNotches(const Standard_Real prec)
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);
241 for( i = 1; i <= myOpenFreeBounds->Length(); i++) {
242 Handle(ShapeAnalysis_FreeBoundData) fbData = myOpenFreeBounds->Value(i);
243 CheckNotches(fbData, prec);
246 return Standard_True;
249 //=======================================================================
250 //function : CheckNotches
252 //=======================================================================
254 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::CheckNotches(Handle(ShapeAnalysis_FreeBoundData)& fbData,
255 const Standard_Real prec)
257 ShapeExtend_WireData swd(fbData->FreeBound());
258 if (swd.NbEdges() > 1)
259 for (Standard_Integer j=1; j <= swd.NbEdges(); j++) {
262 if (CheckNotches(fbData->FreeBound(), j, notch, dMax, prec))
263 fbData->AddNotch(notch, dMax);
266 return Standard_True;
269 //=======================================================================
270 //function : CheckContours
272 //=======================================================================
274 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::CheckContours(const Standard_Real prec)
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);
282 for ( i = 1; i <= myOpenFreeBounds->Length(); i++) {
283 Handle(ShapeAnalysis_FreeBoundData) fbData = myOpenFreeBounds->Value(i);
284 status |= FillProperties(fbData,prec);
291 //=======================================================================
292 //function : CheckNotches
294 //=======================================================================
296 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::CheckNotches(const TopoDS_Wire& wire,
297 const Standard_Integer num,
299 Standard_Real& distMax,
300 const Standard_Real /*prec*/)
302 Standard_Real tol = Max ( myTolerance, Precision::Confusion());
303 Handle(ShapeExtend_WireData) wdt = new ShapeExtend_WireData(wire);
307 if ( (num <= 0)||(num > wdt->NbEdges()) ) return Standard_False;
309 Standard_Integer n1 = ( num > 0 ? num : wdt->NbEdges() );
310 Standard_Integer n2 = ( n1 < wdt->NbEdges() ? n1+1 : 1 );
312 TopoDS_Edge E1 = wdt->Edge(n1);
315 Handle(ShapeAnalysis_Wire) saw = new ShapeAnalysis_Wire;
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);
323 TopoDS_Edge E2 = wdt->Edge(n2);
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;
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();
340 Standard_Real angl = Abs( vec1.Angle(vec2));
341 if (angl > 0.95*M_PI) {
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);
347 Standard_Real p1, p2;
348 if ( First2 < Last2 ) {
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;
363 return Standard_True;
366 return Standard_False;
370 //=======================================================================
371 //function : FillProperties
373 //=======================================================================
375 Standard_Boolean ShapeAnalysis_FreeBoundsProperties::FillProperties(Handle(ShapeAnalysis_FreeBoundData)& fbData,
376 const Standard_Real /*prec*/)
378 Standard_Real area, length;
379 ContourProperties(fbData->FreeBound(), area, length);
382 Standard_Real aver = 0;
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;
390 r = (1. + sqrt(aux))/(8.*k);
391 aver = length/(2.*r);
397 fbData->SetArea(area);
398 fbData->SetPerimeter(length);
400 fbData->SetWidth(aver);
402 return Standard_True;