1 // Created on: 1995-01-06
2 // Created by: Frederic MAUPAS
3 // Copyright (c) 1995-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 //pdn 11.01.99 #144 bm1_pe_t4 protection of exceptions in draw
18 // abv 13.04.99 S4136: eliminate BRepAPI::Precision()
19
20 #include <BRep_Builder.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepTools.hxx>
23 #include <BRepTools_WireExplorer.hxx>
24 #include <ElCLib.hxx>
25 #include <ElSLib.hxx>
26 #include <Geom2d_Curve.hxx>
27 #include <Geom2d_Line.hxx>
28 #include <Geom2d_TrimmedCurve.hxx>
29 #include <Geom2dAPI_InterCurveCurve.hxx>
30 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
31 #include <Geom_BoundedCurve.hxx>
32 #include <Geom_BSplineCurve.hxx>
33 #include <Geom_BSplineSurface.hxx>
34 #include <Geom_ConicalSurface.hxx>
35 #include <Geom_Curve.hxx>
36 #include <Geom_CylindricalSurface.hxx>
37 #include <Geom_Line.hxx>
38 #include <Geom_Plane.hxx>
39 #include <Geom_SphericalSurface.hxx>
40 #include <Geom_ToroidalSurface.hxx>
41 #include <GeomAbs_CurveType.hxx>
42 #include <GeomAbs_Shape.hxx>
43 #include <GeomAdaptor_Curve.hxx>
44 #include <GeomAPI_ProjectPointOnCurve.hxx>
45 #include <GeomAPI_ProjectPointOnSurf.hxx>
46 #include <gp_Vec2d.hxx>
47 #include <Precision.hxx>
48 #include <Standard_ErrorHandler.hxx>
49 #include <Standard_Failure.hxx>
50 #include <StepGeom_CartesianPoint.hxx>
51 #include <StepGeom_Direction.hxx>
52 #include <StepGeom_Line.hxx>
53 #include <StepGeom_Pcurve.hxx>
54 #include <StepGeom_PcurveOrSurface.hxx>
55 #include <StepGeom_SeamCurve.hxx>
56 #include <StepGeom_Surface.hxx>
57 #include <StepGeom_SurfaceCurve.hxx>
58 #include <StepGeom_Vector.hxx>
59 #include <StepRepr_DefinitionalRepresentation.hxx>
60 #include <StepShape_Edge.hxx>
61 #include <StepShape_EdgeLoop.hxx>
62 #include <StepShape_OrientedEdge.hxx>
63 #include <StepToTopoDS.hxx>
64 #include <StepToTopoDS_GeometricTool.hxx>
65 #include <TopExp.hxx>
66 #include <TopExp_Explorer.hxx>
67 #include <TopoDS.hxx>
68 #include <Transfer_TransientProcess.hxx>
69
70 // ----------------------------------------------------------------------------
71 // Method : HasPCurve
72 // Purpose : returns true if the surface curve has at least one pcurve lying
73 //on the surface
74 // ----------------------------------------------------------------------------
PCurve(const Handle (StepGeom_SurfaceCurve)& SurfCurve,const Handle (StepGeom_Surface)& BasisSurf,Handle (StepGeom_Pcurve)& thePCurve,const Standard_Integer last)75 Standard_Integer StepToTopoDS_GeometricTool::PCurve
76 (const Handle(StepGeom_SurfaceCurve)& SurfCurve,
77 const Handle(StepGeom_Surface)& BasisSurf,
78 Handle(StepGeom_Pcurve)& thePCurve, const Standard_Integer last)
79 {
80 Standard_Integer NbAssGeom = SurfCurve->NbAssociatedGeometry();
81 thePCurve.Nullify();
82 for (Standard_Integer i= last+1; i<=NbAssGeom; i++) {
83 thePCurve = SurfCurve->AssociatedGeometryValue(i).Pcurve();
84 if (!thePCurve.IsNull()) {
85 if (thePCurve->BasisSurface() == BasisSurf) return i;
86 }
87 }
88 thePCurve.Nullify();
89 return 0;
90 }
91
92 // ----------------------------------------------------------------------------
93 // Method : IsSeamCurve
94 // Purpose : Two edges of the same wire references the same oriented edge
95 // Then the surface_curve is a seam curve
96 // ----------------------------------------------------------------------------
97
IsSeamCurve(const Handle (StepGeom_SurfaceCurve)& SurfCurve,const Handle (StepGeom_Surface)& Surf,const Handle (StepShape_Edge)& StepEdge,const Handle (StepShape_EdgeLoop)& EdgeLoop)98 Standard_Boolean StepToTopoDS_GeometricTool::IsSeamCurve
99 (const Handle(StepGeom_SurfaceCurve)& SurfCurve,
100 const Handle(StepGeom_Surface)& Surf,
101 const Handle(StepShape_Edge)& StepEdge,
102 const Handle(StepShape_EdgeLoop)& EdgeLoop)
103 {
104 if (SurfCurve->IsKind(STANDARD_TYPE(StepGeom_SeamCurve)))
105 return Standard_True;
106
107 if (SurfCurve->NbAssociatedGeometry() != 2) return Standard_False;
108
109 Handle(StepGeom_Pcurve) StepPCurve1 =
110 SurfCurve->AssociatedGeometryValue(1).Pcurve();
111 Handle(StepGeom_Pcurve) StepPCurve2 =
112 SurfCurve->AssociatedGeometryValue(2).Pcurve();
113
114 // Do the two pcurves lye on the same surface ?
115
116 if ((!StepPCurve1.IsNull() && !StepPCurve2.IsNull()) &&
117 (StepPCurve1->BasisSurface() == Surf) &&
118 (StepPCurve2->BasisSurface()== Surf)) {
119
120 Standard_Integer NbEdge = EdgeLoop->NbEdgeList();
121 Standard_Integer nbOE = 0;
122
123 Handle(StepShape_OrientedEdge) OrEdge;
124
125 for (Standard_Integer i = 1; i <= NbEdge; i ++ ) {
126 OrEdge = EdgeLoop->EdgeListValue(i);
127 if (StepEdge == OrEdge->EdgeElement()) nbOE ++;
128 }
129 // two oriented edges of the same wire share the same edge
130 if (nbOE == 2) return Standard_True;
131 }
132 return Standard_False;
133 }
134
135 // ----------------------------------------------------------------------------
136 // Method : IsLikeSeam
137 // Purpose : The two pcurves lies on the same surface but on different wires.
138 // This is typical situation in CATIA BRep : a cylinder is coded
139 // with two faces on the same 'Closed' BSplineSurf, which in the
140 // range of gp_Resolution is not identified as closed
141 // ----------------------------------------------------------------------------
142
IsLikeSeam(const Handle (StepGeom_SurfaceCurve)& SurfCurve,const Handle (StepGeom_Surface)& Surf,const Handle (StepShape_Edge)& StepEdge,const Handle (StepShape_EdgeLoop)& EdgeLoop)143 Standard_Boolean StepToTopoDS_GeometricTool::IsLikeSeam
144 (const Handle(StepGeom_SurfaceCurve)& SurfCurve,
145 const Handle(StepGeom_Surface)& Surf,
146 const Handle(StepShape_Edge)& StepEdge,
147 const Handle(StepShape_EdgeLoop)& EdgeLoop)
148 {
149 if (SurfCurve->NbAssociatedGeometry() != 2) return Standard_False;
150
151 Handle(StepGeom_Pcurve) StepPCurve1 =
152 SurfCurve->AssociatedGeometryValue(1).Pcurve();
153 Handle(StepGeom_Pcurve) StepPCurve2 =
154 SurfCurve->AssociatedGeometryValue(2).Pcurve();
155
156 // Do the two pcurves lye on the same surface ?
157
158 if ((!StepPCurve1.IsNull() && !StepPCurve2.IsNull()) &&
159 (StepPCurve1->BasisSurface() == Surf) &&
160 (StepPCurve2->BasisSurface() == Surf)) {
161
162 Standard_Integer NbEdge = EdgeLoop->NbEdgeList();
163 Standard_Integer nbOE = 0;
164
165 Handle(StepShape_OrientedEdge) OrEdge;
166
167 for (Standard_Integer i = 1; i <= NbEdge; i ++ ) {
168 OrEdge = EdgeLoop->EdgeListValue(i);
169 if (StepEdge == OrEdge->EdgeElement()) nbOE ++;
170 }
171 // the two oriented edges are not in the same wire
172 if (nbOE == 1) {
173 // check if the two pcurves are not identical ?
174 Handle(StepGeom_Line) line1 = Handle(StepGeom_Line)::DownCast
175 (StepPCurve1->ReferenceToCurve()->ItemsValue(1));
176 Handle(StepGeom_Line) line2 = Handle(StepGeom_Line)::DownCast
177 (StepPCurve2->ReferenceToCurve()->ItemsValue(1));
178 if (!line1.IsNull() && !line2.IsNull()) {
179 // Same Origin in X OR Y && Same Vector ??
180 // WITHIN A given tolerance !!!
181 Standard_Real DeltaX = Abs(line1->Pnt()->CoordinatesValue(1) -
182 line2->Pnt()->CoordinatesValue(1));
183 Standard_Real DeltaY = Abs(line1->Pnt()->CoordinatesValue(2) -
184 line2->Pnt()->CoordinatesValue(2));
185
186 Standard_Real DeltaDirX =
187 Abs(line1->Dir()->Orientation()->DirectionRatiosValue(1) -
188 line2->Dir()->Orientation()->DirectionRatiosValue(1));
189 Standard_Real DeltaDirY =
190 Abs(line1->Dir()->Orientation()->DirectionRatiosValue(2) -
191 line2->Dir()->Orientation()->DirectionRatiosValue(2));
192
193 Standard_Real preci2d = Precision::PConfusion(); //:S4136: Parametric(BRepAPI::Precision(),10);
194
195 if ((DeltaX < preci2d) || (DeltaY < preci2d))
196 return ((DeltaDirX < preci2d) && (DeltaDirY < preci2d));
197 else return Standard_False;
198
199 // Warning : la manipulation de tolerances dans ce contexte est un
200 // peu trop dangeureux.
201 // il serait preferable de plus de ne pas restreindre au
202 // cas de deux lignes.
203 // un mode plus convenable de detection serait de se servir
204 // des isos (ou bords naturels) de la surface de base
205 // et de detecter que les deux courbes se trouvent sur le
206 // bord de fermeture.
207 // il faut toutefois prevoir le cas ou les deux courbes
208 // sont confondues (ex : CATIA, "couture" de separation
209 // en deux faces d un support periodique.
210 // Ce travail reste evidement A FAIRE !!! ...
211 }
212 else return Standard_False;
213 }
214 return Standard_False;
215 }
216 return Standard_False;
217 }
218
219 // ----------------------------------------------------------------------------
220 // Method : UpdateParam3d
221 // Purpose : According to the type of curve update parameter (w1>w2)
222 // This situation occurs when an edge crosses the parametric origin.
223 // ----------------------------------------------------------------------------
224
UpdateParam3d(const Handle (Geom_Curve)& theCurve,Standard_Real & w1,Standard_Real & w2,const Standard_Real preci)225 Standard_Boolean StepToTopoDS_GeometricTool::UpdateParam3d(
226 const Handle(Geom_Curve)& theCurve,
227 Standard_Real& w1,
228 Standard_Real& w2,
229 const Standard_Real preci)
230 {
231 // w1 et/ou w2 peuvent etre en dehors des bornes naturelles de la courbe.
232 // On donnera alors la valeur en bout a w1 et/ou w2
233
234 Standard_Real cf = theCurve->FirstParameter();
235 Standard_Real cl = theCurve->LastParameter();
236
237 if (theCurve->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) && !theCurve->IsClosed())
238 {
239 if (w1 < cf)
240 {
241 #ifdef OCCT_DEBUG
242 std::cout << "Update Edge First Parameter to Curve First Parameter" << std::endl;
243 #endif
244 w1 = cf;
245 }
246 else if (w1 > cl)
247 {
248 #ifdef OCCT_DEBUG
249 std::cout << "Update Edge First Parameter to Curve Last Parameter" << std::endl;
250 #endif
251 w1 = cl;
252 }
253 if (w2 < cf) {
254 #ifdef OCCT_DEBUG
255 std::cout << "Update Edge Last Parameter to Curve First Parameter" << std::endl;
256 #endif
257 w2 = cf;
258 }
259 else if (w2 > cl) {
260 #ifdef OCCT_DEBUG
261 std::cout << "Update Edge Last Parameter to Curve Last Parameter" << std::endl;
262 #endif
263 w2 = cl;
264 }
265 }
266
267 if (w1 < w2) return Standard_True;
268
269 if (theCurve->IsPeriodic())
270 {
271 ElCLib::AdjustPeriodic(cf, cl, Precision::PConfusion(), w1, w2); //:a7 abv 11 Feb 98: preci -> PConfusion()
272 }
273 else if (theCurve->IsClosed())
274 {
275 // l'un des points projecte se trouve sur l'origine du parametrage
276 // de la courbe 3D. L algo a donne cl +- preci au lieu de cf ou vice-versa
277 // DANGER precision 3d applique a une espace 1d
278
279 // w2 = cf au lieu de w2 = cl
280 if (Abs(w2 - cf) < Precision::PConfusion() /*preci*/)
281 {
282 w2 = cl;
283 }
284 // w1 = cl au lieu de w1 = cf
285 else if (Abs(w1 - cl) < Precision::PConfusion() /*preci*/)
286 {
287 w1 = cf;
288 }
289 // on se trouve dans un cas ou l origine est traversee
290 // illegal sur une courbe fermee non periodique
291 // on inverse quand meme les parametres !!!!!!
292 else
293 {
294 //:S4136 abv 20 Apr 99: r0701_ug.stp #6230: add check in 3d
295 if (theCurve->Value(w1).Distance(theCurve->Value(cf)) < preci)
296 {
297 w1 = cf;
298 }
299 if (theCurve->Value(w2).Distance(theCurve->Value(cl)) < preci)
300 {
301 w2 = cl;
302 }
303 if (fabs(w2 - w1) < Precision::PConfusion())
304 {
305 w1 = cf;
306 w2 = cl;
307 }
308 else if (w1 > w2)
309 {
310 #ifdef OCCT_DEBUG
311 std::cout << "Warning : parameter range of edge crossing non periodic curve origin" << std::endl;
312 #endif
313 Standard_Real tmp = w1;
314 w1 = w2;
315 w2 = tmp;
316 }
317 }
318 }
319 // The curve is closed within the 3D tolerance
320 else if (theCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
321 {
322 Handle(Geom_BSplineCurve) aBSpline =
323 Handle(Geom_BSplineCurve)::DownCast(theCurve);
324 if (aBSpline->StartPoint().Distance(aBSpline->EndPoint()) <= preci)
325 {
326 //:S4136 <= BRepAPI::Precision()) {
327 // l'un des points projecte se trouve sur l'origine du parametrage
328 // de la courbe 3D. L algo a donne cl +- preci au lieu de cf ou vice-versa
329 // DANGER precision 3d applique a une espace 1d
330
331 // w2 = cf au lieu de w2 = cl
332 if (Abs(w2 - cf) < Precision::PConfusion())
333 {
334 w2 = cl;
335 }
336 // w1 = cl au lieu de w1 = cf
337 else if (Abs(w1 - cl) < Precision::PConfusion())
338 {
339 w1 = cf;
340 }
341 // on se trouve dans un cas ou l origine est traversee
342 // illegal sur une courbe fermee non periodique
343 // on inverse quand meme les parametres !!!!!!
344 else
345 {
346 #ifdef OCCT_DEBUG
347 std::cout << "Warning : parameter range of edge crossing non periodic curve origin" << std::endl;
348 #endif
349 Standard_Real tmp = w1;
350 w1 = w2;
351 w2 = tmp;
352 }
353 }
354 //abv 15.03.00 #72 bm1_pe_t4 protection of exceptions in draw
355 else if (w1 > w2)
356 {
357 #ifdef OCCT_DEBUG
358 std::cout << "Warning: parameter range is bad; curve reversed" << std::endl;
359 #endif
360 w1 = theCurve->ReversedParameter(w1);
361 w2 = theCurve->ReversedParameter(w2);
362 theCurve->Reverse();
363 }
364 //:j9 abv 11 Dec 98: PRO7747 #4875, after :j8: else
365 if (w1 == w2)
366 { //gka 10.07.1998 file PRO7656 entity 33334
367 w1 = cf;
368 w2 = cl;
369 return Standard_False;
370 }
371 }
372 else
373 {
374 #ifdef OCCT_DEBUG
375 std::cout << "UpdateParam3d Failed" << std::endl;
376 std::cout << " - Curve Type : " << theCurve->DynamicType() << std::endl;
377 std::cout << " - Param 1 : " << w1 << std::endl;
378 std::cout << " - Param 2 : " << w2 << std::endl;
379 #endif
380 //abv 15.03.00 #72 bm1_pe_t4 protection of exceptions in draw
381 if (w1 > w2)
382 {
383 #ifdef OCCT_DEBUG
384 std::cout << "Warning: parameter range is bad; curve reversed" << std::endl;
385 #endif
386 w1 = theCurve->ReversedParameter(w1);
387 w2 = theCurve->ReversedParameter(w2);
388 theCurve->Reverse();
389 }
390 //pdn 11.01.99 #144 bm1_pe_t4 protection of exceptions in draw
391 if (w1 == w2)
392 {
393 w1 -= Precision::PConfusion();
394 w2 += Precision::PConfusion();
395 }
396 return Standard_False;
397 }
398 return Standard_True;
399 }
400