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 | |
63 | void 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 | //======================================================================= |
104 | Handle(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 | |
241 | void 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 |
320 | Handle(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 |
494 | Handle(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 | |
537 | Handle(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 | |
564 | Handle(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 | //======================================================================= |
591 | void 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 | //======================================================================= |
726 | void 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 | //======================================================================= |
773 | void 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 | //======================================================================= |
836 | void 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 | |
870 | Handle(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 | |