b311480e |
1 | // Created on: 2000-01-20 |
2 | // Created by: data exchange team |
973c2be1 |
3 | // Copyright (c) 2000-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
b311480e |
15 | |
7fd59977 |
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 | |
42cf5bc1 |
23 | #include <Bnd_Box2d.hxx> |
24 | #include <BRep_Builder.hxx> |
7fd59977 |
25 | #include <BRep_Tool.hxx> |
26 | #include <BRepAdaptor_Surface.hxx> |
7fd59977 |
27 | #include <BRepGProp.hxx> |
42cf5bc1 |
28 | #include <BRepTools.hxx> |
29 | #include <BRepTopAdaptor_FClass2d.hxx> |
30 | #include <Geom2d_Curve.hxx> |
31 | #include <Geom_Plane.hxx> |
32 | #include <Geom_Surface.hxx> |
7fd59977 |
33 | #include <gp_Pnt2d.hxx> |
34 | #include <gp_XY.hxx> |
7fd59977 |
35 | #include <GProp_GProps.hxx> |
7fd59977 |
36 | #include <Precision.hxx> |
42cf5bc1 |
37 | #include <ShapeAnalysis.hxx> |
7fd59977 |
38 | #include <ShapeAnalysis_Curve.hxx> |
42cf5bc1 |
39 | #include <ShapeAnalysis_Edge.hxx> |
40 | #include <ShapeExtend_WireData.hxx> |
41 | #include <Standard_ErrorHandler.hxx> |
42 | #include <Standard_Failure.hxx> |
7fd59977 |
43 | #include <TColgp_SequenceOfPnt.hxx> |
42cf5bc1 |
44 | #include <TColgp_SequenceOfPnt2d.hxx> |
7fd59977 |
45 | #include <TopExp.hxx> |
42cf5bc1 |
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> |
7fd59977 |
54 | |
42cf5bc1 |
55 | // PLANTAGE IsOuterBound, 15-SEP-1998 |
7fd59977 |
56 | //static Standard_Integer numpb = 0; |
7fd59977 |
57 | //======================================================================= |
58 | //function : AdjustByPeriod |
59 | //purpose : |
60 | //======================================================================= |
7fd59977 |
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; |
9248974c |
70 | return ( diff >0 ? -P : P ) * floor( D / P + 0.5 ); |
7fd59977 |
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> |
46aed280 |
123 | static inline void ReverseSeq (HSequence& Seq) |
7fd59977 |
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 ) |
46aed280 |
152 | ReverseSeq(SeqPnt); |
7fd59977 |
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 | { |
6e6cd5d9 |
178 | Standard_Integer nbc = 0; |
7fd59977 |
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 ) |
46aed280 |
195 | ReverseSeq(aSeqPnt); |
7fd59977 |
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 | } |
7fd59977 |
240 | } |
241 | |
242 | //======================================================================= |
243 | //function : OuterBound |
244 | //purpose : replacement of bad BRepTools::OuterBound() |
245 | //======================================================================= |
246 | //:n3 |
247 | |
248 | TopoDS_Wire ShapeAnalysis::OuterWire(const TopoDS_Face& face) |
249 | { |
250 | TopoDS_Face F = face; |
251 | F.Orientation(TopAbs_FORWARD); |
252 | |
253 | BRep_Builder B; |
254 | TopoDS_Wire W; |
255 | TopoDS_Iterator exp (F, Standard_False); |
256 | while ( exp.More() ) { |
257 | if(exp.Value().ShapeType() != TopAbs_WIRE) |
258 | continue; |
259 | W = TopoDS::Wire ( exp.Value() ); |
260 | exp.Next(); |
261 | if ( ! exp.More() ) return W; |
262 | //szv#4:S4163:12Mar99 SGI warns |
263 | TopoDS_Shape sh = F.EmptyCopied(); |
264 | TopoDS_Face fc = TopoDS::Face( sh ); |
265 | B.Add ( fc, W ); |
266 | if ( ShapeAnalysis::IsOuterBound ( fc ) ) return W; |
267 | } |
268 | return W; |
269 | } |
270 | |
271 | //======================================================================= |
272 | //function : GetFaceUVBounds |
273 | //purpose : |
274 | //======================================================================= |
275 | |
276 | void ShapeAnalysis::GetFaceUVBounds (const TopoDS_Face& F, |
277 | Standard_Real& UMin, Standard_Real& UMax, |
278 | Standard_Real& VMin, Standard_Real& VMax) |
279 | { |
280 | TopoDS_Face FF = F; |
281 | FF.Orientation(TopAbs_FORWARD); |
282 | TopExp_Explorer ex(FF,TopAbs_EDGE); |
283 | if (!ex.More()) { |
284 | TopLoc_Location L; |
285 | BRep_Tool::Surface(F,L)->Bounds(UMin,UMax,VMin,VMax); |
286 | return; |
287 | } |
288 | |
289 | Bnd_Box2d B; |
290 | ShapeAnalysis_Edge sae; |
291 | ShapeAnalysis_Curve sac; |
292 | for (;ex.More();ex.Next()) { |
293 | TopoDS_Edge edge = TopoDS::Edge(ex.Current()); |
294 | Handle(Geom2d_Curve) c2d; |
295 | Standard_Real f, l; |
296 | if ( ! sae.PCurve ( edge, F, c2d, f, l, Standard_False ) ) continue; |
297 | sac.FillBndBox ( c2d, f, l, 20, Standard_True, B ); |
298 | } |
299 | B.Get(UMin,VMin,UMax,VMax); |
300 | } |