0030218: Visualization - custom selection presentation is not updated within SelectMg...
[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
58//=======================================================================
7fd59977 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;
399 for (i = 0, j = 1; i < nNodes; i++, j += 3) {
400
401 gp_XYZ aNormal(Norm(j), Norm(j+1), Norm(j+2));
402 arrVec[i] = aNormal;
403
404 }
405 const Handle(VrmlData_Normal) aNormalNode =
406 new VrmlData_Normal (myScene, 0L, nNodes, arrVec);
407 myScene.AddNode (aNormalNode, Standard_False);
408 aFaceSet->SetNormals (aNormalNode);
5b111128 409 return Handle(VrmlData_Geometry) (aFaceSet);
7fd59977 410 }
411
412 Poly_Connect PC(theTri);
413 // Create the Normals node (if UV- values are available)
414 TopLoc_Location aLoc;
08cd2f6b 415 const Standard_Real aConf2 = Precision::SquareConfusion();
7fd59977 416 const Handle(Geom_Surface) aSurface = BRep_Tool::Surface (theFace, aLoc);
417 if (theTri->HasUVNodes() && aSurface.IsNull() == Standard_False) {
418 if (aSurface->IsCNu(1) && aSurface->IsCNv(1))
419 {
420 Standard_Integer nbNormVal = nNodes * 3;
421 Handle(TShort_HArray1OfShortReal) Normals =
422 new TShort_HArray1OfShortReal(1, nbNormVal);
423
424 const TColgp_Array1OfPnt2d& arrUV = theTri->UVNodes();
425 gp_XYZ * arrVec = static_cast <gp_XYZ *>
426 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
427
428 // Compute the normal vectors
429 Standard_Real Tol = Sqrt(aConf2);
430 for (i = 0; i < nNodes; i++) {
431 const gp_Pnt2d& aUV = arrUV(i+1);
432
433 gp_Dir aNormal;
434
435 if (GeomLib::NormEstim(aSurface, aUV, Tol, aNormal) > 1) {
436 //Try to estimate as middle normal of adjacent triangles
437 Standard_Integer n[3];
438
439 gp_XYZ eqPlan(0., 0., 0.);
440 for (PC.Initialize(i+1); PC.More(); PC.Next()) {
a3506de7 441 aTriangles(PC.Value()).Get(n[0], n[1], n[2]);
7fd59977 442 gp_XYZ v1(arrPolyNodes(n[1]).Coord()-arrPolyNodes(n[0]).Coord());
443 gp_XYZ v2(arrPolyNodes(n[2]).Coord()-arrPolyNodes(n[1]).Coord());
444 gp_XYZ vv = v1^v2;
445
446 Standard_Real mod = vv.Modulus();
447 if (mod < Tol)
448 continue;
449
450 eqPlan += vv/mod;
451 }
452
453 if (eqPlan.SquareModulus() > gp::Resolution())
454 aNormal = gp_Dir(eqPlan);
455 }
456 if (isReverse)
457 aNormal.Reverse();
458
459 if (aNormal.X()*aNormal.X() < aConf2)
460 aNormal.SetX(0.);
461 if (aNormal.Y()*aNormal.Y() < aConf2)
462 aNormal.SetY(0.);
463 if (aNormal.Z()*aNormal.Z() < aConf2)
464 aNormal.SetZ(0.);
465 arrVec[i] = aNormal.XYZ();
466
467 Standard_Integer j = i * 3;
7f4c4756 468 Normals->SetValue(j + 1, (Standard_ShortReal)aNormal.X());
469 Normals->SetValue(j + 2, (Standard_ShortReal)aNormal.Y());
470 Normals->SetValue(j + 3, (Standard_ShortReal)aNormal.Z());
7fd59977 471
472 }
473
474 theTri->SetNormals(Normals);
475
476 const Handle(VrmlData_Normal) aNormalNode =
477 new VrmlData_Normal (myScene, 0L, nNodes, arrVec);
478 myScene.AddNode (aNormalNode, Standard_False);
479 aFaceSet->SetNormals (aNormalNode);
480 }
481 }
482
5b111128 483 return Handle(VrmlData_Geometry) (aFaceSet);
7fd59977 484}
485
486//=======================================================================
487//function : polToIndexedLineSet
488//purpose : single polygon3D => IndexedLineSet
489//=======================================================================
490
857ffd5e 491Handle(VrmlData_Geometry) VrmlData_ShapeConvert::polToIndexedLineSet
492 (const Handle(Poly_Polygon3D)& thePol)
7fd59977 493{
494 Standard_Integer i;
495 const Standard_Integer nNodes (thePol->NbNodes());
496 const TColgp_Array1OfPnt& arrPolyNodes = thePol->Nodes();
497 const Handle(NCollection_IncAllocator)& anAlloc = myScene.Allocator();
498
499 const Handle(VrmlData_IndexedLineSet) aLineSet =
500 new VrmlData_IndexedLineSet (myScene, 0L);
501
502 // Create the array of polygons (1 member)
503 const Standard_Integer ** arrPolygons = static_cast<const Standard_Integer **>
504 (anAlloc->Allocate (sizeof(const Standard_Integer *)));
505 aLineSet->SetPolygons (1, arrPolygons);
506
507 // Store the polygon
508 Standard_Integer * aPolygon = static_cast<Standard_Integer *>
509 (anAlloc->Allocate ((nNodes+1)*sizeof(Standard_Integer)));
510 aPolygon[0] = nNodes;
511 for (i = 1; i <= nNodes; i++)
512 aPolygon[i] = i-1;
513 arrPolygons[0] = aPolygon;
514
515 // Create the Coordinates node
516 gp_XYZ * arrNodes = static_cast <gp_XYZ *>
517 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
518 for (i = 0; i < nNodes; i++)
519 arrNodes[i] = arrPolyNodes(i+1).XYZ() * myScale;
520
521 const Handle(VrmlData_Coordinate) aCoordNode =
522 new VrmlData_Coordinate (myScene, 0L, nNodes, arrNodes);
523 myScene.AddNode (aCoordNode, Standard_False);
524 aLineSet->SetCoordinates (aCoordNode);
525
5b111128 526 return Handle(VrmlData_Geometry) (aLineSet);
7fd59977 527}
528
529//=======================================================================
530//function : defaultMaterialFace
531//purpose :
532//=======================================================================
533
534Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialFace () const
535{
536 static char aNodeName[] = "__defaultMaterialFace";
537 Handle(VrmlData_Appearance) anAppearance =
538 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName));
539 if (anAppearance.IsNull()) {
540 const Handle(VrmlData_Material) aMaterial =
541 new VrmlData_Material (myScene, 0L, 1.0, 0.022, 0.);
542 aMaterial->SetDiffuseColor (Quantity_Color(0.780392, 0.568627, 0.113725,
543 Quantity_TOC_RGB));
544 aMaterial->SetEmissiveColor(Quantity_Color(0.329412, 0.223529, 0.027451,
545 Quantity_TOC_RGB));
546 aMaterial->SetSpecularColor(Quantity_Color(0.992157, 0.941176, 0.807843,
547 Quantity_TOC_RGB));
548 myScene.AddNode (aMaterial, Standard_False);
549 anAppearance = new VrmlData_Appearance (myScene, aNodeName);
550 anAppearance->SetMaterial (aMaterial);
551 myScene.AddNode (anAppearance, Standard_False);
552 }
553 return anAppearance;
554}
555
556//=======================================================================
557//function : defaultMaterialEdge
558//purpose :
559//=======================================================================
560
561Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialEdge () const
562{
563 static char aNodeName[] = "__defaultMaterialEdge";
564 Handle(VrmlData_Appearance) anAppearance =
565 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName));
566 if (anAppearance.IsNull()) {
567 const Handle(VrmlData_Material) aMaterial =
568 new VrmlData_Material (myScene, 0L, 0.2, 0.2, 0.2);
569 aMaterial->SetDiffuseColor (Quantity_Color(0.2, 0.7, 0.2,
570 Quantity_TOC_RGB));
571 aMaterial->SetEmissiveColor(Quantity_Color(0.2, 0.7, 0.2,
572 Quantity_TOC_RGB));
573 aMaterial->SetSpecularColor(Quantity_Color(0.2, 0.7, 0.2,
574 Quantity_TOC_RGB));
575 myScene.AddNode (aMaterial, Standard_False);
576 anAppearance = new VrmlData_Appearance (myScene, aNodeName);
577 anAppearance->SetMaterial (aMaterial);
578 myScene.AddNode (anAppearance, Standard_False);
579 }
580 return anAppearance;
581}
a3506de7 582
583
584//=======================================================================
585//function : addShape
586//purpose : Adds the shape from the document
587//=======================================================================
588void VrmlData_ShapeConvert::addShape (const Handle(VrmlData_Group)& theParent,
589 const TDF_Label& theLabel,
590 const Handle(TDocStd_Document)& theDoc)
591{
592 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
593 Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(theDoc->Main());
594
595 NCollection_DataMap<TopoDS_Shape, TDF_Label> aChildShapeToLabels;
596 TDF_LabelSequence aChildLabels;
597 aShapeTool->GetSubShapes(theLabel, aChildLabels);
598 for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
599 {
600 const TDF_Label& aChildLabel = aChildIter.Value();
601 TopoDS_Shape aChildShape;
602 if (aShapeTool->GetShape(aChildLabel, aChildShape))
603 {
604 aChildShapeToLabels.Bind(aChildShape, aChildLabel);
605 }
606 }
607
608 const TopoDS_Shape aShape = aShapeTool->GetShape(theLabel);
609 Handle(VrmlData_Group) aGroup = 0L;
610 TopExp_Explorer anExp(aShape, TopAbs_FACE);
611 Standard_Integer nbFaces = 0;
612 for (; anExp.More(); anExp.Next()) {
613 nbFaces++;
614 }
615 Handle(TDataStd_Name) aNameAttribute;
616 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
617 if (nbFaces > 1)
618 {
619 if (!aNameAttribute.IsNull())
620 {
621 TCollection_AsciiString aName = aNameAttribute->Get();
622 aGroup = new VrmlData_Group(myScene, aName.ToCString());
623 }
624 else
625 {
626 aGroup = new VrmlData_Group(myScene, 0L);
627 }
628 myScene.AddNode(aGroup, theParent.IsNull());
629 if (!theParent.IsNull())
630 {
631 theParent->AddNode(aGroup);
632 }
633 }
634
635 anExp.Init(aShape, TopAbs_FACE);
636 for (; anExp.More(); anExp.Next()) {
637 TopLoc_Location aLoc;
638 Handle(VrmlData_Geometry) aTShapeNode =
639 makeTShapeNode(anExp.Current(), TopAbs_FACE, aLoc);
640 if (!aTShapeNode.IsNull())
641 {
642 Handle(VrmlData_ShapeNode) aShapeNode = 0L;
643 if (aGroup.IsNull() && !aNameAttribute.IsNull())
644 {
645 TCollection_AsciiString aName = aNameAttribute->Get();
646 aName.ChangeAll(' ', '_');
647 aShapeNode = new VrmlData_ShapeNode(myScene, aName.ToCString());
648 }
649 else
650 {
651 aShapeNode = new VrmlData_ShapeNode(myScene, 0L);
652 }
653
654 // set color
655 TDF_Label aColorL;
656 Standard_Boolean findColor = Standard_False;
657 const TDF_Label* aLabel = aChildShapeToLabels.Seek(anExp.Current());
658 if (aLabel != NULL)
659 {
660 findColor = aColorTool->GetColor(*aLabel, XCAFDoc_ColorSurf, aColorL)
661 || aColorTool->GetColor(*aLabel, XCAFDoc_ColorGen, aColorL);
662 }
663 if (!findColor)
664 {
665 findColor = aColorTool->GetColor(theLabel, XCAFDoc_ColorSurf, aColorL)
666 || aColorTool->GetColor(theLabel, XCAFDoc_ColorGen, aColorL);
667 }
668 if (!findColor)
669 {
670 aShapeNode->SetAppearance(defaultMaterialFace());
671 }
672 else
673 {
674 aShapeNode->SetAppearance(makeMaterialFromColor(aColorL, aColorTool));
675 }
676
677 myScene.AddNode(aShapeNode, Standard_False);
678 aShapeNode->SetGeometry(aTShapeNode);
679 if (aLoc.IsIdentity())
680 {
681 // Store the shape node directly into the main Group.
682 if (!aGroup.IsNull())
683 {
684 aGroup->AddNode(aShapeNode);
685 }
686 else
687 {
688 theParent->AddNode(aShapeNode);
689 }
690 }
691 else
692 {
693 // Create a Transform grouping node
694 Handle(VrmlData_Group) aTrans = new VrmlData_Group(myScene, 0L,
695 Standard_True);
696 gp_Trsf aTrsf(aLoc);
697 if (fabs(myScale - 1.) > Precision::Confusion())
698 {
699 aTrsf.SetScaleFactor(myScale);
700 }
701 aTrans->SetTransform(aTrsf);
702 myScene.AddNode(aTrans, Standard_False);
703 if (!aGroup.IsNull())
704 {
705 aGroup->AddNode(aTrans);
706 }
707 else
708 {
709 theParent->AddNode(aTrans);
710 }
711 // Store the shape node under the transform.
712 aTrans->AddNode(aShapeNode);
713 }
714 }
715 }
716}
717
718
719//=======================================================================
720//function : addInstance
721//purpose : Adds the reference from the document
722//=======================================================================
723void VrmlData_ShapeConvert::addInstance (const Handle(VrmlData_Group)& theParent,
724 const TDF_Label& theLabel,
725 const Handle(TDocStd_Document)& theDoc)
726{
727 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
728
729 const TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
730 Handle(VrmlData_Group) aTrans = 0L;
731 if (!aLoc.IsIdentity())
732 {
733 // Create a Transform grouping node
734 aTrans = new VrmlData_Group(myScene, 0L, Standard_True);
735 gp_Trsf aTrsf(aLoc);
736 if (fabs(myScale - 1.) > Precision::Confusion()) {
737 aTrsf.SetScaleFactor(myScale);
738 }
739 aTrans->SetTransform(aTrsf);
740 myScene.AddNode(aTrans, theParent.IsNull());
741 if (!theParent.IsNull())
742 {
743 theParent->AddNode(aTrans);
744 }
745 }
746
747 Handle(TDataStd_Name) aNameAttribute;
748 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
749
750 TDF_Label aRefLabel;
751 aShapeTool->GetReferredShape(theLabel, aRefLabel);
752 Handle(TDataStd_Name) aRefNameAttribute;
753 aRefLabel.FindAttribute(TDataStd_Name::GetID(), aRefNameAttribute);
754
755 if (aShapeTool->IsSimpleShape(aRefLabel))
756 {
757 addShape((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc);
758 }
759 else if (aShapeTool->IsAssembly(aRefLabel))
760 {
761 addAssembly((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc, aTrans.IsNull());
762 }
763}
764
765
766//=======================================================================
767//function : addAssembly
768//purpose : Adds the assembly from the document
769//=======================================================================
770void VrmlData_ShapeConvert::addAssembly (const Handle(VrmlData_Group)& theParent,
771 const TDF_Label& theLabel,
772 const Handle(TDocStd_Document)& theDoc,
773 const Standard_Boolean theNeedCreateGroup)
774{
775 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
776
777 Handle(VrmlData_Group) anAssembly = 0L;
778 if (theNeedCreateGroup)
779 {
780 Handle(TDataStd_Name) aNameAttribute;
781 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
782 if (!aNameAttribute.IsNull())
783 {
784 TCollection_AsciiString aName = aNameAttribute->Get();
785 anAssembly = new VrmlData_Group(myScene, aName.ToCString());
786 }
787 else
788 {
789 anAssembly = new VrmlData_Group(myScene, 0L);
790 }
791 TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
792 if (!aLoc.IsIdentity())
793 {
794 gp_Trsf aTrsf(aLoc);
795 if (fabs(myScale - 1.) > Precision::Confusion()) {
796 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
797 aTrsf.SetTranslationPart(aTransl);
798 }
799 anAssembly->SetTransform(aTrsf);
800 }
801 myScene.AddNode(anAssembly, theParent.IsNull());
802 if (!theParent.IsNull())
803 {
804 theParent->AddNode(anAssembly);
805 }
806 }
807
808 TDF_LabelSequence aChildLabels;
809 aShapeTool->GetComponents(theLabel, aChildLabels);
810 for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
811 {
812 const TDF_Label& aChildLabel = aChildIter.Value();
813 if (aShapeTool->IsAssembly(aChildLabel))
814 {
815 addAssembly((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc, anAssembly.IsNull());
816 }
817 else if (aShapeTool->IsReference(aChildLabel))
818 {
819 addInstance((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
820 }
821 else if (aShapeTool->IsSimpleShape(aChildLabel))
822 {
823 addShape((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
824 }
825 }
826}
827
828
829//=======================================================================
830//function : ConvertDocument
831//purpose :
832//=======================================================================
833void VrmlData_ShapeConvert::ConvertDocument(const Handle(TDocStd_Document) &theDoc)
834{
835 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
836
837 TDF_LabelSequence aFreeShapeLabels;
838 aShapeTool->GetFreeShapes(aFreeShapeLabels);
839
840 Handle(VrmlData_Group) aGroup = 0L;
841 if (aFreeShapeLabels.Size() > 1)
842 {
843 aGroup = new VrmlData_Group(myScene, 0L);
844 myScene.AddNode(aGroup);
845 }
846
847 for (TDF_LabelSequence::Iterator aRootIter(aFreeShapeLabels); aRootIter.More(); aRootIter.Next())
848 {
849 const TDF_Label& aFreeShapeLabel = aRootIter.Value();
850 if (aShapeTool->IsSimpleShape(aFreeShapeLabel))
851 {
852 addShape(aGroup, aFreeShapeLabel, theDoc);
853 }
854 else if (aShapeTool->IsAssembly(aFreeShapeLabel))
855 {
856 addAssembly(aGroup, aFreeShapeLabel, theDoc, Standard_True);
857 }
858 }
859}
860
861
862//=======================================================================
863//function : makeMaterialFromColor
864//purpose :
865//=======================================================================
866
867Handle(VrmlData_Appearance) VrmlData_ShapeConvert::makeMaterialFromColor(
868 const TDF_Label& theColorL,
869 const Handle(XCAFDoc_ColorTool)& theColorTool) const
870{
871 Quantity_ColorRGBA aColor;
872 theColorTool->GetColor(theColorL, aColor);
873
874 TCollection_AsciiString aNodeName = "_materialFace_";
875 Handle(TDataStd_Name) aNameAttribute;
876 if (theColorL.FindAttribute(TDataStd_Name::GetID(), aNameAttribute))
877 {
878 aNodeName.AssignCat(aNameAttribute->Get());
879 Standard_Integer n = aNodeName.Search(" ");
880 if (n > 0)
881 {
882 aNodeName = aNodeName.SubString(1, n - 1);
883 }
884 }
885 else
886 {
887 aNodeName.AssignCat(aColor.GetRGB().Red());
888 aNodeName.AssignCat("_");
889 aNodeName.AssignCat(aColor.GetRGB().Green());
890 aNodeName.AssignCat("_");
891 aNodeName.AssignCat(aColor.GetRGB().Blue());
892 }
893
894 Handle(VrmlData_Appearance) anAppearance =
895 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName.ToCString()));
896 if (anAppearance.IsNull()) {
897 const Handle(VrmlData_Material) aMaterial =
898 new VrmlData_Material(myScene, 0L);
899 aMaterial->SetDiffuseColor(aColor.GetRGB());
900 myScene.AddNode(aMaterial, Standard_False);
901 anAppearance = new VrmlData_Appearance(myScene, aNodeName.ToCString());
902 anAppearance->SetMaterial(aMaterial);
903 myScene.AddNode(anAppearance, Standard_False);
904 }
905
906 return anAppearance;
907}
908
909