1 // Created on: 1994-11-30
2 // Created by: Frederic MAUPAS
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
21 // Integration to ensure SCCS base integrity
22 //%pdn 30 Nov 98: TestRally 9 issue on r1001_ec.stp (toruses)
23 // abv 6 Jan 99: TR10: fix by PDN commented (temporarily) because CATIA do not read DEG_TORUSes
24 // rln 19.01.99: uncomment %30 pdn for integration into K4L
26 // abv 30.11.99: fix %30 pdn changed to produce SurfaceOfRevolution instead of DegenerateToroidalSurface
28 #include <TopoDSToStep_MakeStepFace.ixx>
30 #include <TopoDSToStep_MakeStepWire.hxx>
31 #include <TopoDSToStep.hxx>
34 #include <TopoDS_Iterator.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <BRepTools.hxx>
37 #include <BRep_Tool.hxx>
38 #include <Bnd_Box2d.hxx>
39 #include <BndLib_Add2dCurve.hxx>
41 #include <Geom_Surface.hxx>
42 #include <Geom_Plane.hxx>
43 #include <Geom_ElementarySurface.hxx>
44 #include <Geom_CylindricalSurface.hxx>
45 #include <Geom_ConicalSurface.hxx>
46 #include <Geom_ToroidalSurface.hxx>
47 #include <Geom_SphericalSurface.hxx>
48 #include <Geom_RectangularTrimmedSurface.hxx>
49 #include <Geom_Circle.hxx>
50 #include <Geom_TrimmedCurve.hxx>
51 #include <Geom_SurfaceOfRevolution.hxx>
53 #include <Precision.hxx>
54 #include <Geom2dAdaptor_Curve.hxx>
55 #include <Geom2dConvert.hxx>
56 #include <Geom2d_TrimmedCurve.hxx>
57 #include <Geom2d_Curve.hxx>
58 #include <Geom2d_BezierCurve.hxx>
59 #include <Geom2d_Hyperbola.hxx>
60 #include <Geom2d_Parabola.hxx>
61 #include <Geom2d_Line.hxx>
63 #include <TCollection_HAsciiString.hxx>
65 #include <StepRepr_DefinitionalRepresentation.hxx>
66 #include <StepRepr_HArray1OfRepresentationItem.hxx>
67 #include <StepGeom_GeometricRepresentationContextAndParametricRepresentationContext.hxx>
68 #include <StepGeom_Surface.hxx>
69 #include <StepGeom_SurfaceCurve.hxx>
70 #include <StepGeom_SeamCurve.hxx>
71 #include <StepGeom_HArray1OfPcurveOrSurface.hxx>
72 #include <StepShape_HArray1OfFaceBound.hxx>
73 #include <StepGeom_PcurveOrSurface.hxx>
74 #include <StepGeom_Pcurve.hxx>
75 #include <StepShape_Loop.hxx>
76 #include <StepGeom_Curve.hxx>
77 #include <StepShape_EdgeCurve.hxx>
78 #include <StepShape_AdvancedFace.hxx>
79 #include <StepShape_FaceBound.hxx>
80 #include <StepShape_FaceOuterBound.hxx>
81 #include <StepGeom_ToroidalSurface.hxx>
82 #include <StepGeom_DegenerateToroidalSurface.hxx>
84 #include <UnitsMethods.hxx>
86 #include <GeomToStep_MakeSurface.hxx>
87 #include <GeomToStep_MakeCurve.hxx>
89 #include <TColStd_SequenceOfTransient.hxx>
90 #include <TransferBRep_ShapeMapper.hxx>
91 #include <TCollection_HAsciiString.hxx>
93 #include <ShapeAlgo.hxx>
94 #include <ShapeAlgo_AlgoContainer.hxx>
96 // Processing of non-manifold topology (ssv; 10.11.2010)
97 #include <TransferBRep.hxx>
98 #include <Interface_Static.hxx>
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
104 TopoDSToStep_MakeStepFace::TopoDSToStep_MakeStepFace()
106 done = Standard_False;
109 TopoDSToStep_MakeStepFace::TopoDSToStep_MakeStepFace
110 (const TopoDS_Face& F,
111 TopoDSToStep_Tool& T,
112 const Handle(Transfer_FinderProcess)& FP)
114 done = Standard_False;
118 // ----------------------------------------------------------------------------
121 // ----------------------------------------------------------------------------
123 void TopoDSToStep_MakeStepFace::Init(const TopoDS_Face& aFace,
124 TopoDSToStep_Tool& aTool,
125 const Handle(Transfer_FinderProcess)& FP)
127 // --------------------------------------------------------------
128 // the face is given with its relative orientation (in the Shell)
129 // --------------------------------------------------------------
131 //szv#4:S4163:12Mar99 SGI warns
132 TopoDS_Shape sh = aFace.Oriented(TopAbs_FORWARD);
133 const TopoDS_Face ForwardFace = TopoDS::Face(sh);
134 aTool.SetCurrentFace(ForwardFace);
135 Handle(TransferBRep_ShapeMapper) errShape =
136 new TransferBRep_ShapeMapper(aFace); // on ne sait jamais
138 // [BEGIN] Processing non-manifold topology (another approach) (ssv; 10.11.2010)
139 Standard_Boolean isNMMode = Interface_Static::IVal("write.step.nonmanifold");
141 Handle(StepShape_AdvancedFace) anAF;
142 Handle(TransferBRep_ShapeMapper) aSTEPMapper = TransferBRep::ShapeMapper(FP, aFace);
143 if ( FP->FindTypedTransient(aSTEPMapper, STANDARD_TYPE(StepShape_AdvancedFace), anAF) ) {
144 // Non-manifold topology detected
145 Handle(StepShape_AdvancedFace) aLinkingAF = new StepShape_AdvancedFace;
146 aLinkingAF->Init( anAF->Name(),
148 anAF->FaceGeometry(),
149 !anAF->SameSense() );
151 myError = TopoDSToStep_FaceDone;
152 myResult = aLinkingAF;
153 done = Standard_True;
157 // [END] Processing non-manifold topology (ssv; 10.11.2010)
159 if (aTool.IsBound(aFace)) {
160 myError = TopoDSToStep_FaceDone;
161 done = Standard_True;
162 myResult = aTool.Find(aFace);
169 //BRepAdaptor_Surface SA = BRepAdaptor_Surface(ForwardFace);
171 if (aFace.Orientation() == TopAbs_INTERNAL ||
172 aFace.Orientation() == TopAbs_EXTERNAL ) {
173 FP->AddWarning(errShape, " Face from Non Manifold Topology");
174 myError = TopoDSToStep_NonManifoldFace;
175 done = Standard_False;
179 // ------------------
180 // Get the Outer Wire
181 // ------------------
183 const TopoDS_Wire theOuterWire = BRepTools::OuterWire(ForwardFace);
185 if (theOuterWire.IsNull()) {
187 cout<< "Warning : Face without wire not mapped";
189 FP->AddWarning(errShape, " Face without wire not mapped");
190 myError = TopoDSToStep_InfiniteFace;
191 done = Standard_False;
199 Handle(Geom_Surface) Su = BRep_Tool::Surface(ForwardFace);
200 // CKY 23 SEP 1996 : une FACE de Step n a pas droit a RECTANGULAR_TRIMMED...
201 // Il faut donc d abord "demonter" la RectangularTrimmedSurface pour
202 // passer la Surface de base
203 Handle(Geom_RectangularTrimmedSurface) aRTS =
204 Handle(Geom_RectangularTrimmedSurface)::DownCast(Su);
205 if (!aRTS.IsNull()) Su = aRTS->BasisSurface();
207 //Handle(Geom_Surface) Su = SA.Surface().Surface();
208 //Su = Handle(Geom_Surface)::DownCast(Su->Copy());
209 //gp_Trsf Tr1 = SA.Trsf();
210 //Su->Transform(Tr1);
212 // Surfaces with indirect Axes are already reversed
213 // (see TopoDSToStepAct_Actor)
214 //Standard_Boolean ReverseSurfaceOrientation = Standard_False; //szv#4:S4163:12Mar99 unused
215 aTool.SetSurfaceReversed(Standard_False);
217 GeomToStep_MakeSurface MkSurface(Su);
218 Handle(StepGeom_Surface) Spms = MkSurface.Value();
220 //%pdn 30 Nov 98: TestRally 9 issue on r1001_ec.stp:
221 // toruses with major_radius < minor are re-coded as degenerate
222 // rln 19.01.99: uncomment %30 pdn for integration into K4L
223 if(Spms->IsKind(STANDARD_TYPE(StepGeom_ToroidalSurface))) {
224 Handle(StepGeom_ToroidalSurface) trsf = Handle(StepGeom_ToroidalSurface)::DownCast(Spms);
225 Standard_Real R = trsf->MajorRadius();
226 Standard_Real r = trsf->MinorRadius();
227 if ( R < r ) { // if torus is degenerate, make revolution instead
228 Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(Su);
229 gp_Ax3 Ax3 = TS->Position();
230 gp_Pnt pos = Ax3.Location();
231 gp_Dir dir = Ax3.Direction();
232 gp_Dir X = Ax3.XDirection();
234 // create basis curve
235 Standard_Real UF, VF, UL, VL;
236 ShapeAlgo::AlgoContainer()->GetFaceUVBounds ( aFace, UF, UL, VF, VL );
237 gp_Ax2 Ax2 ( pos.XYZ() + X.XYZ() * TS->MajorRadius(), X ^ dir, X );
238 Handle(Geom_Curve) BasisCurve = new Geom_Circle ( Ax2, TS->MinorRadius() );
240 // convert basis curve to bspline in order to avoid self-intersecting
241 // surface of revolution (necessary e.g. for CATIA)
242 if ( VL - VF - 2 * M_PI < -Precision::PConfusion() )
243 BasisCurve = ShapeAlgo::AlgoContainer()->ConvertCurveToBSpline (BasisCurve, VF, VL, Precision::Approximation(),
245 // BasisCurve = new Geom_TrimmedCurve ( BasisCurve, VF, VL );
247 // create surface of revolution
248 gp_Ax1 Axis = Ax3.Axis();
249 if ( ! Ax3.Direct() ) Axis.Reverse();
250 Handle(Geom_SurfaceOfRevolution) Rev = new Geom_SurfaceOfRevolution ( BasisCurve, Axis );
253 GeomToStep_MakeSurface MkRev(Rev);
254 Spms = MkRev.Value();
262 Handle(StepShape_Loop) Loop;
263 Handle(StepShape_FaceBound) FaceBound;
265 TopoDSToStep_MakeStepWire MkWire;
266 TColStd_SequenceOfTransient mySeq;
268 // Initialize the Wire Explorer with the forward face
270 TopExp_Explorer WireExp;
271 for (WireExp.Init(ForwardFace,TopAbs_WIRE);WireExp.More();WireExp.Next()) {
273 const TopoDS_Wire CurrentWire = TopoDS::Wire(WireExp.Current());
274 if (!CurrentWire.IsNull()) {
276 //szv#4:S4163:12Mar99 SGI warns
277 //TopoDS_Shape ssh = CurrentWire.Oriented(TopAbs_FORWARD);
278 //const TopoDS_Wire ForwardWire = TopoDS::Wire(ssh);
280 //MkWire.Init(ForwardWire, aTool, FP);
281 MkWire.Init(CurrentWire, aTool, FP);
282 if (MkWire.IsDone()) Loop = Handle(StepShape_Loop)::DownCast(MkWire.Value());
285 cout << TopoDSToStep::DecodeWireError(MkWire.Error()) << endl;
287 FP->AddWarning(errShape, " a Wire not mapped");
292 //if (theOuterWire.IsEqual(CurrentWire))
293 //FaceBound = new StepShape_FaceOuterBound();
295 FaceBound = new StepShape_FaceBound();
297 // ----------------------------------------------------
298 // When the geometric normal of a Surface is reversed :
299 // - the wire topological orientation is reversed
300 // ----------------------------------------------------
301 // CAS.CADE face orientation :
302 // when a face is reversed in a shell, the orientation of the underlying
303 // topology is implicitly reversed. This is not the case in Step.
304 // If face orientation is Reversed => the underlying (Step mapped) wire
305 // are explicitly reversed
307 Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString("");
309 // Ajoute le 30 Juin pour TEST
310 // Il convient de reprendre a la base ce probleme d'orientation
311 // et notamment la politique d`exploration du Shape (on explore
312 // toujours les sous-shapes d'un shape de maniere FORWARD !
313 // la modif (on ajoute : si context faceted ... sinon) est a verifier
314 // aupres des autres editeurs de CFAO de la Round Table.
316 if (!aTool.Faceted() && aFace.Orientation() == TopAbs_REVERSED)
317 FaceBound->Init(aName, Loop,
318 (CurrentWire.Orientation() == TopAbs_REVERSED));
320 FaceBound->Init(aName, Loop,
321 (CurrentWire.Orientation() == TopAbs_FORWARD));
323 mySeq.Append(FaceBound);
326 // ----------------------------------------
327 // Translate the Edge 2D Geometry (pcurves)
328 // ----------------------------------------
330 if ( ! aTool.Faceted() && aTool.PCurveMode() != 0 ) {
332 TopExp_Explorer Ex(ForwardFace, TopAbs_EDGE);
334 // ------------------------------------------------
335 // Exploration of all the Edges in the current face
336 // ------------------------------------------------
338 for (;Ex.More(); Ex.Next()) {
339 TopoDS_Edge E = TopoDS::Edge(Ex.Current());
340 Standard_Real cf, cl;
341 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, ForwardFace, cf, cl);
343 //CA = BRepAdaptor_Curve(E, ForwardFace);
344 //GeomAbs_CurveType typCOnS = CA.CurveOnSurface().GetCurve().GetType();
346 //if (typCOnS == GeomAbs_Line && BRep_Tool::Degenerated(E) ) {
347 if ( //:abv 26Jan00, CAX-IF TRJ3: C2d->IsKind(STANDARD_TYPE(Geom2d_Line)) &&
348 BRep_Tool::Degenerated(E)) {
349 // The edge 2D Geometry degenerates in 3D
350 // The edge 2D geometry is not mapped onto any Step entity
351 // (ProStep agreement)
354 else { // Copy the Curve2d which might be changed
355 //C2d = CA.CurveOnSurface().GetCurve().Curve();
356 //C2d = Handle(Geom2d_Curve)::DownCast(C2d->Copy());
357 C2d = Handle(Geom2d_Curve)::DownCast(C2d->Copy());
360 // for writing VERTEX_LOOP
361 if(!aTool.IsBound(E)) continue;
362 Handle(StepGeom_Curve) Cpms =
363 Handle(StepShape_EdgeCurve)::DownCast(aTool.Find(E))->EdgeGeometry();
364 if ( Cpms.IsNull() ) continue;
366 if ( !C2d.IsNull() && aTool.IsBound(E) ) {
367 if (C2d->IsKind(STANDARD_TYPE(Geom2d_Hyperbola)) ||
368 C2d->IsKind(STANDARD_TYPE(Geom2d_Parabola))) {
369 if(Su->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
370 Su->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
371 Su->IsKind(STANDARD_TYPE(Geom_ConicalSurface)) ||
372 Su->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
373 C2d = new Geom2d_TrimmedCurve(C2d, cf, cl, Standard_True);
377 if ((C2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) ||
378 (C2d->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)))) {
379 C2d = Geom2dConvert::CurveToBSplineCurve(C2d);
382 // if the Surface is a RectangularTrimmedSurface,
383 // use the BasisSurface.
384 // CKY 23 SEP 1996 : on reste en Radian car on code des Radians
385 // sauf que ca ne marche pas bien ...
386 Handle(Geom2d_Curve) C2dMapped;
387 if (Su->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
388 Handle(Geom_RectangularTrimmedSurface) alocalRTS =
389 Handle(Geom_RectangularTrimmedSurface)::DownCast(Su);
390 C2dMapped = UnitsMethods::RadianToDegree(C2d, alocalRTS->BasisSurface());
393 C2dMapped = UnitsMethods::RadianToDegree(C2d, Su);
396 // C2dMapped = C2d; // cky : en remplacement de ce qui precede
397 GeomToStep_MakeCurve MkCurve(C2dMapped);
399 // --------------------
400 // Translate the Pcurve
401 // --------------------
403 Handle(StepGeom_Pcurve) Pc = new StepGeom_Pcurve;
404 Handle(StepRepr_DefinitionalRepresentation) DRI =
405 new StepRepr_DefinitionalRepresentation;
406 Handle(StepRepr_HArray1OfRepresentationItem) aItems =
407 new StepRepr_HArray1OfRepresentationItem(1,1);
408 aItems->SetValue(1,MkCurve.Value());
409 Handle(StepGeom_GeometricRepresentationContextAndParametricRepresentationContext) aContext =
410 new StepGeom_GeometricRepresentationContextAndParametricRepresentationContext();
411 Handle(TCollection_HAsciiString) aContextIdentifier =
412 new TCollection_HAsciiString("2D SPACE");
413 Handle(TCollection_HAsciiString) aContextType =
414 new TCollection_HAsciiString("");
415 Standard_Integer aCoordSpaceDim = 2;
416 aContext->Init(aContextIdentifier, aContextType, aCoordSpaceDim);
418 Handle(TCollection_HAsciiString) aName =
419 new TCollection_HAsciiString("");
421 DRI->Init(aName, aItems, aContext);
422 Pc->Init(aName, Spms, DRI );
423 Handle(StepGeom_SurfaceCurve) C1pms =
424 Handle(StepGeom_SurfaceCurve)::DownCast(Cpms);
425 Handle(StepGeom_HArray1OfPcurveOrSurface) aGeom = C1pms->AssociatedGeometry();
426 if (aGeom.IsNull()) aGeom = new StepGeom_HArray1OfPcurveOrSurface(1,2);
427 StepGeom_PcurveOrSurface PcOrSur;
428 PcOrSur.SetValue(Pc);
429 if ((aGeom->Value(1)).IsNull()) {
430 aGeom->SetValue(1, PcOrSur);
431 if (C1pms->IsKind(STANDARD_TYPE(StepGeom_SeamCurve))) {
432 aGeom->SetValue(2,PcOrSur); // c est au moins ca
435 else if (aGeom->Value(2).IsNull() || //) {
436 C1pms->IsKind(STANDARD_TYPE(StepGeom_SeamCurve))) { //:a8 abv 13 Feb 98: allow seam to have two different pcurves
437 aGeom->SetValue(2, PcOrSur);
439 C1pms->SetAssociatedGeometry(aGeom);
444 // ------------------
445 // Translate the Face
446 // ------------------
448 Standard_Integer nbWires = mySeq.Length();
450 Handle(StepShape_HArray1OfFaceBound) aBounds =
451 new StepShape_HArray1OfFaceBound(1,nbWires);
452 for ( i=1; i<=nbWires; i++ ) {
453 aBounds->SetValue(i, Handle(StepShape_FaceBound)::DownCast(mySeq.Value(i)));
455 Handle(StepShape_AdvancedFace) Fpms = new StepShape_AdvancedFace;
457 // ---------------------------------------------------------------
458 // The underlying surface has always a direct axis (see above)
459 // ---------------------------------------------------------------
461 Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString("");
463 Fpms->Init(aName, aBounds, Spms, aFace.Orientation() == TopAbs_FORWARD);
465 aTool.Bind(aFace, Fpms);
466 myError = TopoDSToStep_FaceDone;
468 done = Standard_True;
472 // ----------------------------
473 // MakeFace Face Error Handling
474 // ----------------------------
476 FP->AddWarning(errShape, " No Wires of this Face were mapped");
477 myError = TopoDSToStep_NoWireMapped;
478 done = Standard_False;
483 // ----------------------------------------------------------------------------
486 // ----------------------------------------------------------------------------
488 const Handle(StepShape_TopologicalRepresentationItem)& TopoDSToStep_MakeStepFace::Value() const
490 StdFail_NotDone_Raise_if(!done,"");
494 // ----------------------------------------------------------------------------
497 // ----------------------------------------------------------------------------
499 TopoDSToStep_MakeFaceError TopoDSToStep_MakeStepFace::Error() const