1 // Created on: 1994-11-30
2 // Created by: Frederic MAUPAS
3 // Copyright (c) 1994-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 // Integration to ensure SCCS base integrity
18 //%pdn 30 Nov 98: TestRally 9 issue on r1001_ec.stp (toruses)
19 // abv 6 Jan 99: TR10: fix by PDN commented (temporarily) because CATIA do not read DEG_TORUSes
20 // rln 19.01.99: uncomment %30 pdn for integration into K4L
22 // abv 30.11.99: fix %30 pdn changed to produce SurfaceOfRevolution instead of DegenerateToroidalSurface
24 #include <Bnd_Box2d.hxx>
25 #include <BndLib_Add2dCurve.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRepTools.hxx>
28 #include <Geom2d_BezierCurve.hxx>
29 #include <Geom2d_Curve.hxx>
30 #include <Geom2d_Hyperbola.hxx>
31 #include <Geom2d_Line.hxx>
32 #include <Geom2d_Parabola.hxx>
33 #include <Geom2d_TrimmedCurve.hxx>
34 #include <Geom2dAdaptor_Curve.hxx>
35 #include <Geom2dConvert.hxx>
36 #include <Geom_BSplineCurve.hxx>
37 #include <Geom_Circle.hxx>
38 #include <Geom_ConicalSurface.hxx>
39 #include <Geom_CylindricalSurface.hxx>
40 #include <Geom_ElementarySurface.hxx>
41 #include <Geom_Plane.hxx>
42 #include <Geom_RectangularTrimmedSurface.hxx>
43 #include <Geom_SphericalSurface.hxx>
44 #include <Geom_Surface.hxx>
45 #include <Geom_SurfaceOfRevolution.hxx>
46 #include <Geom_ToroidalSurface.hxx>
47 #include <Geom_TrimmedCurve.hxx>
48 #include <GeomToStep_MakeCurve.hxx>
49 #include <GeomToStep_MakeSurface.hxx>
50 #include <Interface_Static.hxx>
51 #include <Precision.hxx>
52 #include <ShapeAlgo.hxx>
53 #include <ShapeAlgo_AlgoContainer.hxx>
54 #include <StdFail_NotDone.hxx>
55 #include <StepGeom_Curve.hxx>
56 #include <StepGeom_DegenerateToroidalSurface.hxx>
57 #include <StepGeom_GeometricRepresentationContextAndParametricRepresentationContext.hxx>
58 #include <StepGeom_HArray1OfPcurveOrSurface.hxx>
59 #include <StepGeom_Pcurve.hxx>
60 #include <StepGeom_PcurveOrSurface.hxx>
61 #include <StepGeom_SeamCurve.hxx>
62 #include <StepGeom_Surface.hxx>
63 #include <StepGeom_SurfaceCurve.hxx>
64 #include <StepGeom_ToroidalSurface.hxx>
65 #include <StepRepr_DefinitionalRepresentation.hxx>
66 #include <StepRepr_HArray1OfRepresentationItem.hxx>
67 #include <StepShape_AdvancedFace.hxx>
68 #include <StepShape_EdgeCurve.hxx>
69 #include <StepShape_FaceBound.hxx>
70 #include <StepShape_FaceOuterBound.hxx>
71 #include <StepShape_HArray1OfFaceBound.hxx>
72 #include <StepShape_Loop.hxx>
73 #include <StepShape_TopologicalRepresentationItem.hxx>
74 #include <TCollection_HAsciiString.hxx>
75 #include <TColStd_SequenceOfTransient.hxx>
76 #include <TopExp_Explorer.hxx>
78 #include <TopoDS_Face.hxx>
79 #include <TopoDS_Iterator.hxx>
80 #include <TopoDSToStep.hxx>
81 #include <TopoDSToStep_MakeStepFace.hxx>
82 #include <TopoDSToStep_MakeStepWire.hxx>
83 #include <TopoDSToStep_Tool.hxx>
84 #include <Transfer_FinderProcess.hxx>
85 #include <TransferBRep.hxx>
86 #include <TransferBRep_ShapeMapper.hxx>
87 #include <UnitsMethods.hxx>
89 // Processing of non-manifold topology (ssv; 10.11.2010)
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
93 TopoDSToStep_MakeStepFace::TopoDSToStep_MakeStepFace()
95 done = Standard_False;
98 TopoDSToStep_MakeStepFace::TopoDSToStep_MakeStepFace
99 (const TopoDS_Face& F,
100 TopoDSToStep_Tool& T,
101 const Handle(Transfer_FinderProcess)& FP)
103 done = Standard_False;
107 // ----------------------------------------------------------------------------
110 // ----------------------------------------------------------------------------
112 void TopoDSToStep_MakeStepFace::Init(const TopoDS_Face& aFace,
113 TopoDSToStep_Tool& aTool,
114 const Handle(Transfer_FinderProcess)& FP)
116 // --------------------------------------------------------------
117 // the face is given with its relative orientation (in the Shell)
118 // --------------------------------------------------------------
120 //szv#4:S4163:12Mar99 SGI warns
121 TopoDS_Shape sh = aFace.Oriented(TopAbs_FORWARD);
122 const TopoDS_Face ForwardFace = TopoDS::Face(sh);
123 aTool.SetCurrentFace(ForwardFace);
124 Handle(TransferBRep_ShapeMapper) errShape =
125 new TransferBRep_ShapeMapper(aFace); // on ne sait jamais
127 // [BEGIN] Processing non-manifold topology (another approach) (ssv; 10.11.2010)
128 Standard_Boolean isNMMode = Interface_Static::IVal("write.step.nonmanifold");
130 Handle(StepShape_AdvancedFace) anAF;
131 Handle(TransferBRep_ShapeMapper) aSTEPMapper = TransferBRep::ShapeMapper(FP, aFace);
132 if ( FP->FindTypedTransient(aSTEPMapper, STANDARD_TYPE(StepShape_AdvancedFace), anAF) ) {
133 // Non-manifold topology detected
134 Handle(StepShape_AdvancedFace) aLinkingAF = new StepShape_AdvancedFace;
135 aLinkingAF->Init( anAF->Name(),
137 anAF->FaceGeometry(),
138 !anAF->SameSense() );
140 myError = TopoDSToStep_FaceDone;
141 myResult = aLinkingAF;
142 done = Standard_True;
146 // [END] Processing non-manifold topology (ssv; 10.11.2010)
148 if (aTool.IsBound(aFace)) {
149 myError = TopoDSToStep_FaceDone;
150 done = Standard_True;
151 myResult = aTool.Find(aFace);
158 //BRepAdaptor_Surface SA = BRepAdaptor_Surface(ForwardFace);
160 if (aFace.Orientation() == TopAbs_INTERNAL ||
161 aFace.Orientation() == TopAbs_EXTERNAL ) {
162 FP->AddWarning(errShape, " Face from Non Manifold Topology");
163 myError = TopoDSToStep_NonManifoldFace;
164 done = Standard_False;
168 // ------------------
169 // Get the Outer Wire
170 // ------------------
172 const TopoDS_Wire theOuterWire = BRepTools::OuterWire(ForwardFace);
174 if (theOuterWire.IsNull()) {
176 cout<< "Warning : Face without wire not mapped";
178 FP->AddWarning(errShape, " Face without wire not mapped");
179 myError = TopoDSToStep_InfiniteFace;
180 done = Standard_False;
188 Handle(Geom_Surface) Su = BRep_Tool::Surface(ForwardFace);
189 // CKY 23 SEP 1996 : une FACE de Step n a pas droit a RECTANGULAR_TRIMMED...
190 // Il faut donc d abord "demonter" la RectangularTrimmedSurface pour
191 // passer la Surface de base
192 Handle(Geom_RectangularTrimmedSurface) aRTS =
193 Handle(Geom_RectangularTrimmedSurface)::DownCast(Su);
194 if (!aRTS.IsNull()) Su = aRTS->BasisSurface();
196 //Handle(Geom_Surface) Su = SA.Surface().Surface();
197 //Su = Handle(Geom_Surface)::DownCast(Su->Copy());
198 //gp_Trsf Tr1 = SA.Trsf();
199 //Su->Transform(Tr1);
201 // Surfaces with indirect Axes are already reversed
202 // (see TopoDSToStepAct_Actor)
203 //Standard_Boolean ReverseSurfaceOrientation = Standard_False; //szv#4:S4163:12Mar99 unused
204 aTool.SetSurfaceReversed(Standard_False);
206 GeomToStep_MakeSurface MkSurface(Su);
207 Handle(StepGeom_Surface) Spms = MkSurface.Value();
209 //%pdn 30 Nov 98: TestRally 9 issue on r1001_ec.stp:
210 // toruses with major_radius < minor are re-coded as degenerate
211 // rln 19.01.99: uncomment %30 pdn for integration into K4L
212 if(Spms->IsKind(STANDARD_TYPE(StepGeom_ToroidalSurface))) {
213 Handle(StepGeom_ToroidalSurface) trsf = Handle(StepGeom_ToroidalSurface)::DownCast(Spms);
214 Standard_Real R = trsf->MajorRadius();
215 Standard_Real r = trsf->MinorRadius();
216 if ( R < r ) { // if torus is degenerate, make revolution instead
217 Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(Su);
218 gp_Ax3 Ax3 = TS->Position();
219 gp_Pnt pos = Ax3.Location();
220 gp_Dir dir = Ax3.Direction();
221 gp_Dir X = Ax3.XDirection();
223 // create basis curve
224 Standard_Real UF, VF, UL, VL;
225 ShapeAlgo::AlgoContainer()->GetFaceUVBounds ( aFace, UF, UL, VF, VL );
226 gp_Ax2 Ax2 ( pos.XYZ() + X.XYZ() * TS->MajorRadius(), X ^ dir, X );
227 Handle(Geom_Curve) BasisCurve = new Geom_Circle ( Ax2, TS->MinorRadius() );
229 // convert basis curve to bspline in order to avoid self-intersecting
230 // surface of revolution (necessary e.g. for CATIA)
231 if ( VL - VF - 2 * M_PI < -Precision::PConfusion() )
232 BasisCurve = ShapeAlgo::AlgoContainer()->ConvertCurveToBSpline (BasisCurve, VF, VL, Precision::Approximation(),
234 // BasisCurve = new Geom_TrimmedCurve ( BasisCurve, VF, VL );
236 // create surface of revolution
237 gp_Ax1 Axis = Ax3.Axis();
238 if ( ! Ax3.Direct() ) Axis.Reverse();
239 Handle(Geom_SurfaceOfRevolution) Rev = new Geom_SurfaceOfRevolution ( BasisCurve, Axis );
242 GeomToStep_MakeSurface MkRev(Rev);
243 Spms = MkRev.Value();
251 Handle(StepShape_Loop) Loop;
252 Handle(StepShape_FaceBound) FaceBound;
254 TopoDSToStep_MakeStepWire MkWire;
255 TColStd_SequenceOfTransient mySeq;
257 // Initialize the Wire Explorer with the forward face
259 TopExp_Explorer WireExp;
260 for (WireExp.Init(ForwardFace,TopAbs_WIRE);WireExp.More();WireExp.Next()) {
262 const TopoDS_Wire CurrentWire = TopoDS::Wire(WireExp.Current());
263 if (!CurrentWire.IsNull()) {
265 //szv#4:S4163:12Mar99 SGI warns
266 //TopoDS_Shape ssh = CurrentWire.Oriented(TopAbs_FORWARD);
267 //const TopoDS_Wire ForwardWire = TopoDS::Wire(ssh);
269 //MkWire.Init(ForwardWire, aTool, FP);
270 MkWire.Init(CurrentWire, aTool, FP);
271 if (MkWire.IsDone()) Loop = Handle(StepShape_Loop)::DownCast(MkWire.Value());
274 cout << TopoDSToStep::DecodeWireError(MkWire.Error())->String() << endl;
276 FP->AddWarning(errShape, " a Wire not mapped");
281 //if (theOuterWire.IsEqual(CurrentWire))
282 //FaceBound = new StepShape_FaceOuterBound();
284 FaceBound = new StepShape_FaceBound();
286 // ----------------------------------------------------
287 // When the geometric normal of a Surface is reversed :
288 // - the wire topological orientation is reversed
289 // ----------------------------------------------------
290 // CAS.CADE face orientation :
291 // when a face is reversed in a shell, the orientation of the underlying
292 // topology is implicitly reversed. This is not the case in Step.
293 // If face orientation is Reversed => the underlying (Step mapped) wire
294 // are explicitly reversed
296 Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString("");
298 // Ajoute le 30 Juin pour TEST
299 // Il convient de reprendre a la base ce probleme d'orientation
300 // et notamment la politique d`exploration du Shape (on explore
301 // toujours les sous-shapes d'un shape de maniere FORWARD !
302 // la modif (on ajoute : si context faceted ... sinon) est a verifier
303 // aupres des autres editeurs de CFAO de la Round Table.
305 if (!aTool.Faceted() && aFace.Orientation() == TopAbs_REVERSED)
306 FaceBound->Init(aName, Loop,
307 (CurrentWire.Orientation() == TopAbs_REVERSED));
309 FaceBound->Init(aName, Loop,
310 (CurrentWire.Orientation() == TopAbs_FORWARD));
312 mySeq.Append(FaceBound);
315 // ----------------------------------------
316 // Translate the Edge 2D Geometry (pcurves)
317 // ----------------------------------------
319 if ( ! aTool.Faceted() && aTool.PCurveMode() != 0 ) {
321 TopExp_Explorer Ex(ForwardFace, TopAbs_EDGE);
323 // ------------------------------------------------
324 // Exploration of all the Edges in the current face
325 // ------------------------------------------------
327 for (;Ex.More(); Ex.Next()) {
328 TopoDS_Edge E = TopoDS::Edge(Ex.Current());
329 Standard_Real cf, cl;
330 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, ForwardFace, cf, cl);
332 //CA = BRepAdaptor_Curve(E, ForwardFace);
333 //GeomAbs_CurveType typCOnS = CA.CurveOnSurface().GetCurve().GetType();
335 //if (typCOnS == GeomAbs_Line && BRep_Tool::Degenerated(E) ) {
336 if ( //:abv 26Jan00, CAX-IF TRJ3: C2d->IsKind(STANDARD_TYPE(Geom2d_Line)) &&
337 BRep_Tool::Degenerated(E)) {
338 // The edge 2D Geometry degenerates in 3D
339 // The edge 2D geometry is not mapped onto any Step entity
340 // (ProStep agreement)
343 else { // Copy the Curve2d which might be changed
344 //C2d = CA.CurveOnSurface().GetCurve().Curve();
345 //C2d = Handle(Geom2d_Curve)::DownCast(C2d->Copy());
346 C2d = Handle(Geom2d_Curve)::DownCast(C2d->Copy());
349 // for writing VERTEX_LOOP
350 if(!aTool.IsBound(E)) continue;
351 Handle(StepGeom_Curve) Cpms =
352 Handle(StepShape_EdgeCurve)::DownCast(aTool.Find(E))->EdgeGeometry();
353 if ( Cpms.IsNull() ) continue;
355 if ( !C2d.IsNull() && aTool.IsBound(E) ) {
356 if (C2d->IsKind(STANDARD_TYPE(Geom2d_Hyperbola)) ||
357 C2d->IsKind(STANDARD_TYPE(Geom2d_Parabola))) {
358 if(Su->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
359 Su->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
360 Su->IsKind(STANDARD_TYPE(Geom_ConicalSurface)) ||
361 Su->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
362 C2d = new Geom2d_TrimmedCurve(C2d, cf, cl, Standard_True);
366 if ((C2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) ||
367 (C2d->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)))) {
368 C2d = Geom2dConvert::CurveToBSplineCurve(C2d);
371 // if the Surface is a RectangularTrimmedSurface,
372 // use the BasisSurface.
373 // CKY 23 SEP 1996 : on reste en Radian car on code des Radians
374 // sauf que ca ne marche pas bien ...
375 Handle(Geom2d_Curve) C2dMapped;
376 if (Su->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
377 Handle(Geom_RectangularTrimmedSurface) alocalRTS =
378 Handle(Geom_RectangularTrimmedSurface)::DownCast(Su);
379 C2dMapped = UnitsMethods::RadianToDegree(C2d, alocalRTS->BasisSurface());
382 C2dMapped = UnitsMethods::RadianToDegree(C2d, Su);
385 // C2dMapped = C2d; // cky : en remplacement de ce qui precede
386 GeomToStep_MakeCurve MkCurve(C2dMapped);
388 // --------------------
389 // Translate the Pcurve
390 // --------------------
392 Handle(StepGeom_Pcurve) Pc = new StepGeom_Pcurve;
393 Handle(StepRepr_DefinitionalRepresentation) DRI =
394 new StepRepr_DefinitionalRepresentation;
395 Handle(StepRepr_HArray1OfRepresentationItem) aItems =
396 new StepRepr_HArray1OfRepresentationItem(1,1);
397 aItems->SetValue(1,MkCurve.Value());
398 Handle(StepGeom_GeometricRepresentationContextAndParametricRepresentationContext) aContext =
399 new StepGeom_GeometricRepresentationContextAndParametricRepresentationContext();
400 Handle(TCollection_HAsciiString) aContextIdentifier =
401 new TCollection_HAsciiString("2D SPACE");
402 Handle(TCollection_HAsciiString) aContextType =
403 new TCollection_HAsciiString("");
404 Standard_Integer aCoordSpaceDim = 2;
405 aContext->Init(aContextIdentifier, aContextType, aCoordSpaceDim);
407 Handle(TCollection_HAsciiString) aName =
408 new TCollection_HAsciiString("");
410 DRI->Init(aName, aItems, aContext);
411 Pc->Init(aName, Spms, DRI );
412 Handle(StepGeom_SurfaceCurve) C1pms =
413 Handle(StepGeom_SurfaceCurve)::DownCast(Cpms);
414 Handle(StepGeom_HArray1OfPcurveOrSurface) aGeom = C1pms->AssociatedGeometry();
415 if (aGeom.IsNull()) aGeom = new StepGeom_HArray1OfPcurveOrSurface(1,2);
416 StepGeom_PcurveOrSurface PcOrSur;
417 PcOrSur.SetValue(Pc);
418 if ((aGeom->Value(1)).IsNull()) {
419 aGeom->SetValue(1, PcOrSur);
420 if (C1pms->IsKind(STANDARD_TYPE(StepGeom_SeamCurve))) {
421 aGeom->SetValue(2,PcOrSur); // c est au moins ca
424 else if (aGeom->Value(2).IsNull() || //) {
425 C1pms->IsKind(STANDARD_TYPE(StepGeom_SeamCurve))) { //:a8 abv 13 Feb 98: allow seam to have two different pcurves
426 aGeom->SetValue(2, PcOrSur);
428 C1pms->SetAssociatedGeometry(aGeom);
433 // ------------------
434 // Translate the Face
435 // ------------------
437 Standard_Integer nbWires = mySeq.Length();
439 Handle(StepShape_HArray1OfFaceBound) aBounds =
440 new StepShape_HArray1OfFaceBound(1,nbWires);
441 for ( i=1; i<=nbWires; i++ ) {
442 aBounds->SetValue(i, Handle(StepShape_FaceBound)::DownCast(mySeq.Value(i)));
444 Handle(StepShape_AdvancedFace) Fpms = new StepShape_AdvancedFace;
446 // ---------------------------------------------------------------
447 // The underlying surface has always a direct axis (see above)
448 // ---------------------------------------------------------------
450 Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString("");
452 Fpms->Init(aName, aBounds, Spms, aFace.Orientation() == TopAbs_FORWARD);
454 aTool.Bind(aFace, Fpms);
455 myError = TopoDSToStep_FaceDone;
457 done = Standard_True;
461 // ----------------------------
462 // MakeFace Face Error Handling
463 // ----------------------------
465 FP->AddWarning(errShape, " No Wires of this Face were mapped");
466 myError = TopoDSToStep_NoWireMapped;
467 done = Standard_False;
472 // ----------------------------------------------------------------------------
475 // ----------------------------------------------------------------------------
477 const Handle(StepShape_TopologicalRepresentationItem)& TopoDSToStep_MakeStepFace::Value() const
479 StdFail_NotDone_Raise_if(!done,"");
483 // ----------------------------------------------------------------------------
486 // ----------------------------------------------------------------------------
488 TopoDSToStep_MakeFaceError TopoDSToStep_MakeStepFace::Error() const