0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / VrmlData / VrmlData_ShapeConvert.cxx
... / ...
CommitLineData
1// Created on: 2007-08-04
2// Created by: Alexander GRIGORIEV
3// Copyright (c) 2007-2014 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#include <VrmlData_ShapeConvert.hxx>
17#include <VrmlData_Scene.hxx>
18#include <VrmlData_Group.hxx>
19#include <VrmlData_IndexedFaceSet.hxx>
20#include <VrmlData_IndexedLineSet.hxx>
21#include <VrmlData_ShapeNode.hxx>
22#include <BRep_Builder.hxx>
23#include <BRep_Tool.hxx>
24#include <Geom_Surface.hxx>
25#include <NCollection_DataMap.hxx>
26#include <Poly_Triangulation.hxx>
27#include <Poly_Connect.hxx>
28#include <Poly_PolygonOnTriangulation.hxx>
29#include <Poly_Polygon3D.hxx>
30#include <TDataStd_Name.hxx>
31#include <TDF_Label.hxx>
32//#include <TDF_LabelSequence.hxx>
33#include <TDocStd_Document.hxx>
34#include <TopExp_Explorer.hxx>
35#include <TopoDS.hxx>
36#include <TopoDS_Face.hxx>
37#include <TopoDS_Shape.hxx>
38#include <TopoDS_Wire.hxx>
39#include <GCPnts_TangentialDeflection.hxx>
40#include <BRepAdaptor_Curve.hxx>
41#include <TColStd_Array1OfReal.hxx>
42#include <TColStd_HArray1OfReal.hxx>
43#include <GeomLib.hxx>
44#include <TShort_HArray1OfShortReal.hxx>
45#include <VrmlData_Appearance.hxx>
46#include <XCAFDoc_ColorTool.hxx>
47#include <XCAFDoc_DocumentTool.hxx>
48#include <XCAFDoc_ShapeTool.hxx>
49#include <XCAFPrs_Style.hxx>
50#include <XCAFDoc_VisMaterial.hxx>
51#include <XCAFDoc_VisMaterialTool.hxx>
52
53//=======================================================================
54//function : AddShape
55//purpose :
56//=======================================================================
57
58void VrmlData_ShapeConvert::AddShape (const TopoDS_Shape& theShape,
59 const char * theName)
60{
61 ShapeData aData;/* = { - compilation problem on SUN
62 TCollection_AsciiString(),
63 theShape,
64 NULL
65 };*/
66 aData.Shape = theShape;
67 aData.Node = NULL;
68
69 if (theName) {
70 char buf[2048], * optr = &buf[0];
71 char * eptr = &buf[sizeof(buf)-1];
72 for (const char * ptr = theName;; ptr++) {
73 char sym = *ptr;
74 if (sym == '\0' || sym == '\n' || sym == '\r') {
75 * optr = '\0';
76 break;
77 }
78 if (sym == '\"' || sym == '\\')
79 * optr = '/';
80 else if (sym == '.')
81 * optr = '_';
82 else
83 * optr = sym;
84 if (++optr >= eptr) {
85 *optr = '\0';
86 break;
87 }
88 }
89 aData.Name = buf;
90 }
91 myShapes.Append (aData);
92}
93
94
95//=======================================================================
96//function : makeTShapeNode
97//purpose : auxiliary
98//=======================================================================
99Handle(VrmlData_Geometry) VrmlData_ShapeConvert::makeTShapeNode(const TopoDS_Shape& theShape,
100 const TopAbs_ShapeEnum theShapeType,
101 TopLoc_Location& theLoc)
102{
103 Handle(VrmlData_Geometry) aTShapeNode = 0L;
104 const Standard_Boolean isReverse = (theShape.Orientation() == TopAbs_REVERSED);
105
106 TopoDS_Shape aTestedShape;
107 aTestedShape.TShape(theShape.TShape());
108 aTestedShape.Orientation(isReverse ? TopAbs_REVERSED : TopAbs_FORWARD);
109 switch (theShapeType) {
110 case TopAbs_FACE:
111 {
112 const TopoDS_Face& aFace = TopoDS::Face(theShape);
113 if (aFace.IsNull() == Standard_False) {
114 Handle(Poly_Triangulation) aTri =
115 BRep_Tool::Triangulation(aFace, theLoc);
116
117 if (myRelMap.IsBound(aTestedShape)) {
118 aTShapeNode = myRelMap(aTestedShape);
119 break;
120 }
121
122 if (aTri.IsNull() == Standard_False) {
123 TopoDS_Shape aTestedShapeRev = aTestedShape;
124 aTestedShapeRev.Orientation(isReverse ?
125 TopAbs_FORWARD : TopAbs_REVERSED);
126 Handle(VrmlData_IndexedFaceSet) aFaceSetToReuse;
127 if (myRelMap.IsBound(aTestedShapeRev))
128 aFaceSetToReuse = Handle(VrmlData_IndexedFaceSet)::DownCast
129 (myRelMap(aTestedShapeRev));
130
131 Handle(VrmlData_Coordinate) aCoordToReuse;
132 if (aFaceSetToReuse.IsNull() == Standard_False)
133 aCoordToReuse = aFaceSetToReuse->Coordinates();
134
135 aTShapeNode = triToIndexedFaceSet(aTri, aFace, aCoordToReuse);
136 myScene.AddNode(aTShapeNode, Standard_False);
137 // Bind the converted face
138 myRelMap.Bind(aTestedShape, aTShapeNode);
139 }
140 }
141 }
142 break;
143 case TopAbs_WIRE:
144 {
145 const TopoDS_Wire& aWire = TopoDS::Wire(theShape);
146 if (aWire.IsNull() == Standard_False) {
147 }
148 }
149 break;
150 case TopAbs_EDGE:
151 {
152 const TopoDS_Edge& aEdge = TopoDS::Edge(theShape);
153 if (aEdge.IsNull() == Standard_False) {
154 if (myRelMap.IsBound(aTestedShape)) {
155 aTShapeNode = myRelMap(aTestedShape);
156 break;
157 }
158 // Check the presence of reversly oriented Edge. It can also be used
159 // because we do not distinguish the orientation for edges.
160 aTestedShape.Orientation(isReverse ?
161 TopAbs_FORWARD : TopAbs_REVERSED);
162 if (myRelMap.IsBound(aTestedShape)) {
163 aTShapeNode = myRelMap(aTestedShape);
164 break;
165 }
166
167 //try to find PolygonOnTriangulation
168 Handle(Poly_PolygonOnTriangulation) aPT;
169 Handle(Poly_Triangulation) aT;
170 TopLoc_Location aL;
171 BRep_Tool::PolygonOnTriangulation(aEdge, aPT, aT, aL);
172
173 // If PolygonOnTriangulation was found -> get the Polygon3D
174 Handle(Poly_Polygon3D) aPol;
175 if (!aPT.IsNull() && !aT.IsNull() && aPT->HasParameters()) {
176 BRepAdaptor_Curve aCurve(aEdge);
177 Handle(TColStd_HArray1OfReal) aPrs = aPT->Parameters();
178 Standard_Integer nbNodes = aPT->NbNodes();
179 TColgp_Array1OfPnt arrNodes(1, nbNodes);
180 TColStd_Array1OfReal arrUVNodes(1, nbNodes);
181
182 for (Standard_Integer j = 1; j <= nbNodes; j++) {
183 arrUVNodes(j) = aPrs->Value(aPrs->Lower() + j - 1);
184 arrNodes(j) = aCurve.Value(arrUVNodes(j));
185 }
186 aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
187 aPol->Deflection(aPT->Deflection());
188 }
189 else {
190 aPol = BRep_Tool::Polygon3D(aEdge, aL);
191
192 // If polygon was not found -> generate it
193 if (aPol.IsNull()) {
194 BRepAdaptor_Curve aCurve(aEdge);
195 const Standard_Real aFirst = aCurve.FirstParameter();
196 const Standard_Real aLast = aCurve.LastParameter();
197
198 GCPnts_TangentialDeflection TD(aCurve, aFirst, aLast,
199 myDeflAngle, myDeflection, 2);
200 const Standard_Integer nbNodes = TD.NbPoints();
201
202 TColgp_Array1OfPnt arrNodes(1, nbNodes);
203 TColStd_Array1OfReal arrUVNodes(1, nbNodes);
204 for (Standard_Integer j = 1; j <= nbNodes; j++) {
205 arrNodes(j) = TD.Value(j);
206 arrUVNodes(j) = TD.Parameter(j);
207 }
208 aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
209 aPol->Deflection(myDeflection);
210 }
211 }
212
213 if (!aPol.IsNull())
214 {
215 aTShapeNode = polToIndexedLineSet(aPol);
216 myScene.AddNode(aTShapeNode, Standard_False);
217 // Bind the converted face
218 myRelMap.Bind(aTestedShape, aTShapeNode);
219 }
220 }
221 }
222 break;
223 default:
224 break;
225 }
226
227 return aTShapeNode;
228}
229
230
231//=======================================================================
232//function : Convert
233//purpose :
234//=======================================================================
235
236void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
237 const Standard_Boolean theExtractEdges,
238 const Standard_Real theDeflection,
239 const Standard_Real theDeflAngle)
240{
241 //const Standard_Real aDeflection =
242 // theDeflection < 0.0001 ? 0.0001 : theDeflection;
243
244 myDeflection = theDeflection < 0.0001 ? 0.0001 : theDeflection;
245 myDeflAngle = theDeflAngle;
246
247 Standard_Boolean Extract[2] = {theExtractFaces, theExtractEdges};
248 TopAbs_ShapeEnum ShapeType[2] = {TopAbs_FACE, TopAbs_EDGE};
249 Standard_Integer i;
250
251 const Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
252
253 // Relocation map for converted shapes. We should distinguish both TShape
254 // and Orientation in this map.
255 //NCollection_DataMap <TopoDS_Shape,Handle(VrmlData_Geometry)>
256 // aRelMap (100, anAlloc);
257 myRelMap = NCollection_DataMap <TopoDS_Shape, Handle(VrmlData_Geometry)>(100, anAlloc);
258
259 NCollection_List<ShapeData>::Iterator anIter (myShapes);
260 for (; anIter.More(); anIter.Next())
261 {
262 ShapeData& aData = anIter.ChangeValue();
263 TCollection_AsciiString aGrName = aData.Name;
264 aGrName.ChangeAll(' ', '_');
265 aGrName.ChangeAll('#', '_');
266 Handle(VrmlData_Group) aGroup =
267 new VrmlData_Group (myScene, aGrName.ToCString());
268 myScene.AddNode (aGroup);
269
270 for(i = 0; i < 2; ++i) {
271
272 if(!Extract[i]) continue;
273
274 TopExp_Explorer anExp (aData.Shape, ShapeType[i]);
275 for (; anExp.More(); anExp.Next()) {
276 const TopoDS_Shape& aShape = anExp.Current();
277 TopLoc_Location aLoc;
278 Handle(VrmlData_Geometry) aTShapeNode =
279 makeTShapeNode(aShape, ShapeType[i], aLoc);
280 if (!aTShapeNode.IsNull()) {
281 const Handle(VrmlData_ShapeNode) aShapeNode =
282 new VrmlData_ShapeNode (myScene, 0L);
283 aShapeNode->SetAppearance (ShapeType[i] == TopAbs_FACE ?
284 defaultMaterialFace():defaultMaterialEdge());
285 myScene.AddNode (aShapeNode, Standard_False);
286 aShapeNode->SetGeometry (aTShapeNode);
287 if (aLoc.IsIdentity())
288 // Store the shape node directly into the main Group.
289 aGroup->AddNode (aShapeNode);
290 else {
291 // Create a Transform grouping node
292 Handle(VrmlData_Group) aTrans = new VrmlData_Group (myScene, 0L,
293 Standard_True);
294 gp_Trsf aTrsf (aLoc);
295 if (fabs(myScale - 1.) > Precision::Confusion())
296 {
297 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
298 aTrsf.SetTranslationPart (aTransl);
299 }
300 aTrans->SetTransform (aTrsf);
301 myScene.AddNode (aTrans, Standard_False);
302 aGroup->AddNode (aTrans);
303
304 // Store the shape node under the transform.
305 aTrans->AddNode (aShapeNode);
306 }
307 }
308 }
309 }
310 }
311 myShapes.Clear();
312}
313
314//=======================================================================
315//function : triToIndexedFaceSet
316//purpose :
317//=======================================================================
318
319Handle(VrmlData_Geometry) VrmlData_ShapeConvert::triToIndexedFaceSet
320 (const Handle(Poly_Triangulation)& theTri,
321 const TopoDS_Face& theFace,
322 const Handle(VrmlData_Coordinate)& theCoord)
323{
324 Standard_Integer i;
325 const Standard_Integer nNodes (theTri->NbNodes());
326 const Standard_Integer nTriangles (theTri->NbTriangles());
327
328 // protection against creation degenerative triangles
329 Standard_Integer nbTri = 0;
330 Poly_Array1OfTriangle aTriangles(1, nTriangles);
331 for (i = 0; i < nTriangles; i++) {
332 Standard_Integer idx[3];
333 theTri->Triangle (i + 1).Get (idx[0], idx[1], idx[2]);
334 if (idx[0] == idx[1] || idx[0] == idx[2] || idx[1] == idx[2])
335 {
336 continue;
337 }
338 nbTri++;
339 aTriangles.SetValue (nbTri, theTri->Triangle (i + 1));
340 }
341 aTriangles.Resize(1, nbTri, Standard_True);
342
343 const Handle(VrmlData_IndexedFaceSet) aFaceSet =
344 new VrmlData_IndexedFaceSet (myScene,
345 0L, // no name
346 Standard_True, // IsCCW
347 Standard_False, // IsSolid
348 Standard_False); // IsConvex
349 const Handle(NCollection_IncAllocator)& anAlloc = myScene.Allocator();
350 const Standard_Boolean isReverse = (theFace.Orientation() == TopAbs_REVERSED);
351
352 // Create the array of triangles
353 const Standard_Integer ** arrPolygons = static_cast<const Standard_Integer **>
354 (anAlloc->Allocate (nbTri * sizeof(const Standard_Integer *)));
355 aFaceSet->SetPolygons (nbTri, arrPolygons);
356
357 // Store the triangles
358 for (i = 0; i < nbTri; i++) {
359 Standard_Integer * aPolygon = static_cast<Standard_Integer *>
360 (anAlloc->Allocate (4*sizeof(Standard_Integer)));
361 aPolygon[0] = 3;
362 aTriangles(i + 1).Get(aPolygon[1], aPolygon[2], aPolygon[3]);
363 aPolygon[1]--;
364 if (isReverse) {
365 const Standard_Integer aTmp = aPolygon[2]-1;
366 aPolygon[2] = aPolygon[3]-1;
367 aPolygon[3] = aTmp;
368 } else {
369 aPolygon[2]--;
370 aPolygon[3]--;
371 }
372 arrPolygons[i] = aPolygon;
373 }
374
375 // Create the Coordinates node
376 if (theCoord.IsNull() == Standard_False)
377 aFaceSet->SetCoordinates (theCoord);
378 else {
379 gp_XYZ * arrNodes = static_cast <gp_XYZ *>
380 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
381 for (i = 0; i < nNodes; i++)
382 {
383 arrNodes[i] = theTri->Node (i+1).XYZ() * myScale;
384 }
385
386 const Handle(VrmlData_Coordinate) aCoordNode =
387 new VrmlData_Coordinate (myScene, 0L, nNodes, arrNodes);
388 myScene.AddNode (aCoordNode, Standard_False);
389 aFaceSet->SetCoordinates (aCoordNode);
390 }
391
392 // Create the Normals node if theTri has normals
393 if (theTri->HasNormals())
394 {
395 gp_XYZ* arrVec = static_cast<gp_XYZ*>(anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
396 gp_Vec3f aVec3;
397 for (i = 0; i < nNodes; i++)
398 {
399 theTri->Normal (i + 1, aVec3);
400 gp_XYZ aNormal (aVec3.x(), aVec3.y(), aVec3.z());
401 if (isReverse)
402 {
403 aNormal.Reverse();
404 }
405 arrVec[i] = aNormal;
406 }
407 const Handle(VrmlData_Normal) aNormalNode =
408 new VrmlData_Normal (myScene, 0L, nNodes, arrVec);
409 myScene.AddNode (aNormalNode, Standard_False);
410 aFaceSet->SetNormals (aNormalNode);
411 return Handle(VrmlData_Geometry) (aFaceSet);
412 }
413
414 Poly_Connect PC(theTri);
415 // Create the Normals node (if UV- values are available)
416 TopLoc_Location aLoc;
417 const Standard_Real aConf2 = Precision::SquareConfusion();
418 const Handle(Geom_Surface) aSurface = BRep_Tool::Surface (theFace, aLoc);
419 if (theTri->HasUVNodes() && aSurface.IsNull() == Standard_False)
420 {
421 if (aSurface->IsCNu(1) && aSurface->IsCNv(1))
422 {
423 gp_XYZ* arrVec = static_cast<gp_XYZ*> (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
424
425 // Compute the normal vectors
426 Standard_Real Tol = Sqrt(aConf2);
427 for (i = 0; i < nNodes; i++)
428 {
429 const gp_Pnt2d aUV = theTri->UVNode (i+1);
430 gp_Dir aNormal;
431 if (GeomLib::NormEstim(aSurface, aUV, Tol, aNormal) > 1) {
432 //Try to estimate as middle normal of adjacent triangles
433 Standard_Integer n[3];
434
435 gp_XYZ eqPlan(0., 0., 0.);
436 for (PC.Initialize(i+1); PC.More(); PC.Next()) {
437 aTriangles(PC.Value()).Get(n[0], n[1], n[2]);
438 gp_XYZ v1 (theTri->Node (n[1]).Coord()-theTri->Node (n[0]).Coord());
439 gp_XYZ v2 (theTri->Node (n[2]).Coord()-theTri->Node (n[1]).Coord());
440 gp_XYZ vv = v1^v2;
441
442 Standard_Real mod = vv.Modulus();
443 if (mod < Tol)
444 continue;
445
446 eqPlan += vv/mod;
447 }
448
449 if (eqPlan.SquareModulus() > gp::Resolution())
450 aNormal = gp_Dir(eqPlan);
451 }
452 if (isReverse)
453 aNormal.Reverse();
454
455 if (aNormal.X()*aNormal.X() < aConf2)
456 aNormal.SetX(0.);
457 if (aNormal.Y()*aNormal.Y() < aConf2)
458 aNormal.SetY(0.);
459 if (aNormal.Z()*aNormal.Z() < aConf2)
460 aNormal.SetZ(0.);
461
462 arrVec[i] = aNormal.XYZ();
463 }
464
465 const Handle(VrmlData_Normal) aNormalNode =
466 new VrmlData_Normal (myScene, 0L, nNodes, arrVec);
467 myScene.AddNode (aNormalNode, Standard_False);
468 aFaceSet->SetNormals (aNormalNode);
469 }
470 }
471
472 return Handle(VrmlData_Geometry) (aFaceSet);
473}
474
475//=======================================================================
476//function : polToIndexedLineSet
477//purpose : single polygon3D => IndexedLineSet
478//=======================================================================
479
480Handle(VrmlData_Geometry) VrmlData_ShapeConvert::polToIndexedLineSet
481 (const Handle(Poly_Polygon3D)& thePol)
482{
483 Standard_Integer i;
484 const Standard_Integer nNodes (thePol->NbNodes());
485 const TColgp_Array1OfPnt& arrPolyNodes = thePol->Nodes();
486 const Handle(NCollection_IncAllocator)& anAlloc = myScene.Allocator();
487
488 const Handle(VrmlData_IndexedLineSet) aLineSet =
489 new VrmlData_IndexedLineSet (myScene, 0L);
490
491 // Create the array of polygons (1 member)
492 const Standard_Integer ** arrPolygons = static_cast<const Standard_Integer **>
493 (anAlloc->Allocate (sizeof(const Standard_Integer *)));
494 aLineSet->SetPolygons (1, arrPolygons);
495
496 // Store the polygon
497 Standard_Integer * aPolygon = static_cast<Standard_Integer *>
498 (anAlloc->Allocate ((nNodes+1)*sizeof(Standard_Integer)));
499 aPolygon[0] = nNodes;
500 for (i = 1; i <= nNodes; i++)
501 aPolygon[i] = i-1;
502 arrPolygons[0] = aPolygon;
503
504 // Create the Coordinates node
505 gp_XYZ * arrNodes = static_cast <gp_XYZ *>
506 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
507 for (i = 0; i < nNodes; i++)
508 arrNodes[i] = arrPolyNodes(i+1).XYZ() * myScale;
509
510 const Handle(VrmlData_Coordinate) aCoordNode =
511 new VrmlData_Coordinate (myScene, 0L, nNodes, arrNodes);
512 myScene.AddNode (aCoordNode, Standard_False);
513 aLineSet->SetCoordinates (aCoordNode);
514
515 return Handle(VrmlData_Geometry) (aLineSet);
516}
517
518//=======================================================================
519//function : defaultMaterialFace
520//purpose :
521//=======================================================================
522
523Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialFace () const
524{
525 static char aNodeName[] = "__defaultMaterialFace";
526 Handle(VrmlData_Appearance) anAppearance =
527 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName));
528 if (anAppearance.IsNull()) {
529 const Handle(VrmlData_Material) aMaterial =
530 new VrmlData_Material (myScene, 0L, 1.0, 0.022, 0.);
531 aMaterial->SetDiffuseColor (Quantity_Color(0.780392, 0.568627, 0.113725,
532 Quantity_TOC_sRGB));
533 aMaterial->SetEmissiveColor(Quantity_Color(0.329412, 0.223529, 0.027451,
534 Quantity_TOC_sRGB));
535 aMaterial->SetSpecularColor(Quantity_Color(0.992157, 0.941176, 0.807843,
536 Quantity_TOC_sRGB));
537 myScene.AddNode (aMaterial, Standard_False);
538 anAppearance = new VrmlData_Appearance (myScene, aNodeName);
539 anAppearance->SetMaterial (aMaterial);
540 myScene.AddNode (anAppearance, Standard_False);
541 }
542 return anAppearance;
543}
544
545//=======================================================================
546//function : defaultMaterialEdge
547//purpose :
548//=======================================================================
549
550Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialEdge () const
551{
552 static char aNodeName[] = "__defaultMaterialEdge";
553 Handle(VrmlData_Appearance) anAppearance =
554 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName));
555 if (anAppearance.IsNull()) {
556 const Handle(VrmlData_Material) aMaterial =
557 new VrmlData_Material (myScene, 0L, 0.2, 0.2, 0.2);
558 aMaterial->SetDiffuseColor (Quantity_Color(0.2, 0.7, 0.2,
559 Quantity_TOC_RGB));
560 aMaterial->SetEmissiveColor(Quantity_Color(0.2, 0.7, 0.2,
561 Quantity_TOC_RGB));
562 aMaterial->SetSpecularColor(Quantity_Color(0.2, 0.7, 0.2,
563 Quantity_TOC_RGB));
564 myScene.AddNode (aMaterial, Standard_False);
565 anAppearance = new VrmlData_Appearance (myScene, aNodeName);
566 anAppearance->SetMaterial (aMaterial);
567 myScene.AddNode (anAppearance, Standard_False);
568 }
569 return anAppearance;
570}
571
572
573//=======================================================================
574//function : addShape
575//purpose : Adds the shape from the document
576//=======================================================================
577void VrmlData_ShapeConvert::addShape (const Handle(VrmlData_Group)& theParent,
578 const TDF_Label& theLabel,
579 const Handle(TDocStd_Document)& theDoc)
580{
581 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
582 Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(theDoc->Main());
583 Handle(XCAFDoc_VisMaterialTool) aMatTool = XCAFDoc_DocumentTool::VisMaterialTool(theDoc->Main());
584
585 NCollection_DataMap<TopoDS_Shape, TDF_Label> aChildShapeToLabels;
586 TDF_LabelSequence aChildLabels;
587 aShapeTool->GetSubShapes(theLabel, aChildLabels);
588 for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
589 {
590 const TDF_Label& aChildLabel = aChildIter.Value();
591 TopoDS_Shape aChildShape;
592 if (aShapeTool->GetShape(aChildLabel, aChildShape))
593 {
594 aChildShapeToLabels.Bind(aChildShape, aChildLabel);
595 }
596 }
597
598 const TopoDS_Shape aShape = aShapeTool->GetShape(theLabel);
599 Handle(VrmlData_Group) aGroup = 0L;
600 TopExp_Explorer anExp(aShape, TopAbs_FACE);
601 Standard_Integer nbFaces = 0;
602 for (; anExp.More(); anExp.Next()) {
603 nbFaces++;
604 }
605 Handle(TDataStd_Name) aNameAttribute;
606 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
607 if (nbFaces > 1)
608 {
609 if (!aNameAttribute.IsNull())
610 {
611 TCollection_AsciiString aName = aNameAttribute->Get();
612 aName.ChangeAll(' ', '_');
613 aName.ChangeAll('#', '_');
614 aGroup = new VrmlData_Group(myScene, aName.ToCString());
615 }
616 else
617 {
618 aGroup = new VrmlData_Group(myScene, 0L);
619 }
620 myScene.AddNode(aGroup, theParent.IsNull());
621 if (!theParent.IsNull())
622 {
623 theParent->AddNode(aGroup);
624 }
625 }
626
627 anExp.Init(aShape, TopAbs_FACE);
628 for (; anExp.More(); anExp.Next()) {
629 TopLoc_Location aLoc;
630 Handle(VrmlData_Geometry) aTShapeNode =
631 makeTShapeNode(anExp.Current(), TopAbs_FACE, aLoc);
632 if (!aTShapeNode.IsNull())
633 {
634 Handle(VrmlData_ShapeNode) aShapeNode = 0L;
635 if (aGroup.IsNull() && !aNameAttribute.IsNull())
636 {
637 TCollection_AsciiString aName = aNameAttribute->Get();
638 aName.ChangeAll(' ', '_');
639 aName.ChangeAll('#', '_');
640 aShapeNode = new VrmlData_ShapeNode(myScene, aName.ToCString());
641 }
642 else
643 {
644 aShapeNode = new VrmlData_ShapeNode(myScene, 0L);
645 }
646
647 // set color
648 XCAFPrs_Style aStyle;
649 Quantity_ColorRGBA aColor;
650 TDF_Label aLabel, anAttribLab;
651 if (aChildShapeToLabels.Find (anExp.Current(), aLabel))
652 {
653 Handle(XCAFDoc_VisMaterial) aVisMat = aMatTool->GetShapeMaterial (aLabel);
654 if (!aVisMat.IsNull()
655 && !aVisMat->IsEmpty())
656 {
657 anAttribLab = aVisMat->Label();
658 aStyle.SetMaterial (aVisMat);
659 }
660 else if (aColorTool->GetColor (aLabel, XCAFDoc_ColorSurf, anAttribLab)
661 || aColorTool->GetColor (aLabel, XCAFDoc_ColorGen, anAttribLab))
662 {
663 aColorTool->GetColor (anAttribLab, aColor);
664 aStyle.SetColorSurf (aColor);
665 }
666 }
667 if (!aStyle.IsSetColorSurf()
668 && aStyle.Material().IsNull())
669 {
670 Handle(XCAFDoc_VisMaterial) aVisMat = aMatTool->GetShapeMaterial (theLabel);
671 if (!aVisMat.IsNull()
672 && !aVisMat->IsEmpty())
673 {
674 anAttribLab = aVisMat->Label();
675 aStyle.SetMaterial (aVisMat);
676 }
677 if (aColorTool->GetColor (theLabel, XCAFDoc_ColorSurf, anAttribLab)
678 || aColorTool->GetColor (theLabel, XCAFDoc_ColorGen, anAttribLab))
679 {
680 aColorTool->GetColor (anAttribLab, aColor);
681 aStyle.SetColorSurf (aColor);
682 }
683 }
684 if (!aStyle.IsSetColorSurf()
685 && aStyle.Material().IsNull())
686 {
687 aShapeNode->SetAppearance(defaultMaterialFace());
688 }
689 else
690 {
691 aShapeNode->SetAppearance (makeMaterialFromStyle (aStyle, anAttribLab));
692 }
693
694 myScene.AddNode(aShapeNode, theParent.IsNull() && aGroup.IsNull());
695 aShapeNode->SetGeometry(aTShapeNode);
696 if (aLoc.IsIdentity())
697 {
698 // Store the shape node directly into the main Group.
699 if (!aGroup.IsNull())
700 {
701 aGroup->AddNode(aShapeNode);
702 }
703 else if (!theParent.IsNull())
704 {
705 theParent->AddNode(aShapeNode);
706 }
707 }
708 else
709 {
710 // Create a Transform grouping node
711 Handle(VrmlData_Group) aTrans = new VrmlData_Group(myScene, 0L,
712 Standard_True);
713 gp_Trsf aTrsf(aLoc);
714 if (fabs(myScale - 1.) > Precision::Confusion())
715 {
716 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
717 aTrsf.SetTranslationPart(aTransl);
718 }
719 aTrans->SetTransform(aTrsf);
720 myScene.AddNode(aTrans, theParent.IsNull() && aGroup.IsNull());
721 if (!aGroup.IsNull())
722 {
723 aGroup->AddNode(aTrans);
724 }
725 else if (!theParent.IsNull())
726 {
727 theParent->AddNode(aTrans);
728 }
729 // Store the shape node under the transform.
730 aTrans->AddNode(aShapeNode);
731 }
732 }
733 }
734}
735
736
737//=======================================================================
738//function : addInstance
739//purpose : Adds the reference from the document
740//=======================================================================
741void VrmlData_ShapeConvert::addInstance (const Handle(VrmlData_Group)& theParent,
742 const TDF_Label& theLabel,
743 const Handle(TDocStd_Document)& theDoc)
744{
745 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
746
747 const TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
748 Handle(VrmlData_Group) aTrans = 0L;
749 if (!aLoc.IsIdentity())
750 {
751 // Create a Transform grouping node
752 aTrans = new VrmlData_Group(myScene, 0L, Standard_True);
753 gp_Trsf aTrsf(aLoc);
754 if (fabs(myScale - 1.) > Precision::Confusion())
755 {
756 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
757 aTrsf.SetTranslationPart(aTransl);
758 }
759 aTrans->SetTransform(aTrsf);
760 myScene.AddNode(aTrans, theParent.IsNull());
761 if (!theParent.IsNull())
762 {
763 theParent->AddNode(aTrans);
764 }
765 }
766
767 Handle(TDataStd_Name) aNameAttribute;
768 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
769
770 TDF_Label aRefLabel;
771 aShapeTool->GetReferredShape(theLabel, aRefLabel);
772 Handle(TDataStd_Name) aRefNameAttribute;
773 aRefLabel.FindAttribute(TDataStd_Name::GetID(), aRefNameAttribute);
774
775 if (aShapeTool->IsSimpleShape(aRefLabel))
776 {
777 addShape((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc);
778 }
779 else if (aShapeTool->IsAssembly(aRefLabel))
780 {
781 addAssembly((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc, aTrans.IsNull());
782 }
783}
784
785
786//=======================================================================
787//function : addAssembly
788//purpose : Adds the assembly from the document
789//=======================================================================
790void VrmlData_ShapeConvert::addAssembly (const Handle(VrmlData_Group)& theParent,
791 const TDF_Label& theLabel,
792 const Handle(TDocStd_Document)& theDoc,
793 const Standard_Boolean theNeedCreateGroup)
794{
795 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
796
797 Handle(VrmlData_Group) anAssembly = 0L;
798 if (theNeedCreateGroup)
799 {
800 Handle(TDataStd_Name) aNameAttribute;
801 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
802 if (!aNameAttribute.IsNull())
803 {
804 TCollection_AsciiString aName = aNameAttribute->Get();
805 aName.ChangeAll(' ', '_');
806 aName.ChangeAll('#', '_');
807 anAssembly = new VrmlData_Group(myScene, aName.ToCString());
808 }
809 else
810 {
811 anAssembly = new VrmlData_Group(myScene, 0L);
812 }
813 TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
814 if (!aLoc.IsIdentity())
815 {
816 gp_Trsf aTrsf(aLoc);
817 if (fabs(myScale - 1.) > Precision::Confusion())
818 {
819 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
820 aTrsf.SetTranslationPart(aTransl);
821 }
822 anAssembly->SetTransform(aTrsf);
823 }
824 myScene.AddNode(anAssembly, theParent.IsNull());
825 if (!theParent.IsNull())
826 {
827 theParent->AddNode(anAssembly);
828 }
829 }
830
831 TDF_LabelSequence aChildLabels;
832 aShapeTool->GetComponents(theLabel, aChildLabels);
833 for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
834 {
835 const TDF_Label& aChildLabel = aChildIter.Value();
836 if (aShapeTool->IsAssembly(aChildLabel))
837 {
838 addAssembly((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc, anAssembly.IsNull());
839 }
840 else if (aShapeTool->IsReference(aChildLabel))
841 {
842 addInstance((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
843 }
844 else if (aShapeTool->IsSimpleShape(aChildLabel))
845 {
846 addShape((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
847 }
848 }
849}
850
851
852//=======================================================================
853//function : ConvertDocument
854//purpose :
855//=======================================================================
856void VrmlData_ShapeConvert::ConvertDocument(const Handle(TDocStd_Document) &theDoc)
857{
858 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
859
860 TDF_LabelSequence aFreeShapeLabels;
861 aShapeTool->GetFreeShapes(aFreeShapeLabels);
862
863 Handle(VrmlData_Group) aGroup = 0L;
864 if (aFreeShapeLabels.Size() > 1)
865 {
866 aGroup = new VrmlData_Group(myScene, 0L);
867 myScene.AddNode(aGroup);
868 }
869
870 for (TDF_LabelSequence::Iterator aRootIter(aFreeShapeLabels); aRootIter.More(); aRootIter.Next())
871 {
872 const TDF_Label& aFreeShapeLabel = aRootIter.Value();
873 if (aShapeTool->IsAssembly (aFreeShapeLabel))
874 {
875 addAssembly (aGroup, aFreeShapeLabel, theDoc, Standard_True);
876 }
877 else if (aShapeTool->IsReference (aFreeShapeLabel))
878 {
879 addInstance (aGroup, aFreeShapeLabel, theDoc);
880 }
881 else if (aShapeTool->IsSimpleShape (aFreeShapeLabel))
882 {
883 addShape (aGroup, aFreeShapeLabel, theDoc);
884 }
885 }
886}
887
888//=======================================================================
889//function : makeMaterialFromStyle
890//purpose :
891//=======================================================================
892Handle(VrmlData_Appearance) VrmlData_ShapeConvert::makeMaterialFromStyle (const XCAFPrs_Style& theStyle,
893 const TDF_Label& theAttribLab) const
894{
895 const Quantity_ColorRGBA aColor = !theStyle.Material().IsNull()
896 ? theStyle.Material()->BaseColor()
897 : theStyle.GetColorSurfRGBA();
898
899 TCollection_AsciiString aNodeName = "_materialFace_";
900 Handle(TDataStd_Name) aNameAttribute;
901 if (theAttribLab.FindAttribute(TDataStd_Name::GetID(), aNameAttribute))
902 {
903 aNodeName.AssignCat(aNameAttribute->Get());
904 Standard_Integer n = aNodeName.Search(" ");
905 if (n > 0)
906 {
907 aNodeName = aNodeName.SubString(1, n - 1);
908 }
909 }
910 else
911 {
912 NCollection_Vec3<Standard_Real> aColor_sRGB;
913 aColor.GetRGB().Values (aColor_sRGB.r(), aColor_sRGB.g(), aColor_sRGB.b(), Quantity_TOC_sRGB);
914 aNodeName.AssignCat(aColor_sRGB.r());
915 aNodeName.AssignCat("_");
916 aNodeName.AssignCat(aColor_sRGB.g());
917 aNodeName.AssignCat("_");
918 aNodeName.AssignCat(aColor_sRGB.b());
919 }
920
921 Handle(VrmlData_Appearance) anAppearance = Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName.ToCString()));
922 if (anAppearance.IsNull())
923 {
924 Handle(VrmlData_Material) aMaterial = new VrmlData_Material (myScene, 0L);
925 aMaterial->SetDiffuseColor (aColor.GetRGB());
926 myScene.AddNode (aMaterial, Standard_False);
927 anAppearance = new VrmlData_Appearance (myScene, aNodeName.ToCString());
928 anAppearance->SetMaterial (aMaterial);
929 myScene.AddNode (anAppearance, Standard_False);
930 }
931
932 return anAppearance;
933}