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