0027772: Foundation Classes - define Standard_Boolean using C++ type "bool" instead...
[occt.git] / src / STEPControl / STEPControl_ActorWrite.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
7fd59977 14//:k8 abv 6 Jan 99: unique names for PRODUCTs
15//:k9 abv 6 Jan 99: TR10: eliminating duplicated APPLICATION_CONTEXT entities
16//abv,gka 05.04.99: S4136: change parameters and update units
17// PTV 22.08.2002 OCC609 transfer solo vertices into step file.
18// PTV 16.09.2002 OCC725 transfer compound of vertices into one geometrical curve set.
7fd59977 19
42cf5bc1 20#include <BRep_Builder.hxx>
21#include <BRep_Tool.hxx>
22#include <BRepTools_Modifier.hxx>
23#include <Geom_Curve.hxx>
24#include <Geom_Line.hxx>
25#include <Geom_Plane.hxx>
26#include <Geom_Surface.hxx>
7fd59977 27#include <GeomToStep_MakeAxis2Placement3d.hxx>
42cf5bc1 28#include <gp_Ax2.hxx>
29#include <Interface_Macros.hxx>
30#include <Interface_MSG.hxx>
31#include <Interface_Static.hxx>
32#include <MoniTool_DataMapOfShapeTransient.hxx>
33#include <OSD_Timer.hxx>
34#include <ShapeAnalysis_ShapeTolerance.hxx>
35#include <ShapeExtend_Explorer.hxx>
f117cc5a 36#include <ShapeProcess_ShapeContext.hxx>
42cf5bc1 37#include <Standard_Type.hxx>
38#include <StepBasic_ApplicationProtocolDefinition.hxx>
39#include <StepBasic_HArray1OfProduct.hxx>
40#include <STEPConstruct_AP203Context.hxx>
7fd59977 41#include <STEPConstruct_Assembly.hxx>
42#include <STEPConstruct_ContextTool.hxx>
42cf5bc1 43#include <STEPConstruct_Part.hxx>
7fd59977 44#include <STEPConstruct_UnitContext.hxx>
42cf5bc1 45#include <STEPControl_ActorWrite.hxx>
46#include <STEPControl_StepModelType.hxx>
47#include <StepData_StepModel.hxx>
48#include <StepGeom_Axis2Placement3d.hxx>
49#include <StepGeom_GeomRepContextAndGlobUnitAssCtxAndGlobUncertaintyAssCtx.hxx>
50#include <StepGeom_Point.hxx>
51#include <StepRepr_GlobalUnitAssignedContext.hxx>
52#include <StepRepr_HArray1OfRepresentationItem.hxx>
53#include <StepRepr_PropertyDefinition.hxx>
54#include <StepRepr_ShapeRepresentationRelationship.hxx>
55#include <StepShape_AdvancedBrepShapeRepresentation.hxx>
56#include <StepShape_BrepWithVoids.hxx>
57#include <StepShape_FacetedBrep.hxx>
58#include <StepShape_FacetedBrepAndBrepWithVoids.hxx>
59#include <StepShape_FacetedBrepShapeRepresentation.hxx>
60#include <StepShape_GeometricallyBoundedWireframeShapeRepresentation.hxx>
61#include <StepShape_GeometricCurveSet.hxx>
62#include <StepShape_GeometricSetSelect.hxx>
63#include <StepShape_HArray1OfGeometricSetSelect.hxx>
64#include <StepShape_ManifoldSolidBrep.hxx>
65#include <StepShape_ManifoldSurfaceShapeRepresentation.hxx>
66#include <StepShape_NonManifoldSurfaceShapeRepresentation.hxx>
67#include <StepShape_ShapeDefinitionRepresentation.hxx>
68#include <StepShape_ShapeRepresentation.hxx>
69#include <StepShape_ShellBasedSurfaceModel.hxx>
70#include <StepShape_TopologicalRepresentationItem.hxx>
71#include <StepShape_VertexPoint.hxx>
72#include <TCollection_HAsciiString.hxx>
73#include <TColStd_HSequenceOfTransient.hxx>
74#include <TopExp.hxx>
75#include <TopExp_Explorer.hxx>
76#include <TopoDS.hxx>
77#include <TopoDS_Compound.hxx>
78#include <TopoDS_Iterator.hxx>
79#include <TopoDS_Shape.hxx>
80#include <TopoDS_Solid.hxx>
7fd59977 81#include <TopoDSToStep.hxx>
82#include <TopoDSToStep_Builder.hxx>
83#include <TopoDSToStep_FacetedTool.hxx>
7fd59977 84#include <TopoDSToStep_MakeBrepWithVoids.hxx>
85#include <TopoDSToStep_MakeFacetedBrep.hxx>
86#include <TopoDSToStep_MakeFacetedBrepAndBrepWithVoids.hxx>
87#include <TopoDSToStep_MakeGeometricCurveSet.hxx>
42cf5bc1 88#include <TopoDSToStep_MakeManifoldSolidBrep.hxx>
7fd59977 89#include <TopoDSToStep_MakeShellBasedSurfaceModel.hxx>
42cf5bc1 90#include <TopoDSToStep_MakeStepVertex.hxx>
91#include <TopoDSToStep_Tool.hxx>
92#include <TopTools_HSequenceOfShape.hxx>
93#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
94#include <TopTools_ListIteratorOfListOfShape.hxx>
95#include <TopTools_ListOfShape.hxx>
96#include <TopTools_MapOfShape.hxx>
7fd59977 97#include <Transfer_Binder.hxx>
98#include <Transfer_Finder.hxx>
99#include <Transfer_FinderProcess.hxx>
42cf5bc1 100#include <Transfer_SequenceOfBinder.hxx>
101#include <Transfer_SimpleBinderOfTransient.hxx>
102#include <Transfer_TransientProcess.hxx>
7fd59977 103#include <TransferBRep.hxx>
42cf5bc1 104#include <TransferBRep_ShapeMapper.hxx>
7fd59977 105#include <UnitsMethods.hxx>
7fd59977 106#include <XSAlgo.hxx>
107#include <XSAlgo_AlgoContainer.hxx>
7fd59977 108
92efcf78 109IMPLEMENT_STANDARD_RTTIEXT(STEPControl_ActorWrite,Transfer_ActorOfFinderProcess)
110
42cf5bc1 111// Transfer
112// TransferShape
113//:d6
7fd59977 114// Non-manifold topology processing (ssv; 10.11.2010)
7fd59977 115// ============================================================================
116// Function: DumpWhatIs
0797d9d3 117// Purpose: Use it in debug mode to dump your shapes
7fd59977 118// ============================================================================
0797d9d3 119#ifdef OCCT_DEBUG
7fd59977 120static void DumpWhatIs(const TopoDS_Shape& S) {
121
122 TopTools_MapOfShape aMapOfShape;
123 aMapOfShape.Add(S);
124 TopTools_ListOfShape aListOfShape;
125 aListOfShape.Append(S);
126 TopTools_ListIteratorOfListOfShape itL(aListOfShape);
127 Standard_Integer nbSolids = 0,
128 nbShells = 0,
129 nbOpenShells = 0,
130 nbFaces = 0,
131 nbWires = 0,
132 nbEdges = 0,
133 nbVertexes = 0;
134
135 for( ; itL.More(); itL.Next() ) {
136 TopoDS_Iterator it( itL.Value() );
137 for ( ; it.More(); it.Next() ) {
138 TopoDS_Shape aSubShape = it.Value();
139 if ( !aMapOfShape.Add(aSubShape) )
140 continue;
141 aListOfShape.Append(aSubShape);
142 if (aSubShape.ShapeType() == TopAbs_SOLID)
143 nbSolids++;
144 if (aSubShape.ShapeType() == TopAbs_SHELL) {
145 if ( !aSubShape.Closed() )
146 nbOpenShells++;
147 nbShells++;
148 }
149 if (aSubShape.ShapeType() == TopAbs_FACE)
150 nbFaces++;
151 if (aSubShape.ShapeType() == TopAbs_WIRE)
152 nbWires++;
153 if (aSubShape.ShapeType() == TopAbs_EDGE)
154 nbEdges++;
155 if (aSubShape.ShapeType() == TopAbs_VERTEX)
156 nbVertexes++;
157 }
158 }
498ce76b 159
7fd59977 160 cout << "//What is?// NB SOLIDS: " << nbSolids << endl;
161 cout << "//What is?// NB SHELLS: " << nbShells << endl;
162 cout << "//What is?// OPEN SHELLS: " << nbOpenShells << endl;
163 cout << "//What is?// CLOSED SHELLS: " << nbShells - nbOpenShells << endl;
164 cout << "//What is?// NB FACES: " << nbFaces << endl;
165 cout << "//What is?// NB WIRES: " << nbWires << endl;
166 cout << "//What is?// NB EDGES: " << nbEdges << endl;
167 cout << "//What is?// NB VERTEXES: " << nbVertexes << endl;
7fd59977 168}
498ce76b 169#endif
7fd59977 170
171//=======================================================================
172// Function : IsManifoldShape
173// Purpose : Used to define whether the passed shape has manifold
174// topology or not
175//=======================================================================
176
177static Standard_Boolean IsManifoldShape(const TopoDS_Shape& theShape) {
178
179 Standard_Boolean aResult = Standard_True;
180
181 // Do not check nested Compounds
182 TopoDS_Compound aDirectShapes;
183 BRep_Builder aBrepBuilder;
184 aBrepBuilder.MakeCompound(aDirectShapes);
185
186 TopoDS_Iterator anIt(theShape);
187 for ( ; anIt.More(); anIt.Next() ) {
188 TopoDS_Shape aDirectChild = anIt.Value();
189 if (aDirectChild.ShapeType() != TopAbs_COMPOUND)
190 aBrepBuilder.Add(aDirectShapes, aDirectChild);
191 }
192
0797d9d3 193 #ifdef OCCT_DEBUG
7fd59977 194 DumpWhatIs(aDirectShapes);
195 #endif
196
197 TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
198 TopExp::MapShapesAndAncestors(aDirectShapes, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
199
200 Standard_Integer aNbEdges = aMapEdgeFaces.Extent();
0797d9d3 201 #ifdef OCCT_DEBUG
7fd59977 202 cout << "Checking whether the topology passed is manifold..." << endl;
203 #endif
204
205 // Check topology
206 for (Standard_Integer i = 1; i <= aNbEdges; i++) {
207 TopoDS_Edge aCurrentEdge = TopoDS::Edge( aMapEdgeFaces.FindKey(i) );
208 if ( !BRep_Tool::Degenerated(aCurrentEdge) ) {
209 Standard_Integer aNbAncestors = aMapEdgeFaces.FindFromIndex(i).Extent();
210 if (aNbAncestors > 2) {
211 aResult = Standard_False;
212 break;
213 }
214 }
215 }
216
0797d9d3 217 #ifdef OCCT_DEBUG
7fd59977 218 cout << "Check result: "
219 << (aResult ? "TRUE" : "FALSE") << endl;
220 #endif
221
222 return aResult;
223}
7fd59977 224
225//=======================================================================
226//function : STEPControl_ActorWrite
227//purpose :
228//=======================================================================
229
230STEPControl_ActorWrite::STEPControl_ActorWrite ()
231: mygroup (0) , mytoler (-1.)
232{
233 SetMode(STEPControl_ShellBasedSurfaceModel);
234}
235
236//=======================================================================
237//method: getNMSSRForGroup
238//purpose: allows to get NMSSR (NON_MANIFOLD_SURFACE_SHAPE_REPRESENTATION)
239// STEP's entity for the group of shells (!) passed
240//=======================================================================
241
242Handle(StepShape_NonManifoldSurfaceShapeRepresentation) STEPControl_ActorWrite::getNMSSRForGroup(const Handle(TopTools_HSequenceOfShape)& shapeGroup,
243 const Handle(Transfer_FinderProcess)& FP,
244 Standard_Boolean& isNMSSRCreated) const
245{
246 Handle(StepShape_NonManifoldSurfaceShapeRepresentation) aResult;
247
248 if ( !shapeGroup.IsNull() ) {
249 for (Standard_Integer i = 1; i <= shapeGroup->Length(); i++) {
250 TopoDS_Shape aCurrentShape = shapeGroup->Value(i);
251 Handle(TransferBRep_ShapeMapper) mapper = TransferBRep::ShapeMapper(FP, aCurrentShape);
252 if ( FP->FindTypedTransient(mapper, STANDARD_TYPE(StepShape_NonManifoldSurfaceShapeRepresentation), aResult) )
253 break;
254 }
255 }
256
257 if ( aResult.IsNull() ) {
0797d9d3 258 #ifdef OCCT_DEBUG
7fd59977 259 cout << "\nNew NMSSR created" << endl;
260 #endif
261 aResult = new StepShape_NonManifoldSurfaceShapeRepresentation;
262 isNMSSRCreated = Standard_True;
263 } else {
0797d9d3 264 #ifdef OCCT_DEBUG
7fd59977 265 cout << "\nExisting NMSSR is used" << endl;
266 #endif
267 isNMSSRCreated = Standard_False;
268 }
269
270 return aResult;
271}
272
f117cc5a 273//=======================================================================
274//function : mergeInfoForNM
275//purpose : bind already written shared faces to STEP entity for non-manifold
276//=======================================================================
277void STEPControl_ActorWrite::mergeInfoForNM(const Handle(Transfer_FinderProcess)& theFP,
278 const Handle(Standard_Transient) &theInfo) const
279{
280 Handle(ShapeProcess_ShapeContext) aContext = Handle(ShapeProcess_ShapeContext)::DownCast ( theInfo );
281 if ( aContext.IsNull() ) return;
282
283 const TopTools_DataMapOfShapeShape &aMap = aContext->Map();
284 TopTools_DataMapIteratorOfDataMapOfShapeShape aShapeShapeIt(aMap);
285
286 for ( ; aShapeShapeIt.More(); aShapeShapeIt.Next() ) {
287 TopoDS_Shape anOrig = aShapeShapeIt.Key(), aRes = aShapeShapeIt.Value();
288 if (anOrig.ShapeType() != TopAbs_FACE)
289 continue;
290
291 Handle(TransferBRep_ShapeMapper) anOrigMapper= TransferBRep::ShapeMapper ( theFP, anOrig);
292 Handle(Transfer_Binder) anOrigBinder = theFP->Find ( anOrigMapper );
293 if (anOrigBinder.IsNull())
294 continue;
295
296 Handle(TransferBRep_ShapeMapper) aResMapper = TransferBRep::ShapeMapper ( theFP, aRes );
297 theFP->Bind(aResMapper, anOrigBinder);
298 }
299}
300
7fd59977 301
302//=======================================================================
303//function : SetMode
304//purpose :
305//=======================================================================
306
307void STEPControl_ActorWrite::SetMode (const STEPControl_StepModelType M)
308{
309 switch (M) {
310 case STEPControl_AsIs : ModeTrans() = 0; break;
311 case STEPControl_ManifoldSolidBrep : ModeTrans() = 3; break;
312 case STEPControl_BrepWithVoids : ModeTrans() = 5; break;
313 case STEPControl_FacetedBrep : ModeTrans() = 1; break;
314 case STEPControl_FacetedBrepAndBrepWithVoids : ModeTrans() = 6; break;
315 case STEPControl_ShellBasedSurfaceModel : ModeTrans() = 2;
316 case STEPControl_GeometricCurveSet : ModeTrans() = 4;
317 case STEPControl_Hybrid : ModeTrans() = 0; break; // PAS IMPLEMENTE !!
318 default: break;
319 }
320}
321
322//=======================================================================
323//function : Mode
324//purpose :
325//=======================================================================
326
327STEPControl_StepModelType STEPControl_ActorWrite::Mode () const
328{
329 switch (themodetrans) {
330 case 0 : return STEPControl_AsIs;
331 case 1 : return STEPControl_FacetedBrep;
332 case 2 : return STEPControl_ShellBasedSurfaceModel;
333 case 3 : return STEPControl_ManifoldSolidBrep;
334 case 4 : return STEPControl_GeometricCurveSet;
335 case 5 : return STEPControl_BrepWithVoids;
336 case 6 : return STEPControl_FacetedBrepAndBrepWithVoids;
337 default : break;
338 }
339 return STEPControl_AsIs;
340}
341
342//=======================================================================
343//function : SetGroupMode
344//purpose :
345//=======================================================================
346
347void STEPControl_ActorWrite::SetGroupMode (const Standard_Integer mode)
348{
349 if (mode >= 0) mygroup = mode;
350}
351
352//=======================================================================
353//function : GroupMode
354//purpose :
355//=======================================================================
356
357Standard_Integer STEPControl_ActorWrite::GroupMode () const
358{
359 return mygroup;
360}
361
362//=======================================================================
363//function : SetTolerance
364//purpose :
365//=======================================================================
366
367void STEPControl_ActorWrite::SetTolerance (const Standard_Real Tol)
368{
369 mytoler = Tol;
370}
371
372//=======================================================================
373//function : Recognize
374// ATTENTION, Recognize doit s aligner sur ce que Transfer sait faire
375//purpose :
376//=======================================================================
377
378Standard_Boolean STEPControl_ActorWrite::Recognize (const Handle(Transfer_Finder)& start)
379{
380 STEPControl_StepModelType mymode = Mode();
381 Handle(TransferBRep_ShapeMapper) mapper = Handle(TransferBRep_ShapeMapper)::DownCast(start);
382 if (mapper.IsNull()) return Standard_False;
383 if (mymode == STEPControl_AsIs) return Standard_True;
384
385 Standard_Boolean yasolid = Standard_False, yashell = Standard_False,
386 yaface = Standard_False;
387
388 TopoDS_Shape theShape, aShape;
389// theShape = TopoDSToStep::DirectFaces(mapper->Value());
390 theShape = mapper->Value(); // pour une reconnaissance c est bien assez
391
392 if (theShape.ShapeType() == TopAbs_COMPOUND) {
393
394 TopExp_Explorer SolidExp, ShellExp, FaceExp;
395
396 for (SolidExp.Init(theShape, TopAbs_SOLID);
397 SolidExp.More();SolidExp.Next()) yasolid = Standard_True;
398 for (ShellExp.Init(theShape, TopAbs_SHELL, TopAbs_SOLID);
399 ShellExp.More();ShellExp.Next()) yashell = Standard_True;
400 for (FaceExp.Init(theShape, TopAbs_FACE, TopAbs_SHELL);
401 FaceExp.More();FaceExp.Next()) yaface = Standard_True;
402 }
403 else if (theShape.ShapeType() == TopAbs_SOLID) yasolid = Standard_True;
404 else if (theShape.ShapeType() == TopAbs_SHELL) yashell = Standard_True;
405 else if (theShape.ShapeType() == TopAbs_FACE) yaface = Standard_True;
406 else if (mymode != STEPControl_GeometricCurveSet) return Standard_False;
407// pour wireframe ?
408
409// Faceted : il est OBLIGATOIRE d avoir des surfaces support Plane et des
410// courbes 3D Line (pcurves ignorees)
411
412 if (mymode == STEPControl_FacetedBrep || mymode == STEPControl_FacetedBrepAndBrepWithVoids) {
413 for (TopExp_Explorer ffac(theShape,TopAbs_FACE); ffac.More(); ffac.Next()) {
414 const TopoDS_Face& F = TopoDS::Face (ffac.Current());
415 TopLoc_Location locbid;
416 Handle(Geom_Surface) surf = BRep_Tool::Surface (F,locbid);
417 if (surf.IsNull() || !surf->IsKind(STANDARD_TYPE(Geom_Plane)) ) return Standard_False;
418 }
419 for (TopExp_Explorer fedg(theShape,TopAbs_EDGE); fedg.More(); fedg.Next()) {
420 const TopoDS_Edge& E = TopoDS::Edge (fedg.Current());
421 TopLoc_Location locbid; Standard_Real first,last;
422 Handle(Geom_Curve) curv = BRep_Tool::Curve (E,locbid,first,last);
423 if (curv.IsNull() || !curv->IsKind(STANDARD_TYPE(Geom_Line)) ) return Standard_False;
424 }
425 }
426
427 switch (mymode) {
428 case STEPControl_ManifoldSolidBrep: return (yasolid || yashell);
429 case STEPControl_BrepWithVoids:
430 case STEPControl_FacetedBrep:
431 case STEPControl_FacetedBrepAndBrepWithVoids: return yasolid;
432 case STEPControl_ShellBasedSurfaceModel:
433 return (yasolid || yashell || yaface);
434 case STEPControl_GeometricCurveSet: return Standard_True; // tout OK
435 default : break;
436 }
437 return Standard_False;
438}
439
440
441// ######## MAKE PRODUCT DATA + CONTEXT ########
442
443//=======================================================================
444//function : Transfer
445//purpose :
446//=======================================================================
447
448Handle(Transfer_Binder) STEPControl_ActorWrite::Transfer (const Handle(Transfer_Finder)& start,
449 const Handle(Transfer_FinderProcess)& FP)
450{
451 XSAlgo::AlgoContainer()->PrepareForTransfer();
452
453 Handle(TransferBRep_ShapeMapper) mapper = Handle(TransferBRep_ShapeMapper)::DownCast(start);
454
455 if (mapper.IsNull()) return NullResult();
456 TopoDS_Shape shape = mapper->Value();
457
458 // init context
459 Handle(StepData_StepModel) model = Handle(StepData_StepModel)::DownCast ( FP->Model() );
460 if ( ! model.IsNull() ) myContext.SetModel ( model ); //: abv 04.11.00: take APD from model
461 myContext.AddAPD ( Standard_False ); // update APD
462 myContext.SetLevel ( 1 ); // set assembly level to 1 (to ensure)
463
464 //:S4136: init UnitsMethods to reset angle unit factors (see TopoDSToStep)
465 Standard_Real lFactor = UnitsMethods::GetLengthFactorValue ( Interface_Static::IVal ( "write.step.unit" ) );
466 lFactor /= UnitsMethods::GetCasCadeLengthUnit();
467 Standard_Integer anglemode = Interface_Static::IVal("step.angleunit.mode");
c6541a0c 468 UnitsMethods::InitializeFactors ( lFactor, ( anglemode <= 1 ? 1. : M_PI/180. ), 1. );
7fd59977 469
470 // create SDR
471 STEPConstruct_Part SDRTool;
472 SDRTool.MakeSDR ( 0, myContext.GetProductName(), myContext.GetAPD()->Application() );
473 Handle(StepShape_ShapeDefinitionRepresentation) sdr = SDRTool.SDRValue();
474 // transfer shape
475
476 Handle(Transfer_Binder) resbind = TransferShape (mapper,sdr,FP);
477
478// Handle(StepShape_ShapeRepresentation) resultat;
479// FP->GetTypedTransient (resbind,STANDARD_TYPE(StepShape_ShapeRepresentation),resultat);
480// sdr->SetUsedRepresentation (resultat);
481
482 // create binder with all root entities produced from shape
483 Handle(TColStd_HSequenceOfTransient) roots = myContext.GetRootsForPart ( SDRTool );
484 Handle(Transfer_Binder) resprod = TransientResult ( myContext.GetAPD() );
485 for ( Standard_Integer i=1; i <= roots->Length(); i++ )
486 resprod->AddResult ( TransientResult ( roots->Value(i) ) );
487 resprod->AddResult(resbind);
488
489 // bind and exit
490 //FP->Bind (mapper,resprod);
491 myContext.NextIndex();
492 return resprod;
493}
494
495//==========================================
496
497static Standard_Real UsedTolerance (const Standard_Real mytoler,
498 const TopoDS_Shape& theShape)
499{
500
501 // COMPUTING 3D TOLERANCE
502 // Either from Session, or Computed (Least,Average, or Greatest)
503 // Then given to TopoDSToStep_Tool
504
505 Standard_Real Tol = mytoler;
506 Standard_Integer tolmod = Interface_Static::IVal("write.precision.mode");
507 if (Tol <= 0 && tolmod == 2) Tol =
508 Interface_Static::RVal("write.precision.val");
509 if (Tol <= 0) {
510 ShapeAnalysis_ShapeTolerance stu;
511 Tol = stu.Tolerance (theShape,tolmod);
512 // Par defaut, on prend une tolerance moyenne, on elimine les aberrations
513 Tol = Interface_MSG::Intervalled (Tol * 1.5); // arrondi a 1 2 5 ...
514 }
515 if (Tol == 0) Tol = 1.e-07; // minimum ...
516
517 return Tol;
518}
519
520//=======================================================================
521//function : IsAssembly
522//purpose :
523//=======================================================================
524// if GroupMode is >1 downgrades all compounds having single subshape to that
525// subshape
526
527Standard_Boolean STEPControl_ActorWrite::IsAssembly (TopoDS_Shape &S) const
528{
529 if ( ! GroupMode() || S.ShapeType() != TopAbs_COMPOUND ) return Standard_False;
530 // PTV 16.09.2002 OCC725 for storing compound of vertices
1fa7cb8c 531 if (Interface_Static::IVal("write.step.vertex.mode") == 0) {//bug 23950
532 if (S.ShapeType() == TopAbs_COMPOUND ) {
533 Standard_Boolean IsOnlyVertices = Standard_True;
534 TopoDS_Iterator anItr( S );
535 for ( ; anItr.More(); anItr.Next() ) {
536 if ( anItr.Value().ShapeType() != TopAbs_VERTEX ) {
537 IsOnlyVertices = Standard_False;
538 break;
539 }
7fd59977 540 }
1fa7cb8c 541 if ( IsOnlyVertices )
542 return Standard_False;
7fd59977 543 }
7fd59977 544 }
545 if ( GroupMode() ==1 ) return Standard_True;
546 TopoDS_Iterator it ( S );
547 if ( ! it.More() ) return Standard_False;
548 TopoDS_Shape shape = it.Value();
549 it.Next();
550 if ( it.More() ) return Standard_True;
551 S = shape;
552 return IsAssembly ( S );
553}
554
555//=======================================================================
556//function : TransferShape
557//purpose :
558//=======================================================================
559
560/*
561static void UpdateMap (const TopoDS_Shape &shape,
562 BRepTools_Modifier &M1,
563 BRepTools_Modifier &M2,
564 const Handle(Transfer_FinderProcess) &FinderProcess)
565{
566 TopoDS_Shape S = M1.ModifiedShape ( shape );
567 S = M2.ModifiedShape ( S );
568 if ( S == shape ) return;
569
570 Handle(TransferBRep_ShapeMapper) mapper = TransferBRep::ShapeMapper ( FinderProcess, S );
571 Handle(Transfer_Binder) binder = FinderProcess->Find ( mapper );
572 if ( ! binder.IsNull() ) {
573 mapper = TransferBRep::ShapeMapper ( FinderProcess, shape );
574 FinderProcess->Bind ( mapper, binder );
575 }
576
577 for ( TopoDS_Iterator it(shape); it.More(); it.Next() )
578 UpdateMap ( it.Value(), M1, M2, FinderProcess );
579}
580*/
581
582// PTV 16.09.2002 added for transfering vertices.
583static Standard_Boolean transferVertex (const Handle(Transfer_FinderProcess)& FP,
584 Handle(StepShape_HArray1OfGeometricSetSelect)& aGSS,
585 const TopoDS_Shape& aShVrtx,
586 const Standard_Integer theNum)
587{
588 Standard_Boolean IsDone = Standard_False;
589 MoniTool_DataMapOfShapeTransient aMap;
590 TopoDSToStep_Tool aTool(aMap, Standard_True);
591 TopoDSToStep_MakeStepVertex aMkVrtx ( TopoDS::Vertex(aShVrtx), aTool, FP );
592
593 if (!aMkVrtx.IsDone())
594 return IsDone;
595
596 Handle(StepShape_VertexPoint) aVP =
597 Handle(StepShape_VertexPoint)::DownCast(aTool.Find(aShVrtx));
598 if (aVP.IsNull())
599 return IsDone;
600
601 StepShape_GeometricSetSelect select;
602 select.SetValue(aVP->VertexGeometry());
603 // add current result
604 aGSS->SetValue( theNum, select );
605 IsDone = Standard_True;
606 return IsDone;
607}
608
609
610Handle(Transfer_Binder) STEPControl_ActorWrite::TransferShape (const Handle(Transfer_Finder)& start,
611 const Handle(StepShape_ShapeDefinitionRepresentation)& SDR0,
612 const Handle(Transfer_FinderProcess)& FP,
613 const Handle(TopTools_HSequenceOfShape)& shapeGroup,
614 const Standard_Boolean isManifold)
615{
616 STEPControl_StepModelType mymode = Mode();
617 Handle(TransferBRep_ShapeMapper) mapper = Handle(TransferBRep_ShapeMapper)::DownCast(start);
618 Handle(Transfer_Binder) binder;
619
620 // Indicates whether to use an exising NMSSR to write items to (ss; 13.11.2010)
621 Standard_Boolean useExistingNMSSR = Standard_False;
622
623 if (mapper.IsNull()) return binder;
624 TopoDS_Shape theShape = mapper->Value();
625
626 if (theShape.IsNull()) return binder;
627
628 // INDIVIDUAL SHAPE ALREADY TRANSFERRED : RETURN IT !
629 binder = FP->Find(start);
630 if (!binder.IsNull()) { if (!binder->HasResult()) binder.Nullify(); }
631 if (!binder.IsNull()) {
632 //:abv 20.05.02: writing box & face from it (shared) in one compound
633 // as assembly - while face already translated, it should be
634 // re-translated to break sharing
0797d9d3 635#ifdef OCCT_DEBUG
7fd59977 636 cout << "Warning: STEPControl_ActorWrite::TransferShape(): shape already translated" << endl;
637#endif
638// return binder;
639 }
640
641 // MODE ASSEMBLY : if Compound, (sub-)assembly
642 if ( IsAssembly(theShape) )
643 return TransferCompound(start, SDR0, FP);
644
645 // [BEGIN] Separate manifold topology from non-manifold in group mode 0 (ssv; 18.11.2010)
dde68833 646 Standard_Boolean isNMMode = Interface_Static::IVal("write.step.nonmanifold") != 0;
7fd59977 647 Handle(Transfer_Binder) aNMBinder;
648 if (isNMMode && !GroupMode() && theShape.ShapeType() == TopAbs_COMPOUND) {
649 TopoDS_Compound aNMCompound;
650 TopoDS_Compound aManifoldCompound;
651 BRep_Builder brepBuilder;
652
653 // Create empty Compounds
654 brepBuilder.MakeCompound(aManifoldCompound);
655 brepBuilder.MakeCompound(aNMCompound);
656
657 // Indicates whether there is only non-manifold topology detected
658 // (there is no manifold topology found in the Compound passed)
659 Standard_Boolean isOnlyNonManifold = Standard_False;
660
661 // Find a Compound containing non-manifold topology.
662 // NOTE: only one such Compound must exist in the entire Compound passed
663 if ( !IsManifoldShape(theShape) ) {
664 aNMCompound = TopoDS::Compound(theShape);
665 isOnlyNonManifold = Standard_True;
666 }
667 else {
668 TopTools_ListOfShape aListOfShapes;
669 TopTools_ListOfShape aListOfManifoldShapes;
670 aListOfShapes.Append(theShape);
671
672 TopTools_ListIteratorOfListOfShape itL(aListOfShapes);
673 for ( ; itL.More(); itL.Next() ) {
674 TopoDS_Shape aParentShape = itL.Value();
675 TopoDS_Iterator it(aParentShape);
676 for ( ; it.More(); it.Next() ) {
677 TopoDS_Shape aSubShape = it.Value();
678 if (aSubShape.ShapeType() == TopAbs_COMPOUND && !IsManifoldShape(aSubShape) )
679 aNMCompound = TopoDS::Compound(aSubShape);
680 else if (aSubShape.ShapeType() == TopAbs_COMPOUND)
681 aListOfShapes.Append(aSubShape);
682 else
683 aListOfManifoldShapes.Append(aSubShape);
684 }
685 }
686
687 // Group manifold topology together.
688 // NOTE: there is no sense that initial Compound structure was lost as
689 // group mode is set to 0 (no Assemblies are mapped)
690 for ( itL.Initialize(aListOfManifoldShapes); itL.More(); itL.Next() ) {
691 TopoDS_Shape aCurrentManiShape = itL.Value();
692 brepBuilder.Add(aManifoldCompound, aCurrentManiShape);
693 }
694
695 }
696
697 // Process only manifold topology in the current TransferShape invocation.
698 // Invoke TransferShape for non-manifold topology separately (see below)
699 theShape = aManifoldCompound;
700
701 // List of items to transfer
702 Handle(TopTools_HSequenceOfShape) RepItemSeq = new TopTools_HSequenceOfShape();
703 // Non-manifold group to pass into TransferShape with each shape from RepItemSeq
704 Handle(TopTools_HSequenceOfShape) NonManifoldGroup = new TopTools_HSequenceOfShape();
705
706 // Transfer Solids to closed Shells. Prepare RepItemSeq & NonManifoldGroup
707 for ( TopoDS_Iterator iter(aNMCompound); iter.More(); iter.Next() ) {
708 TopoDS_Shape aSubShape = iter.Value();
709 if (aSubShape.ShapeType() == TopAbs_SOLID) {
710 for ( TopoDS_Iterator aSubIter(aSubShape); aSubIter.More(); aSubIter.Next() ) {
711 TopoDS_Shell aSubShell = TopoDS::Shell( aSubIter.Value() );
712 aSubShell.Closed(Standard_True);
713 RepItemSeq->Append(aSubShell);
714 NonManifoldGroup->Append(aSubShell);
715 }
716 }
717 else if (!isManifold && (aSubShape.ShapeType() == TopAbs_SHELL) ) {
718 RepItemSeq->Append(aSubShape);
719 NonManifoldGroup->Append(aSubShape);
720 }
721 else
722 RepItemSeq->Append( iter.Value() );
723 }
724
725 Standard_Integer aNMItemsNb = RepItemSeq->Length();
726
727 // In case of pure manifold topology do nothing; theShape is processed as usual (see below)
728 if (aNMItemsNb > 0) {
729
730 // Prepare SDR for non-manifold group. This SDR will be linked to NMSSR by means
731 // of TransferShape invocation. SDR is not created if there is no any manifold
732 // topology in the passed Compound. If topology is pure non-manifold, SDR0 (passed)
733 // is used
734 Handle(StepShape_ShapeDefinitionRepresentation) sdr;
735 if (isOnlyNonManifold)
736 sdr = SDR0;
737 else {
738 STEPConstruct_Part SDRTool;
739 SDRTool.MakeSDR( 0, myContext.GetProductName(), myContext.GetAPD()->Application() );
740 sdr = SDRTool.SDRValue();
741 }
742
743 aNMBinder = TransientResult(sdr);
744
745 // Complete SDR with shape representations.
746 // NOTE: aNMBinder is connected now with this SDR. It will be added to the resulting
747 // binder in the end of this invocation of TransferShape
748 for (Standard_Integer i = 1; i <= aNMItemsNb; i++) {
51740958 749 Handle(TransferBRep_ShapeMapper) aMapper = TransferBRep::ShapeMapper( FP, RepItemSeq->Value(i) );
750 TransferShape(aMapper, sdr, FP, NonManifoldGroup, Standard_False);
7fd59977 751 }
752
753 // Nothing else needed for pure non-manifold topology, return
754 if (isOnlyNonManifold)
755 return aNMBinder;
756
757 }
758
759 }
760 // [END] Separate manifold topology from non-manifold in group mode 0 (ssv; 18.11.2010)
761
762 // create a list of items to translate
763 Handle(TopTools_HSequenceOfShape) RepItemSeq = new TopTools_HSequenceOfShape();
764
1fa7cb8c 765 Standard_Boolean isSeparateVertices =
766 Interface_Static::IVal("write.step.vertex.mode") == 0;//bug 23950
7fd59977 767 // PTV 16.09.2002 OCC725 separate shape from solo vertices.
66d6976f 768 Standard_Boolean isOnlyVertices = Standard_False;
7fd59977 769 if (theShape.ShapeType() == TopAbs_COMPOUND) {
770 Standard_Integer countVrtx = 0;
771 Standard_Integer countSh = 0;
772 TopoDS_Compound aNewShape, aCompOfVrtx;
773 BRep_Builder aB;
774 aB.MakeCompound(aNewShape);
775 aB.MakeCompound(aCompOfVrtx);
776 TopoDS_Iterator anCompIt(theShape);
1fa7cb8c 777 if (isSeparateVertices) {
778 for (; anCompIt.More(); anCompIt.Next()) {
779 TopoDS_Shape aCurSh = anCompIt.Value();
780 if (aCurSh.ShapeType() != TopAbs_VERTEX) {
781 aB.Add(aNewShape, aCurSh);
782 countSh++;
783 }
784 else {
785 aB.Add(aCompOfVrtx, aCurSh);
786 countVrtx++;
787 }
7fd59977 788 }
1fa7cb8c 789 // replace the shapes
790 if (countSh)
791 theShape = aNewShape;
792 if (countVrtx)
793 RepItemSeq->Append(aCompOfVrtx);
794 if (countSh == 0)
795 isOnlyVertices = Standard_True;
7fd59977 796 }
7fd59977 797 }
7fd59977 798
7fd59977 799 if (theShape.ShapeType() == TopAbs_COMPOUND) {
800 TopExp_Explorer SolidExp, ShellExp, FaceExp;
801 if (mymode != STEPControl_GeometricCurveSet) {
802 for (SolidExp.Init(theShape, TopAbs_SOLID);
803 SolidExp.More();SolidExp.Next()) {
804 RepItemSeq->Append(TopoDS::Solid(SolidExp.Current()));
805 }
806 for (ShellExp.Init(theShape, TopAbs_SHELL, TopAbs_SOLID);
807 ShellExp.More();ShellExp.Next()) {
808 RepItemSeq->Append(TopoDS::Shell(ShellExp.Current()));
809 }
810
811 for (FaceExp.Init(theShape, TopAbs_FACE, TopAbs_SHELL);
812 FaceExp.More();FaceExp.Next()) {
813 RepItemSeq->Append(TopoDS::Face(FaceExp.Current()));
814 }
815 }
816 else {
66d6976f 817 if (!isOnlyVertices)
818 RepItemSeq->Append(theShape); //:j1
7fd59977 819 }
820 if(mymode == STEPControl_AsIs) {
821 TopExp_Explorer WireExp, EdgeExp;
822 for (WireExp.Init(theShape, TopAbs_WIRE, TopAbs_FACE);
823 WireExp.More();WireExp.Next())
824 RepItemSeq->Append(TopoDS::Wire(WireExp.Current()));
825 for (EdgeExp.Init(theShape, TopAbs_EDGE, TopAbs_WIRE);
826 EdgeExp.More();EdgeExp.Next())
827 RepItemSeq->Append(TopoDS::Edge(EdgeExp.Current()));
828 }
829
830 }
831 else if (theShape.ShapeType() == TopAbs_SOLID) {
832 RepItemSeq->Append(TopoDS::Solid(theShape));
833 }
834 else if (theShape.ShapeType() == TopAbs_SHELL) {
835 RepItemSeq->Append(TopoDS::Shell(theShape));
836 }
837 else if (theShape.ShapeType() == TopAbs_FACE) {
838 RepItemSeq->Append(TopoDS::Face(theShape));
839 }
846c92e0 840 else if (theShape.ShapeType() == TopAbs_COMPSOLID) {
841 FP->AddWarning(start,"NonManifold COMPSOLID was translated like a set of SOLIDs");
842 if ( GroupMode() > 0)
843 return TransferCompound(start, SDR0, FP);
844 else {
845 TopExp_Explorer SolidExp;
846 for (SolidExp.Init(theShape, TopAbs_SOLID);
847 SolidExp.More();SolidExp.Next()) {
848 RepItemSeq->Append(TopoDS::Solid(SolidExp.Current()));
849 }
850 }
851 }
852
7fd59977 853 else if (mymode != STEPControl_GeometricCurveSet && mymode != STEPControl_AsIs) {
854 FP->AddFail(start,"The Shape is not a SOLID, nor a SHELL, nor a FACE");
855 return binder;
856 }
857 else RepItemSeq->Append (theShape);
858
859 // COMPUTING 3D TOLERANCE
860 // Either from Session, or Computed (Least,Average, or Greatest)
861 // Then given to TopoDSToStep_Tool
862 Standard_Real Tol = UsedTolerance (mytoler,theShape);
863
864 // Create a STEP-Entity for each TopoDS_Shape
865 // according to the current StepModelMode
866
867 Standard_Integer nbs = RepItemSeq->Length();
868 Handle(TColStd_HSequenceOfTransient) ItemSeq =
869 new TColStd_HSequenceOfTransient();
870
871//ptv 10.11.00: allow to write empty Compound: if (GroupMode() >0)
872 ItemSeq->Append (myContext.GetDefaultAxis());
873 STEPControl_StepModelType trmode = mymode;
874 for (Standard_Integer i = 1; i <= nbs; i++) {
875 TopoDS_Shape xShape = RepItemSeq->Value(i);
876
877 if(mymode == STEPControl_AsIs) {
878 switch(xShape.ShapeType()) {
879 case TopAbs_SOLID : trmode = STEPControl_ManifoldSolidBrep;break;
880 case TopAbs_SHELL : trmode = STEPControl_ShellBasedSurfaceModel; break;
881 case TopAbs_FACE : trmode = STEPControl_ShellBasedSurfaceModel;break;
882 default : trmode =STEPControl_GeometricCurveSet; break;
883 }
884 }
885 //:abv 24Jan99 CAX-IF TRJ3: expanded Shape Processing
886// TopoDS_Shape aShape = xShape;
887 // eliminate conical surfaces with negative semiangles
888// Handle(TopoDSToStep_ConicalSurfModif) CSM = new TopoDSToStep_ConicalSurfModif();
889// BRepTools_Modifier CSMT(aShape,CSM);
890// if ( CSMT.IsDone() ) aShape = CSMT.ModifiedShape ( aShape );
891// // eliminate indirect elementary surfaces
892// Handle(TopoDSToStep_DirectModification) DM = new TopoDSToStep_DirectModification();
893// BRepTools_Modifier DMT(aShape,DM);
894// if ( DMT.IsDone() ) aShape = DMT.ModifiedShape ( aShape );
895//// aShape = TopoDSToStep::DirectFaces(xShape);
896 Handle(Standard_Transient) info;
897 Standard_Real maxTol = Interface_Static::RVal("read.maxprecision.val");
898
7fd59977 899 TopoDS_Shape aShape;
f117cc5a 900 aShape = XSAlgo::AlgoContainer()->ProcessShape(xShape, Tol, maxTol,
901 "write.step.resource.name",
902 "write.step.sequence", info,
903 FP->GetProgress() );
904 if (!isManifold) {
905 mergeInfoForNM(FP, info);
906 }
907
7fd59977 908 // create a STEP entity corresponding to shape
909 Handle(StepGeom_GeometricRepresentationItem) item;
910 switch (trmode)
911 {
912 case STEPControl_ManifoldSolidBrep:
913 {
914 if (aShape.ShapeType() == TopAbs_SOLID) {
915 TopoDS_Solid aSolid = TopoDS::Solid(aShape);
916
917 //:d6 abv 13 Mar 98: if solid has more than 1 shell,
918 // try to treat it as solid with voids
919 Standard_Integer nbShells = 0;
920 for ( TopoDS_Iterator It ( aSolid ); It.More(); It.Next() )
921 if (It.Value().ShapeType() == TopAbs_SHELL) nbShells++;
922 if ( nbShells >1 ) {
923 TopoDSToStep_MakeBrepWithVoids MkBRepWithVoids(aSolid,FP);
924 MkBRepWithVoids.Tolerance() = Tol;
925 if (MkBRepWithVoids.IsDone()) {
926 item = MkBRepWithVoids.Value();
927 }
928 else nbShells = 1; //smth went wrong; let it will be just Manifold
929 }
930 if ( nbShells ==1 ) {
931
932 TopoDSToStep_MakeManifoldSolidBrep MkManifoldSolidBrep(aSolid,FP);
933 MkManifoldSolidBrep.Tolerance() = Tol;
934 if (MkManifoldSolidBrep.IsDone()) {
935 item = MkManifoldSolidBrep.Value();
936 }
937 }
938 }
939 else if (aShape.ShapeType() == TopAbs_SHELL) {
940 TopoDS_Shell aShell = TopoDS::Shell(aShape);
941 TopoDSToStep_MakeManifoldSolidBrep MkManifoldSolidBrep(aShell,FP);
942 MkManifoldSolidBrep.Tolerance() = Tol;
943 if (MkManifoldSolidBrep.IsDone()) {
944 item = MkManifoldSolidBrep.Value();
945 }
946 }
947 break;
948 }
949 case STEPControl_BrepWithVoids:
950 {
951 if (aShape.ShapeType() == TopAbs_SOLID) {
952 TopoDS_Solid aSolid = TopoDS::Solid(aShape);
953 TopoDSToStep_MakeBrepWithVoids MkBRepWithVoids(aSolid,FP);
954 MkBRepWithVoids.Tolerance() = Tol;
955 if (MkBRepWithVoids.IsDone()) {
956 item = MkBRepWithVoids.Value();
957 }
958 }
959 break;
960 }
961 case STEPControl_FacetedBrep:
962 {
963 TopoDSToStep_FacetedError facErr = TopoDSToStep_FacetedTool::CheckTopoDSShape(aShape);
964 if (facErr != TopoDSToStep_FacetedDone) {
965 FP->AddFail(start,"Error in Faceted Shape from TopoDS");
966 if (facErr == TopoDSToStep_SurfaceNotPlane) {
967 FP->AddFail(start,"-- The TopoDS_Face is not plane");
968 }
969 else if (facErr == TopoDSToStep_PCurveNotLinear) {
970 FP->AddFail(start,"-- The Face contains non linear PCurves");
971 }
972 return binder;
973 }
974 if (aShape.ShapeType() == TopAbs_SOLID) {
975 TopoDS_Solid aSolid = TopoDS::Solid(aShape);
976 TopoDSToStep_MakeFacetedBrep MkFacetedBrep(aSolid,FP);
977 MkFacetedBrep.Tolerance() = Tol;
978 if (MkFacetedBrep.IsDone()) {
979 item = MkFacetedBrep.Value();
980 }
981 }
982 break;
983 }
984 case STEPControl_FacetedBrepAndBrepWithVoids:
985 {
986 TopoDSToStep_FacetedError facErr = TopoDSToStep_FacetedTool::CheckTopoDSShape(aShape);
987 if (facErr != TopoDSToStep_FacetedDone) {
988 FP->AddFail(start,"Error in Faceted Shape from TopoDS");
989 if (facErr == TopoDSToStep_SurfaceNotPlane) {
990 FP->AddFail(start,"-- The TopoDS_Face is not plane");
991 }
992 else if (facErr == TopoDSToStep_PCurveNotLinear) {
993 FP->AddFail(start,"-- The Face contains non linear PCurves");
994 }
995 return binder;
996 }
997 if (aShape.ShapeType() == TopAbs_SOLID) {
998 TopoDS_Solid aSolid = TopoDS::Solid(aShape);
999 TopoDSToStep_MakeFacetedBrepAndBrepWithVoids
1000 MkFacetedBrepAndBrepWithVoids(aSolid,FP);
1001 MkFacetedBrepAndBrepWithVoids.Tolerance() = Tol;
1002 if (MkFacetedBrepAndBrepWithVoids.IsDone()) {
1003 item = MkFacetedBrepAndBrepWithVoids.Value();
1004 }
1005 }
1006 break;
1007 }
1008 case STEPControl_ShellBasedSurfaceModel:
1009 {
1010 if (aShape.ShapeType() == TopAbs_SOLID) {
1011 TopoDS_Solid aSolid = TopoDS::Solid(aShape);
1012 TopoDSToStep_MakeShellBasedSurfaceModel
1013 MkShellBasedSurfaceModel(aSolid, FP);
1014 MkShellBasedSurfaceModel.Tolerance() = Tol;
1015 if (MkShellBasedSurfaceModel.IsDone()) {
1016 item = MkShellBasedSurfaceModel.Value();
1017 }
1018 }
1019 else if (aShape.ShapeType() == TopAbs_SHELL) {
1020 TopoDS_Shell aShell = TopoDS::Shell(aShape);
1021 // Non-manifold topology is stored via NMSSR containing series of SBSM (ssv; 13.11.2010)
1022 TopoDSToStep_MakeShellBasedSurfaceModel MkShellBasedSurfaceModel(aShell, FP);
1023 MkShellBasedSurfaceModel.Tolerance() = Tol;
1024 if (MkShellBasedSurfaceModel.IsDone()) {
1025 item = MkShellBasedSurfaceModel.Value();
1026 }
1027 }
1028 else if (aShape.ShapeType() == TopAbs_FACE) {
1029 TopoDS_Face aFace = TopoDS::Face(aShape);
1030 TopoDSToStep_MakeShellBasedSurfaceModel
1031 MkShellBasedSurfaceModel(aFace, FP);
1032 MkShellBasedSurfaceModel.Tolerance() = Tol;
1033 if (MkShellBasedSurfaceModel.IsDone()) {
1034 item = MkShellBasedSurfaceModel.Value();
1035 }
1036 }
1037 break;
1038 }
1039 case STEPControl_GeometricCurveSet:
1040 {
1041 TopoDSToStep_MakeGeometricCurveSet MkGeometricCurveSet(aShape,FP);
1042 MkGeometricCurveSet.Tolerance() = Tol;
1043 if (MkGeometricCurveSet.IsDone()) {
1044 item = MkGeometricCurveSet.Value();
1045 }
1046 // PTV 22.08.2002 OCC609 ------------------------- begin --------------------
1047 // modified by PTV 16.09.2002 OCC725
1048 else if (aShape.ShapeType() == TopAbs_COMPOUND ||
1049 aShape.ShapeType() == TopAbs_VERTEX) {
1050 // it is compund with solo vertices.
1051 Standard_Integer aNbVrtx = 0;
1052 Standard_Integer curNb = 0;
1053 TopExp_Explorer anExp (aShape, TopAbs_VERTEX);
1054 for ( ; anExp.More(); anExp.Next() ) {
1055 if ( anExp.Current().ShapeType() != TopAbs_VERTEX )
1056 continue;
1057 aNbVrtx++;
1058 }
1059 if ( aNbVrtx ) {
1060 // create new geometric curve set for all vertices
1061 Handle(StepShape_HArray1OfGeometricSetSelect) aGSS =
1062 new StepShape_HArray1OfGeometricSetSelect(1,aNbVrtx);
1063 Handle(TCollection_HAsciiString) empty = new TCollection_HAsciiString("");
1064 Handle(StepShape_GeometricCurveSet) aGCSet =
1065 new StepShape_GeometricCurveSet;
1066 aGCSet->SetName(empty);
1067 // iterates on compound with vertices and trances each vertex
1068 for ( anExp.ReInit() ; anExp.More(); anExp.Next() ) {
1069 TopoDS_Shape aVertex = anExp.Current();
1070 if ( aVertex.ShapeType() != TopAbs_VERTEX )
1071 continue;
1072 curNb++;
1073 transferVertex (FP, aGSS, aVertex, curNb);
1074 } // end of iteration on compound with vertices.
1075 aGCSet->SetElements(aGSS);
1076 item = aGCSet;
1077 } // end of check that number of vertices is not null
1078 }
1079 // PTV 22.08.2002 OCC609------------------------- end --------------------
1080 break;
1081 }
1082 default: break;
1083 }
1084 if ( item.IsNull() ) continue;
1085
1086 // add resulting item to the FP
1087 ItemSeq->Append(item);
1088 Handle(TransferBRep_ShapeMapper) submapper;
1089 if ( xShape.IsSame ( mapper->Value() ) )
1090 submapper = Handle(TransferBRep_ShapeMapper)::DownCast ( start );
1091 if ( submapper.IsNull() ) submapper = TransferBRep::ShapeMapper (FP,xShape);
1092 Handle(Transfer_Binder) subbind = FP->Find ( submapper );
1093 if ( subbind.IsNull() ) {
1094 subbind = TransientResult ( item );
1095 FP->Bind ( submapper, subbind );
1096 }
1097 else subbind->AddResult ( TransientResult ( item ) );
1098
1099 //:abv 24Jan99 CAX-IF TRJ3: Update FinderProcess map to take into account shape processing
1100// UpdateMap ( xShape, CSMT, DMT, FP );
1101 XSAlgo::AlgoContainer()->MergeTransferInfo(FP, info);
1102 }
1103
1104 // - Make Shape Representation
1105 Standard_Integer nCc1 = ItemSeq->Length();
1106 if (nCc1 < 1) {
1107 FP->AddFail(start,"The Shape has not the appropriate type");
1108 return binder;
1109 }
1110 Handle(StepShape_ShapeRepresentation) shapeRep;
1111 if ( theShape.ShapeType() == TopAbs_SHAPE ) { // for external references
1112 shapeRep = new StepShape_ShapeRepresentation;
1113 }
1114 else {
1115 switch (mymode) {
1116 case STEPControl_ManifoldSolidBrep:
1117 shapeRep = new StepShape_AdvancedBrepShapeRepresentation;
1118 break;
1119 case STEPControl_FacetedBrep:
1120 shapeRep = new StepShape_FacetedBrepShapeRepresentation;
1121 break;
1122 // NOTE: STEPControl_AsIs mode is normally used to transfer non-manifold topology.
1123 // However, as ShellBasedSurfaceModel is used in non-manifold processing
1124 // internally, STEPControl_ShellBasedSurfaceModel is also adjusted to
1125 // be able to work with non-manifold cases
1126 case STEPControl_ShellBasedSurfaceModel:
1127 if (isManifold)
1128 shapeRep = new StepShape_ManifoldSurfaceShapeRepresentation;
1129 else {
1130 Standard_Boolean isNewNMSSRCreated;
1131 shapeRep = this->getNMSSRForGroup(shapeGroup, FP, isNewNMSSRCreated);
1132 useExistingNMSSR = !isNewNMSSRCreated;
1133 }
1134 break;
1135 case STEPControl_GeometricCurveSet:
1136 shapeRep = new StepShape_GeometricallyBoundedWireframeShapeRepresentation;
1137 break;
1138 case STEPControl_AsIs :
1139 {
1140 if(nbs == 1) {
1141 if(trmode == STEPControl_ManifoldSolidBrep)
1142 shapeRep = new StepShape_AdvancedBrepShapeRepresentation;
1143 else if(trmode == STEPControl_ShellBasedSurfaceModel)
1144 // Process non-manifold topology separately (ssv; 13.11.2010)
1145 if (isManifold)
1146 shapeRep = new StepShape_ManifoldSurfaceShapeRepresentation;
1147 else {
1148 Standard_Boolean isNewNMSSRCreated;
1149 shapeRep = this->getNMSSRForGroup(shapeGroup, FP, isNewNMSSRCreated);
1150 useExistingNMSSR = !isNewNMSSRCreated;
1151 }
1152 else if(trmode == STEPControl_GeometricCurveSet)
1153 shapeRep = new StepShape_GeometricallyBoundedWireframeShapeRepresentation;
1154 else if(trmode ==STEPControl_FacetedBrep)
1155 shapeRep = new StepShape_FacetedBrepShapeRepresentation;
1156 }
1157 else shapeRep = new StepShape_ShapeRepresentation;
1158 }
1159 break;
1160 default: break;
1161 }
1162 }
1163 if(shapeRep.IsNull()) {
1164 Handle(Transfer_Binder) resb;
1165 return resb;
1166 }
1167
1168 Handle(StepRepr_HArray1OfRepresentationItem) items =
1169 new StepRepr_HArray1OfRepresentationItem(1,nCc1);
1170
1171 for (Standard_Integer rep = 1; rep <= nCc1; rep++) {
1172 Handle(StepRepr_RepresentationItem) repit =
1173 GetCasted(StepRepr_RepresentationItem, ItemSeq->Value(rep));
1174 items->SetValue(rep,repit);
1175 }
1176 Standard_Integer ap = Interface_Static::IVal("write.step.schema");
1177 Transfer_SequenceOfBinder aSeqBindRelation;
1178 if(ap == 3 && nbs > 1) {
1179 Standard_Integer j = 1;
1180 if(items->Value(j)->IsKind(STANDARD_TYPE(StepGeom_Axis2Placement3d))) {
1181 Handle(StepRepr_HArray1OfRepresentationItem) axis =
1182 new StepRepr_HArray1OfRepresentationItem(1,1);
1183 axis->SetValue(1,items->Value(j++));
1184 shapeRep->SetItems(axis);
1185 }
1186 for (; j <= items->Length(); j++) {
1187
1188 Handle(StepShape_ShapeRepresentation) ShapeRepr1;
1189 if(items->Value(j)->IsKind(STANDARD_TYPE(StepShape_ManifoldSolidBrep)))
1190 ShapeRepr1 = new StepShape_AdvancedBrepShapeRepresentation;
1191 else if(items->Value(j)->IsKind(STANDARD_TYPE(StepShape_ShellBasedSurfaceModel)))
1192 ShapeRepr1 = new StepShape_ManifoldSurfaceShapeRepresentation;
1193 else if(items->Value(j)->IsKind(STANDARD_TYPE(StepShape_GeometricCurveSet)))
1194 ShapeRepr1 = new StepShape_GeometricallyBoundedWireframeShapeRepresentation;
1195 else if (items->Value(j)->IsKind(STANDARD_TYPE(StepShape_FacetedBrep)))
1196 ShapeRepr1 = new StepShape_FacetedBrepShapeRepresentation;
1197 else ShapeRepr1 = new StepShape_ShapeRepresentation;
1198
1199 Handle(StepRepr_HArray1OfRepresentationItem) repr1 = new StepRepr_HArray1OfRepresentationItem(1,2);
1200 repr1->SetValue(1,myContext.GetDefaultAxis());
1201 repr1->SetValue(2,items->Value(j));
1202 ShapeRepr1->SetItems(repr1);
1203 STEPConstruct_UnitContext mk1;
1204 mk1.Init(Tol);
1205 ShapeRepr1->SetContextOfItems(mk1.Value()); // la tolerance, voir au debut
1206 ShapeRepr1->SetName (new TCollection_HAsciiString(""));
1207
1208 Handle(StepRepr_ShapeRepresentationRelationship) aShapeRel = new StepRepr_ShapeRepresentationRelationship;
1209 Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString("");
1210 Handle(TCollection_HAsciiString) aDescr = new TCollection_HAsciiString("");
1211 aShapeRel->SetName(aName);
1212 aShapeRel->SetDescription(aDescr);
1213 aShapeRel->SetRep2(shapeRep);
1214 aShapeRel->SetRep1(ShapeRepr1);
1215
1216 aSeqBindRelation.Append(TransientResult (aShapeRel));
1217 }
1218 }
1219 else {
1220 if (!useExistingNMSSR)
1221 shapeRep->SetItems(items);
1222 else {
1223 // Add new representation item to the NMSSR's existing collection (ssv; 13.11.2010)
1224 Handle(StepRepr_HArray1OfRepresentationItem) oldItems = shapeRep->Items();
1225 Handle(StepRepr_HArray1OfRepresentationItem) newItems =
1226 new StepRepr_HArray1OfRepresentationItem(1, oldItems->Length() + 1);
1227 Standard_Integer el = 1;
1228 for (Standard_Integer i = 1; i <= oldItems->Length(); i++)
1229 newItems->SetValue( el++, oldItems->Value(i) );
1230 newItems->SetValue( el, items->Value( items->Length() ) );
1231 shapeRep->SetItems(newItems);
1232 }
1233 }
1234
1235 // init representation
1236 STEPConstruct_UnitContext mk;
1237 mk.Init(Tol);
1238 shapeRep->SetContextOfItems(mk.Value()); // la tolerance, voir au debut
1239 shapeRep->SetName (new TCollection_HAsciiString(""));
1240
1241 // Create SDR (only once for non-manifold group)
1242 if (!useExistingNMSSR) {
1243 SDR0->SetUsedRepresentation (shapeRep);
1244 // create binder for SR and attach to it binder for RepItem (if exists)
1245 Handle(Transfer_Binder) resbind = TransientResult(shapeRep);
1246 binder = FP->Find(start);
1247 if ( ! binder.IsNull() ) {
1248 resbind->AddResult ( binder );
1249 FP->Rebind(start,resbind);
1250 //binder->AddResult ( resbind );
1251 //resbind = binder;
1252 }
1253 for(Standard_Integer k = 1; k <= aSeqBindRelation.Length(); k++)
1254 resbind->AddResult(aSeqBindRelation.Value(k));
1255
1256 // Add SDR for non-manifold topology in group mode 0 (ssv; 18.11.2010)
1257 if ( !aNMBinder.IsNull() )
1258 resbind->AddResult(aNMBinder);
1259
1260 return resbind;
1261 } else return FP->Find(start);
1262
1263}
1264
1265//=======================================================================
1266//function : TransferCompound
1267// #### TRANSFER COMPOUND AS (SUB-)ASSEMBLY
1268//purpose :
1269//=======================================================================
1270
1271Handle(Transfer_Binder) STEPControl_ActorWrite::TransferCompound (const Handle(Transfer_Finder)& start,
1272 const Handle(StepShape_ShapeDefinitionRepresentation)& SDR0,
1273 const Handle(Transfer_FinderProcess)& FP)
1274{
1275 Handle(TransferBRep_ShapeMapper) mapper = Handle(TransferBRep_ShapeMapper)::DownCast(start);
1276 Handle(Transfer_Binder) binder;
1277 if (mapper.IsNull()) return binder;
1278 TopoDS_Shape theShape = mapper->Value();
1279
1280 // Inspect non-manifold topology case (ssv; 10.11.2010)
dde68833 1281 Standard_Boolean isNMMode = Interface_Static::IVal("write.step.nonmanifold") != 0;
7fd59977 1282 Standard_Boolean isManifold;
1283 if (isNMMode)
1284 isManifold = IsManifoldShape(theShape);
1285 else
1286 isManifold = Standard_True;
1287
1288 // get a sequence of components (subshapes)
1289 Handle(TopTools_HSequenceOfShape) RepItemSeq = new TopTools_HSequenceOfShape();
1290 // Prepare a collection for non-manifold group of shapes
1291 Handle(TopTools_HSequenceOfShape) NonManifoldGroup = new TopTools_HSequenceOfShape();
1fa7cb8c 1292 Standard_Boolean isSeparateVertices =
1293 (Interface_Static::IVal("write.step.vertex.mode") == 0);//bug 23950
7fd59977 1294 // PTV OCC725 17.09.2002 -- begin --
1295 Standard_Integer nbFreeVrtx = 0;
1296 TopoDS_Compound aCompOfVrtx;
1297 BRep_Builder aB;
1298 aB.MakeCompound(aCompOfVrtx);
1299
0797d9d3 1300 #ifdef OCCT_DEBUG
7fd59977 1301 if (!isManifold)
1302 cout << "Exploding Solids to Shells if any..." << endl;
1303 #endif
1304
1305 for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
1306 TopoDS_Shape aSubShape = iter.Value();
1fa7cb8c 1307 if (aSubShape.ShapeType() != TopAbs_VERTEX || !isSeparateVertices) {
7fd59977 1308
1309 // Store non-manifold topology as shells (ssv; 10.11.2010)
1310 if (!isManifold && aSubShape.ShapeType() == TopAbs_SOLID) {
1311 for ( TopoDS_Iterator aSubIter(aSubShape); aSubIter.More(); aSubIter.Next() ) {
1312 TopoDS_Shell aSubShell = TopoDS::Shell( aSubIter.Value() );
1313 aSubShell.Closed(Standard_True);
1314 RepItemSeq->Append(aSubShell);
1315 NonManifoldGroup->Append(aSubShell);
1316 }
1317 }
1318 else if (!isManifold && (aSubShape.ShapeType() == TopAbs_SHELL) ) {
1319 RepItemSeq->Append(aSubShape);
1320 NonManifoldGroup->Append(aSubShape);
1321 }
1322 else
1323 RepItemSeq->Append(aSubShape);
1324
1325 continue;
1326 }
1327 aB.Add(aCompOfVrtx, iter.Value());
1328 nbFreeVrtx++;
1329 }
1330 if (nbFreeVrtx)
1331 RepItemSeq->Append (aCompOfVrtx);
1332
1333 // PTV OCC725 17.09.2002 -- end --
1334
1335 // Constitution : liste d axes, le premier est l origine, les suivants : 1
1336 // par sous-item
1337 Handle(StepShape_ShapeRepresentation) shapeRep =
1338 Handle(StepShape_ShapeRepresentation)::DownCast(SDR0->UsedRepresentation());
1339 if ( shapeRep.IsNull() ) {
1340 shapeRep = new StepShape_ShapeRepresentation;
1341 SDR0->SetUsedRepresentation(shapeRep); // to be used by MakeItem
1342 }
1343 binder = TransientResult(SDR0); // set SDR as first item in order to be found first (but not SDR of subshape!)
1344 binder->AddResult ( TransientResult(shapeRep) );
1345
1346 // translate components
1347 Standard_Integer i, nbs = RepItemSeq->Length();
1348 Handle(TColStd_HSequenceOfTransient) ItemSeq = new TColStd_HSequenceOfTransient();
1349 ItemSeq->Append (myContext.GetDefaultAxis());
1350 myContext.NextLevel();
1351 for ( i = 1; i <= nbs; i ++) {
1352 Handle(TransferBRep_ShapeMapper) subs = TransferBRep::ShapeMapper (FP,RepItemSeq->Value(i));
1353 Handle(StepGeom_Axis2Placement3d) AX1;
1354
1355 Handle(Transfer_Binder) bnd = TransferSubShape(subs, SDR0, AX1, FP, NonManifoldGroup, isManifold);
1356
1357 if (!AX1.IsNull()) ItemSeq->Append (AX1);
1358 // copy binders so as to have all roots in upper binder, but do not conflict
1359 while ( !bnd.IsNull() ) {
1360 Handle(Transfer_SimpleBinderOfTransient) bx =
1361 Handle(Transfer_SimpleBinderOfTransient)::DownCast(bnd);
eafb234b 1362 if ( !bx.IsNull() ) {
7fd59977 1363 // Single SDR is created for a non-manifold group (ssv: 12.11.2010)
1364 if (!isManifold && i > 1)
1365 break;
1366 else
1367 binder->AddResult( TransientResult( bx->Result() ) );
eafb234b 1368 }
7fd59977 1369 bnd = bnd->NextResult();
1370 }
1371 }
1372 myContext.PrevLevel();
1373
1374 Standard_Integer nsub = ItemSeq->Length();
1375 Handle(StepRepr_HArray1OfRepresentationItem) items =
1376 new StepRepr_HArray1OfRepresentationItem(1,nsub);
1377
1378 // initialize representation
1379 for (Standard_Integer rep = 1; rep <= nsub; rep++)
1380 items->SetValue(rep,GetCasted(StepRepr_RepresentationItem, ItemSeq->Value(rep)));
1381 shapeRep->SetItems(items);
1382 Standard_Real Tol = UsedTolerance (mytoler,theShape);
1383 STEPConstruct_UnitContext mk;
1384 mk.Init(Tol);
1385 shapeRep->SetContextOfItems(mk.Value()); // la tolerance, voir au debut
1386 shapeRep->SetName (new TCollection_HAsciiString(""));
1387
1388 // set it to SDR
1389// SDR0->SetUsedRepresentation (shapeRep);
1390
1391 return binder;
1392}
1393
1394//=======================================================================
1395//function : TransferSubShape
1396//purpose :
1397//=======================================================================
1398
1399Handle(Transfer_Binder) STEPControl_ActorWrite::TransferSubShape (const Handle(Transfer_Finder)& start,
1400 const Handle(StepShape_ShapeDefinitionRepresentation)& SDR0,
1401 Handle(StepGeom_Axis2Placement3d)& AX1,
1402 const Handle(Transfer_FinderProcess)& FP,
1403 const Handle(TopTools_HSequenceOfShape)& shapeGroup,
1404 const Standard_Boolean isManifold)
1405{
1406 Handle(TransferBRep_ShapeMapper) mapper = Handle(TransferBRep_ShapeMapper)::DownCast(start);
1407 if (mapper.IsNull()) return NullResult();
1408 TopoDS_Shape shape = mapper->Value();
1409
1410 // SHAPE EN POSITION VENANT D UN ASSEMBLAGE
1411 // Il faut alors distinguer la transformation de la shape meme
1412 // laquelle est consideree a l origine, puis transferee
1413 // A part, un item decrivant une occurence en position est cree
1414 // SINON, la shape est prise et transferee telle quelle
1415 TopoDS_Shape sh0 = shape;
1416 gp_Trsf aLoc;
1417 if ( GroupMode() >0) {
1418 TopLoc_Location shloc = shape.Location();
1419 aLoc = shloc.Transformation();
1420 TopLoc_Location shident;
1421 sh0.Location (shident);
1422 mapper = TransferBRep::ShapeMapper(FP,sh0);
1423 mapper->SameAttributes (start);
1424 }
1425
1426 Handle(Transfer_Binder) resbind = FP->Find(mapper);
1427 Handle(StepShape_ShapeDefinitionRepresentation) sdr;
1428// Handle(StepShape_ShapeRepresentation) resultat;
1429 STEPConstruct_Part SDRTool;
1430
1431 // Already SDR and SR available : take them as are
1432 Standard_Boolean iasdr = FP->GetTypedTransient
1433 (resbind,STANDARD_TYPE(StepShape_ShapeDefinitionRepresentation),sdr);
1434 if ( iasdr ) SDRTool.ReadSDR ( sdr );
1435 else {
1436 SDRTool.MakeSDR ( 0, myContext.GetProductName(), myContext.GetAPD()->Application() );
1437 sdr = SDRTool.SDRValue();
1438 }
1439// resultat = GetCasted(StepShape_ShapeRepresentation,sdr->UsedRepresentation());
1440
1441 // if shape itself not yet translated, do it now
1442 //:abv 20.05.02: see comment in TransferShape(): added "! iasdr ||"
1443 Handle(Transfer_Binder) resprod = TransientResult(sdr); //KA - OCC7141(skl 10.11.2004)
1444 if ( ! iasdr || resbind.IsNull() ) {
1445 resbind = TransferShape(mapper, sdr, FP, shapeGroup, isManifold);
1446 Handle(Transfer_Binder) oldbind = FP->Find ( mapper );
1447 if ( ! oldbind.IsNull() && !resbind.IsNull()) resbind->AddResult ( oldbind );
1448 FP->Bind (mapper,resbind);
1449 resprod=resbind; //KA - OCC7141(skl 10.11.2004)
1450 }
1aa6b1c9 1451 if (resprod.IsNull())
1452 return resprod;
7fd59977 1453
1454 // A new resbind may have been produced
1455// DeclareAndCast(Transfer_SimpleBinderOfTransient,restrans,resbind);
1456// if (restrans.IsNull()) return resbind;
1457// FP->GetTypedTransient (resbind,STANDARD_TYPE(StepShape_ShapeRepresentation),resultat);
1458// sdr->SetUsedRepresentation(resultat); // to be used by MakeItem
1459
1460 // make location for assembly placement
1461 GeomToStep_MakeAxis2Placement3d mkax (aLoc);
1462 Handle(StepGeom_Axis2Placement3d) AxLoc = mkax.Value();
1463 AX1 = AxLoc;
1464
1465 // create assembly structures (CDSR, NAUO etc.)
1466 STEPConstruct_Assembly mkitem;
1467 mkitem.Init (sdr,SDR0,myContext.GetDefaultAxis(),AxLoc);
1468 mkitem.MakeRelationship ();
1469 Handle(TColStd_HSequenceOfTransient) roots = myContext.GetRootsForAssemblyLink ( mkitem );
1470
1471 // add roots corresponding to assembly and product structures to binder
1472 //Handle(Transfer_Binder) resprod = resbind; //KA - OCC7141(skl 10.11.2004)
1473 //KA: we need only the current subshape in resprod, since the binder is copied
1474 // in Transfershape which calls Transfersubshape [ OCC7141(skl 10.11.2004) ]
1475 if ( ! iasdr ) {
1476 resprod->AddResult ( TransientResult ( SDRTool.SDRValue() ) );
1477 resbind->AddResult ( TransientResult ( SDRTool.SDRValue() ) ); //KA - OCC7141(skl 10.11.2004)
1478 roots->Append ( myContext.GetRootsForPart ( SDRTool ) );
1479 }
1480 for ( Standard_Integer i=1; i <= roots->Length(); i++ ) {
1481 resprod->AddResult ( TransientResult ( roots->Value(i) ) );
1482 resbind->AddResult ( TransientResult ( roots->Value(i) ) ); //KA - OCC7141(skl 10.11.2004)
1483 }
1484 myContext.NextIndex();
1485
1486 //FP->Bind (mapper,resprod); //KA - OCC7141(skl 10.11.2004)
1487
1488 // abv 16.10.00: bind CDSR (et al) to located shape in order to be able to track instances
1489 if ( mapper != start ) {
1490 Handle(Transfer_Binder) bnd = FP->Find ( start );
1491 for ( Standard_Integer j=1; j <= roots->Length(); j++ )
1492 if ( bnd.IsNull() ) bnd = TransientResult ( roots->Value(j) );
1493 else bnd->AddResult ( TransientResult ( roots->Value(j) ) );
1494 FP->Bind ( start, bnd );
1495 }
1496
1497 return resprod;
1498}