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