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