0022777: Visualization - Unsafe way to get attribute values from MeshVS_Drawer
[occt.git] / src / MeshVS / MeshVS_MeshPrsBuilder.cxx
1 // Created on: 2003-09-16
2 // Created by: Alexander SOLOVYOV
3 // Copyright (c) 2003-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <Aspect_InteriorStyle.hxx>
18 #include <Graphic3d_ArrayOfPoints.hxx>
19 #include <Graphic3d_ArrayOfPolygons.hxx>
20 #include <Graphic3d_ArrayOfPolylines.hxx>
21 #include <Graphic3d_ArrayOfPrimitives.hxx>
22 #include <Graphic3d_ArrayOfSegments.hxx>
23 #include <Graphic3d_ArrayOfTriangles.hxx>
24 #include <Graphic3d_AspectFillArea3d.hxx>
25 #include <Graphic3d_AspectLine3d.hxx>
26 #include <Graphic3d_AspectMarker3d.hxx>
27 #include <Graphic3d_Group.hxx>
28 #include <MeshVS_Buffer.hxx>
29 #include <MeshVS_DataSource.hxx>
30 #include <MeshVS_Drawer.hxx>
31 #include <MeshVS_DrawerAttribute.hxx>
32 #include <MeshVS_MapOfTwoNodes.hxx>
33 #include <MeshVS_Mesh.hxx>
34 #include <MeshVS_MeshPrsBuilder.hxx>
35 #include <MeshVS_SymmetricPairHasher.hxx>
36 #include <MeshVS_Tool.hxx>
37 #include <NCollection_Map.hxx>
38 #include <NCollection_Vector.hxx>
39 #include <Prs3d_LineAspect.hxx>
40 #include <Prs3d_PointAspect.hxx>
41 #include <Prs3d_Presentation.hxx>
42 #include <Prs3d_Root.hxx>
43 #include <Prs3d_ShadingAspect.hxx>
44 #include <Quantity_NameOfColor.hxx>
45 #include <Select3D_SensitivePoint.hxx>
46 #include <Standard_Type.hxx>
47 #include <TColStd_Array1OfInteger.hxx>
48 #include <TColStd_Array1OfReal.hxx>
49 #include <TColStd_HPackedMapOfInteger.hxx>
50 #include <TColStd_ListIteratorOfListOfReal.hxx>
51 #include <TColStd_MapIntegerHasher.hxx>
52 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
53 #include <TColStd_MapOfInteger.hxx>
54 #include <TColStd_PackedMapOfInteger.hxx>
55 #include <TColStd_SequenceOfInteger.hxx>
56
57 #ifdef _WIN32
58   #include <malloc.h> // for alloca()
59 #endif
60
61 IMPLEMENT_STANDARD_RTTIEXT(MeshVS_MeshPrsBuilder,MeshVS_PrsBuilder)
62
63 //================================================================
64 // Function : Constructor MeshVS_MeshPrsBuilder
65 // Purpose  :
66 //================================================================
67 MeshVS_MeshPrsBuilder::MeshVS_MeshPrsBuilder ( const Handle(MeshVS_Mesh)& Parent,
68                                                const Standard_Integer& DisplayModeMask,
69                                                const Handle (MeshVS_DataSource)& DS,
70                                                const Standard_Integer Id,
71                                                const MeshVS_BuilderPriority& Priority )
72 : MeshVS_PrsBuilder ( Parent, DisplayModeMask, DS, Id, Priority )
73 {
74 }
75
76 //================================================================
77 // Function : Build
78 // Purpose  :
79 //================================================================
80 void MeshVS_MeshPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
81                                     const TColStd_PackedMapOfInteger& IDs,
82                                     TColStd_PackedMapOfInteger& IDsToExclude,
83                                     const Standard_Boolean IsElement,
84                                     const Standard_Integer DisplayMode ) const
85 {
86   if ( DisplayMode <= 0 )
87     return;
88
89   Standard_Boolean HasHilightFlag = ( ( DisplayMode & MeshVS_DMF_HilightPrs ) != 0 );
90   Standard_Integer Extent = IDs.Extent();
91
92   if ( HasHilightFlag && Extent == 1)
93     BuildHilightPrs ( Prs, IDs, IsElement );
94   else if ( IsElement )
95     BuildElements ( Prs, IDs, IDsToExclude, DisplayMode );
96   else
97     BuildNodes ( Prs, IDs, IDsToExclude, DisplayMode );
98 }
99
100 //================================================================
101 // Function : BuildNodes
102 // Purpose  :
103 //================================================================
104 void MeshVS_MeshPrsBuilder::BuildNodes ( const Handle(Prs3d_Presentation)& Prs,
105                                          const TColStd_PackedMapOfInteger& IDs,
106                                          TColStd_PackedMapOfInteger& IDsToExclude,
107                                          const Standard_Integer DisplayMode ) const
108 {
109   Handle( MeshVS_DataSource ) aSource = GetDataSource();
110   Handle( MeshVS_Drawer )     aDrawer = GetDrawer();
111   Handle (Graphic3d_AspectMarker3d) aNodeMark =
112     MeshVS_Tool::CreateAspectMarker3d( GetDrawer() );
113   if ( aSource.IsNull() || aDrawer.IsNull() || aNodeMark.IsNull() )
114     return;
115
116   Standard_Boolean DisplayFreeNodes = Standard_True;
117   aDrawer->GetBoolean( MeshVS_DA_DisplayNodes, DisplayFreeNodes );
118   Standard_Boolean HasSelectFlag = ( ( DisplayMode & MeshVS_DMF_SelectionPrs ) != 0 );
119   Standard_Boolean HasHilightFlag = ( ( DisplayMode & MeshVS_DMF_HilightPrs ) != 0 );
120
121   Standard_Real aCoordsBuf[ 3 ];
122   TColStd_Array1OfReal aCoords( *aCoordsBuf, 1, 3 );
123   Standard_Integer NbNodes;
124   MeshVS_EntityType aType;
125
126   if ( !DisplayFreeNodes )
127     return;
128
129   TColStd_PackedMapOfInteger anIDs;
130   anIDs.Assign( IDs );
131   if ( !HasSelectFlag && !HasHilightFlag )
132   {
133     // subtract the hidden nodes and ids to exclude (to minimize allocated memory)
134     Handle(TColStd_HPackedMapOfInteger) aHiddenNodes = myParentMesh->GetHiddenNodes();
135     if ( !aHiddenNodes.IsNull() )
136       anIDs.Subtract( aHiddenNodes->Map() );
137   }
138   anIDs.Subtract( IDsToExclude );
139
140   Standard_Integer upper = anIDs.Extent();
141   if ( upper<=0 )
142     return;
143
144   Handle(Graphic3d_ArrayOfPoints) aNodePoints = new Graphic3d_ArrayOfPoints (upper);
145   Standard_Integer k=0;
146   TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
147   for( ; it.More(); it.Next() )
148   {
149     Standard_Integer aKey = it.Key();
150     if ( aSource->GetGeom ( aKey, Standard_False, aCoords, NbNodes, aType ) )
151     {
152       if ( IsExcludingOn() )
153         IDsToExclude.Add (aKey);
154       k++;
155       aNodePoints->AddVertex (aCoords(1), aCoords(2), aCoords(3));
156     }
157   }
158
159   if ( k>0 )
160   {
161     Prs3d_Root::NewGroup ( Prs );
162     Handle (Graphic3d_Group) aNodeGroup = Prs3d_Root::CurrentGroup ( Prs );
163     aNodeGroup->SetPrimitivesAspect ( aNodeMark );
164     aNodeGroup->AddPrimitiveArray (aNodePoints);
165   }
166 }
167
168 //================================================================
169 // Function : BuildElements
170 // Purpose  :
171 //================================================================
172 void MeshVS_MeshPrsBuilder::BuildElements( const Handle(Prs3d_Presentation)& Prs,
173                                            const TColStd_PackedMapOfInteger& IDs,
174                                            TColStd_PackedMapOfInteger& IDsToExclude,
175                                            const Standard_Integer DisplayMode ) const
176 {
177   Standard_Integer maxnodes;
178
179   Handle(MeshVS_DataSource) aSource = GetDataSource();
180   if ( aSource.IsNull() )
181     return;
182
183   Handle( MeshVS_Drawer ) aDrawer = GetDrawer();
184   if ( aDrawer.IsNull() || !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, maxnodes ) ||
185        maxnodes <= 0 )
186     return;
187
188   //----------- extract useful display mode flags ----------
189   Standard_Integer aDispMode = ( DisplayMode & GetFlags() );
190   if ( ( aDispMode & MeshVS_DMF_DeformedMask) != 0 )
191   {
192     aDispMode /= MeshVS_DMF_DeformedPrsWireFrame;
193     // This transformation turns deformed mesh flags to real display modes
194   }
195   aDispMode &= MeshVS_DMF_OCCMask;
196   //--------------------------------------------------------
197
198   Standard_Real aShrinkCoef = 0.0;
199   aDrawer->GetDouble ( MeshVS_DA_ShrinkCoeff, aShrinkCoef );
200
201   Standard_Boolean IsWireFrame    = ( aDispMode==MeshVS_DMF_WireFrame ),
202                    IsShading      = ( aDispMode==MeshVS_DMF_Shading ),
203                    IsShrink       = ( aDispMode==MeshVS_DMF_Shrink ),
204                    HasHilightFlag = ( ( DisplayMode & MeshVS_DMF_HilightPrs )   != 0 ),
205                    HasSelectFlag  = ( ( DisplayMode & MeshVS_DMF_SelectionPrs ) != 0 ),
206                    IsMeshReflect = Standard_False, IsMeshAllowOverlap = Standard_False,
207                    IsMeshSmoothShading = Standard_False;
208
209   aDrawer->GetBoolean  ( MeshVS_DA_Reflection, IsMeshReflect );
210   aDrawer->GetBoolean  ( MeshVS_DA_IsAllowOverlapped, IsMeshAllowOverlap );
211   const Standard_Boolean IsReflect = ( IsMeshReflect && !HasHilightFlag );
212   aDrawer->GetBoolean  ( MeshVS_DA_SmoothShading, IsMeshSmoothShading );
213
214   // display mode for highlighted prs of groups
215   IsShrink       = ( IsShrink && !HasHilightFlag );
216   IsShading      = ( IsShading || HasHilightFlag );
217
218   //---------- Creating AspectFillArea3d and AspectLine3d -------------
219   Graphic3d_MaterialAspect AMat;
220   aDrawer->GetMaterial ( MeshVS_DA_FrontMaterial, AMat );
221   if ( !IsReflect )
222   {
223     AMat.SetAmbientColor (Quantity_NOC_BLACK);
224     AMat.SetDiffuseColor (Quantity_NOC_BLACK);
225     AMat.SetSpecularColor(Quantity_NOC_BLACK);
226     AMat.SetEmissiveColor(Quantity_NOC_BLACK);
227   }
228   Handle( Graphic3d_AspectFillArea3d ) aFill = MeshVS_Tool::CreateAspectFillArea3d( GetDrawer(), AMat );
229   Handle( Graphic3d_AspectLine3d ) aBeam = MeshVS_Tool::CreateAspectLine3d ( GetDrawer() );
230   //-------------------------------------------------------------------
231
232   Standard_Boolean IsOverlapControl =
233     !IsMeshAllowOverlap && ( IsWireFrame || IsShading ) && !HasSelectFlag;
234
235   // subtract the hidden elements and ids to exclude (to minimize allocated memory)
236   TColStd_PackedMapOfInteger anIDs;
237   anIDs.Assign( IDs );
238   Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
239   if ( !aHiddenElems.IsNull() )
240     anIDs.Subtract( aHiddenElems->Map() );
241   anIDs.Subtract( IDsToExclude );
242
243   Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
244   TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
245
246   Standard_Boolean showEdges = Standard_True;
247   aDrawer->GetBoolean( MeshVS_DA_ShowEdges, showEdges );
248
249   showEdges = IsWireFrame || showEdges;
250
251   Standard_Integer* aNodesBuf  = (Standard_Integer*) alloca (maxnodes * sizeof (Standard_Integer));
252   Standard_Real*    aCoordsBuf = (Standard_Real*)    alloca (3 * maxnodes * sizeof (Standard_Real));
253
254   TColStd_Array1OfInteger aNodes  (*aNodesBuf, 1, maxnodes);
255   TColStd_Array1OfReal    aCoords (*aCoordsBuf, 1, 3 * maxnodes);
256
257   Standard_Integer aNbFacePrimitives = 0;
258   Standard_Integer aNbVolmPrimitives = 0;
259   Standard_Integer aNbEdgePrimitives = 0;
260   Standard_Integer aNbLinkPrimitives = 0;
261
262   MeshVS_EntityType aType;
263
264   for (it.Reset(); it.More(); it.Next())
265   {
266     Standard_Integer aNbNodes = 0;
267
268     if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType))
269       continue;
270
271     if (aType == MeshVS_ET_Volume)
272     {
273       if (aSource->Get3DGeom (it.Key(), aNbNodes, aTopo))
274       {
275         for (Standard_Integer aFaceIdx = aTopo->Lower(); aFaceIdx <= aTopo->Upper(); ++aFaceIdx)
276         {
277           const TColStd_SequenceOfInteger& aFaceNodes = aTopo->Value (aFaceIdx);
278           
279           if (showEdges) // add edge segments
280           {
281             aNbEdgePrimitives += aFaceNodes.Length();
282           }
283           
284           if (IsShading || IsShrink) // add volumetric cell triangles
285           {
286             if (!HasSelectFlag)
287               aNbVolmPrimitives += aFaceNodes.Length() - 2;
288           }
289         }
290       }
291     }
292     else if (aType == MeshVS_ET_Link)
293     {
294       if (showEdges)
295       {
296         aNbLinkPrimitives += 1; // add link segment
297       }
298     }
299     else if (aType == MeshVS_ET_Face)
300     {
301       if (showEdges)
302       {
303         aNbEdgePrimitives += aNbNodes; // add edge segments
304       }
305
306       if (!IsOverlapControl || IsShading)
307       {
308         if ((IsShading || IsShrink) && !HasSelectFlag)
309         {
310           aNbFacePrimitives += aNbNodes - 2; // add face triangles
311         }
312       }
313     }
314   }
315
316   // Here we do not use indices arrays because they are not effective for some mesh
317   // drawing modes: shrinking mode (displaces the vertices inside the polygon), 3D
318   // cell rendering (normal interpolation is not always applicable - flat shading),
319   // elemental coloring (color interpolation is impossible)
320   Handle (Graphic3d_ArrayOfTriangles) aVolmTriangles =
321     new Graphic3d_ArrayOfTriangles (aNbVolmPrimitives * 3, 0, IsReflect);
322   Handle (Graphic3d_ArrayOfTriangles) aFaceTriangles =
323     new Graphic3d_ArrayOfTriangles (aNbFacePrimitives * 3, 0, IsReflect);
324
325   Handle (Graphic3d_ArrayOfSegments) aLinkSegments;
326   Handle (Graphic3d_ArrayOfSegments) aEdgeSegments;
327
328   if (showEdges)
329   {
330     aLinkSegments = new Graphic3d_ArrayOfSegments (aNbLinkPrimitives * 2);
331     aEdgeSegments = new Graphic3d_ArrayOfSegments (aNbEdgePrimitives * 2);
332   }
333
334   TColStd_PackedMapOfInteger aCustomElements;
335
336   Quantity_Color anOldEdgeColor;
337   Quantity_Color anEdgeColor = aFill->EdgeColor();
338   MeshVS_MapOfTwoNodes aLinkNodes;
339   
340   // Forbid drawings of edges which overlap with some links
341   if (showEdges && IsOverlapControl)
342   {
343     for (it.Reset(); it.More(); it.Next())
344     {
345       if (aSource->GetGeomType (it.Key(), Standard_True, aType) && aType == MeshVS_ET_Link)
346       {
347         Standard_Integer aNbNodes;
348
349         if (aSource->GetNodesByElement (it.Key(), aNodes, aNbNodes) && aNbNodes == 2)
350         {
351           aLinkNodes.Add (MeshVS_TwoNodes (aNodes(1), aNodes(2)));
352         }
353       }
354     }
355   }
356
357   NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher> aSegmentMap;
358
359   for (it.Reset(); it.More(); it.Next())
360   {
361     const Standard_Integer aKey = it.Key();
362
363     Standard_Integer NbNodes;
364     if (!aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType))
365       continue;
366
367     if (!aSource->GetNodesByElement (aKey, aNodes, NbNodes))
368       continue;
369
370     switch (aType)
371     {
372       case MeshVS_ET_Volume:
373       {
374         if (IsExcludingOn())
375           IDsToExclude.Add (aKey);
376
377         if (aSource->Get3DGeom (aKey, NbNodes, aTopo))
378         {
379           // Add wire-frame presentation (draw edges for shading mode as well)
380           if (showEdges)
381           {
382             AddVolumePrs (aTopo, aCoords, NbNodes,
383               aEdgeSegments, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef);
384           }
385
386           // Add shading presentation
387           if ((IsShading || IsShrink) && !HasSelectFlag)
388           {
389             AddVolumePrs (aTopo, aCoords, NbNodes,
390               aVolmTriangles, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef);
391           }
392         }
393       }
394       break;
395
396       case MeshVS_ET_Link:
397       {
398         if (IsExcludingOn())
399           IDsToExclude.Add (aKey);
400
401         if (showEdges)
402         {
403           AddLinkPrs (aCoords, aLinkSegments, IsShrink || HasSelectFlag, aShrinkCoef);
404         }
405       }
406       break;
407
408       case MeshVS_ET_Face:
409       {
410         if (IsExcludingOn())
411           IDsToExclude.Add (aKey);
412
413         if (showEdges && IsOverlapControl)
414         {
415           Standard_Integer Last = 0;
416
417           MeshVS_TwoNodes aTwoNodes (aNodes (1));
418
419           for (Standard_Integer i = 1; i <= NbNodes; ++i)
420           {
421             if (i > 1)
422               aTwoNodes.First = aTwoNodes.Second;
423
424             aTwoNodes.Second = (i < NbNodes) ? aNodes (i+1) : aNodes (1);
425
426             if (aLinkNodes.Contains (aTwoNodes))
427             {
428               for (Standard_Integer aNodeIdx = Last + 1; aNodeIdx < i; ++aNodeIdx)
429               {
430                 const Standard_Integer aNextIdx = aNodeIdx + 1;
431
432                 aEdgeSegments->AddVertex (
433                   aCoords (3 * aNodeIdx - 2), aCoords (3 * aNodeIdx - 1), aCoords (3 * aNodeIdx));
434                 aEdgeSegments->AddVertex (
435                   aCoords (3 * aNextIdx - 2), aCoords (3 * aNextIdx - 1), aCoords (3 * aNextIdx));
436               }
437
438               Last = i;
439             }
440           }
441
442           if (NbNodes - Last > 0)
443           {
444             for (Standard_Integer aNodeIdx = Last; aNodeIdx < NbNodes; ++aNodeIdx)
445             {
446               const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes;
447               
448               const MeshVS_NodePair aSegment (aNodes (aNodeIdx + 1),
449                                               aNodes (aNextIdx + 1));
450
451               if (!aSegmentMap.Contains (aSegment))
452               {
453                 aEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
454                                           aCoords (3 * aNodeIdx + 2),
455                                           aCoords (3 * aNodeIdx + 3));
456
457                 aEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1),
458                                           aCoords (3 * aNextIdx + 2),
459                                           aCoords (3 * aNextIdx + 3));
460
461                 aSegmentMap.Add (aSegment);
462               }
463             }
464           }
465         }
466
467         if (!IsOverlapControl || IsShading)
468         {
469           if (!IsOverlapControl && showEdges)
470           {
471             AddFaceWirePrs (aCoords, NbNodes,
472               aEdgeSegments, IsShrink || HasSelectFlag, aShrinkCoef);
473           }
474
475           if ((IsShading || IsShrink) && !HasSelectFlag)
476           {
477             AddFaceSolidPrs (aKey, aCoords, NbNodes, maxnodes, aFaceTriangles, IsReflect,
478               IsShrink || HasSelectFlag, aShrinkCoef, IsMeshSmoothShading);
479           }
480         }
481       }
482       break;
483
484       default:
485       {
486         aCustomElements.Add (aKey);
487       }
488     }
489   }
490
491   if (IsShrink)
492   {
493     anOldEdgeColor = anEdgeColor;
494     aFill->SetEdgeColor (Quantity_NOC_BLACK);
495   }
496
497   //std::cout << "Actual extents: " << std::endl
498   //  << "Face tris: " << aFaceTriangles->ItemNumber() << " from " << aNbFacePrimitives << std::endl
499   //  << "Volm tris: " << aVolmTriangles->ItemNumber()  << " from " << aNbVolmPrimitives << std::endl
500   //  << "Face segs: " << aEdgeSegments->ItemNumber()  << " from " << aNbEdgePrimitives << std::endl
501   //  << "Link segs: " << aLinkSegments->ItemNumber()  << " from " << aNbLinkPrimitives << std::endl;
502
503   DrawArrays ( Prs, aFaceTriangles, aEdgeSegments, aLinkSegments, aVolmTriangles,
504     !showEdges, HasSelectFlag, aFill, aBeam );
505
506   if ( !aCustomElements.IsEmpty() )
507     CustomBuild ( Prs, aCustomElements, IDsToExclude, DisplayMode );
508
509   if( IsShrink )
510     aFill->SetEdgeColor( anOldEdgeColor );
511 }
512
513 //================================================================
514 // Function : BuildHilightPrs
515 // Purpose  :
516 //================================================================
517 void MeshVS_MeshPrsBuilder::BuildHilightPrs ( const Handle(Prs3d_Presentation)& Prs,
518                                               const TColStd_PackedMapOfInteger& IDs,
519                                               const Standard_Boolean IsElement ) const
520 {
521   Standard_Integer maxnodes;
522
523   Handle (MeshVS_DataSource) aSource = GetDataSource();
524   if ( aSource.IsNull() || IDs.IsEmpty() )
525     return;
526
527   Handle( MeshVS_Drawer ) aDrawer = GetDrawer();
528   if ( aDrawer.IsNull() || !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, maxnodes ) ||
529        maxnodes <= 0 )
530     return;
531
532   MeshVS_Buffer aCoordsBuf (3*maxnodes*sizeof(Standard_Real));
533   TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3*maxnodes);
534
535   Graphic3d_MaterialAspect AMat;
536   aDrawer->GetMaterial ( MeshVS_DA_FrontMaterial, AMat );
537   AMat.SetAmbientColor (Quantity_NOC_BLACK);
538   AMat.SetDiffuseColor (Quantity_NOC_BLACK);
539   AMat.SetSpecularColor(Quantity_NOC_BLACK);
540   AMat.SetEmissiveColor(Quantity_NOC_BLACK);
541
542   Handle( Graphic3d_AspectFillArea3d ) aFill     = MeshVS_Tool::CreateAspectFillArea3d( GetDrawer(), AMat );
543   Handle( Graphic3d_AspectLine3d )     aBeam     = MeshVS_Tool::CreateAspectLine3d( GetDrawer() );
544   Handle( Graphic3d_AspectMarker3d )   aNodeMark = MeshVS_Tool::CreateAspectMarker3d( GetDrawer() );
545
546   // Hilight one element or node
547   TColStd_MapIteratorOfPackedMapOfInteger it (IDs);
548   Standard_Integer ID = it.Key(), NbNodes;
549   MeshVS_EntityType aType;
550
551   if ( !aSource->GetGeom ( ID, IsElement, aCoords, NbNodes, aType ) )
552     return;
553
554   Prs3d_Root::NewGroup ( Prs );
555   Handle (Graphic3d_Group) aHilightGroup = Prs3d_Root::CurrentGroup ( Prs );
556
557   switch ( aType )
558   {
559     case MeshVS_ET_Node :
560     {
561       aHilightGroup->SetPrimitivesAspect (aNodeMark);
562       Handle(Graphic3d_ArrayOfPoints) anArrayOfPoints = new Graphic3d_ArrayOfPoints (1);
563       anArrayOfPoints->AddVertex (aCoords(1), aCoords(2), aCoords(3));
564       aHilightGroup->AddPrimitiveArray (anArrayOfPoints);
565     }
566     break;
567
568     case MeshVS_ET_Link:
569     {
570       aHilightGroup->SetPrimitivesAspect ( aBeam );
571       Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(2);
572       aPrims->AddVertex(aCoords(1),aCoords(2),aCoords(3));
573       aPrims->AddVertex(aCoords(4),aCoords(5),aCoords(6));
574       aHilightGroup->AddPrimitiveArray(aPrims);
575     }
576     break;
577
578     case MeshVS_ET_Face:
579     if ( NbNodes > 0 )
580     {
581       aHilightGroup->SetPrimitivesAspect ( aFill );
582       Handle(Graphic3d_ArrayOfPolygons) aPrims = new Graphic3d_ArrayOfPolygons(NbNodes);
583       for ( Standard_Integer k=1; k<=NbNodes; k++)
584         aPrims->AddVertex(aCoords(3*k-2),aCoords(3*k-1),aCoords(3*k));
585       aHilightGroup->AddPrimitiveArray(aPrims);
586     }
587     break;
588
589     case MeshVS_ET_Volume:
590     if( NbNodes > 0 )
591     {
592       Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
593
594       aHilightGroup->SetPrimitivesAspect ( aFill );
595
596       if( aSource->Get3DGeom( ID, NbNodes, aTopo ) )
597       {
598         const Standard_Integer up = aTopo->Upper();
599         const Standard_Integer lo = aTopo->Lower();
600         Standard_Integer nbnodes = 0, i, j;
601         for( i=lo; i<=up; i++ )
602           nbnodes += aTopo->Value( i ).Length();
603
604         Handle(Graphic3d_ArrayOfPolygons) aPrims = new Graphic3d_ArrayOfPolygons(nbnodes,aTopo->Length());
605         for( i=lo; i<=up; i++ )
606         {
607           const TColStd_SequenceOfInteger& aSeq = aTopo->Value( i );
608           const Standard_Integer m = aSeq.Length();
609           aPrims->AddBound(m);
610           for( j=1; j<=m; j++ )
611           {
612             const Standard_Integer ind = 3*aSeq.Value( j );
613             aPrims->AddVertex(aCoords(ind+1),aCoords(ind+2),aCoords(ind+3));
614           }
615         }
616         aHilightGroup->AddPrimitiveArray(aPrims);
617       }
618     }
619     break;
620
621     default:
622       {
623         TColStd_PackedMapOfInteger tmp;
624         CustomBuild ( Prs, IDs, tmp, MeshVS_DMF_HilightPrs );
625       }
626     break;
627   }
628 }
629
630 //================================================================
631 // Function : AddLinkPrs
632 // Purpose  :
633 //================================================================
634 void MeshVS_MeshPrsBuilder::AddLinkPrs (const TColStd_Array1OfReal&              theCoords,
635                                         const Handle(Graphic3d_ArrayOfSegments)& theSegments,
636                                         const Standard_Boolean                   theIsShrinked,
637                                         const Standard_Real                      theShrinkCoef) const
638 {
639   Standard_Real aX1 = theCoords (1);
640   Standard_Real aY1 = theCoords (2);
641   Standard_Real aZ1 = theCoords (3);
642   Standard_Real aX2 = theCoords (4);
643   Standard_Real aY2 = theCoords (5);
644   Standard_Real aZ2 = theCoords (6);
645
646   if (theIsShrinked)
647   {
648     const Standard_Real xG = (aX1 + aX2) * 0.5;
649     const Standard_Real yG = (aY1 + aY2) * 0.5;
650     const Standard_Real zG = (aZ1 + aZ2) * 0.5;
651
652     aX1 = (aX1 - xG) * theShrinkCoef + xG;
653     aY1 = (aY1 - yG) * theShrinkCoef + yG;
654     aZ1 = (aZ1 - zG) * theShrinkCoef + zG;
655
656     aX2 = 2.0 * xG - aX1;
657     aY2 = 2.0 * yG - aY1;
658     aZ2 = 2.0 * zG - aZ1;
659   }
660
661   theSegments->AddVertex (aX1, aY1, aZ1);
662   theSegments->AddVertex (aX2, aY2, aZ2);
663 }
664
665 //================================================================
666 // Function : AddFaceWirePrs
667 // Purpose  :
668 //================================================================
669 void MeshVS_MeshPrsBuilder::AddFaceWirePrs (const TColStd_Array1OfReal&              theCoords,
670                                             const Standard_Integer                   theNbNodes,
671                                             const Handle(Graphic3d_ArrayOfSegments)& theSegments,
672                                             const Standard_Boolean                   theIsShrinked,
673                                             const Standard_Real                      theShrinkingCoef) const
674 {
675   Standard_Real aCenterX = 0.0;
676   Standard_Real aCenterY = 0.0;
677   Standard_Real aCenterZ = 0.0;
678
679   if (theIsShrinked)
680   {
681     CalculateCenter (theCoords, theNbNodes, aCenterX, aCenterY, aCenterZ);
682   }
683
684   NCollection_Vector<gp_XYZ> aNodes (theNbNodes);
685
686   for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx)
687   {
688     gp_XYZ aPnt (theCoords (3 * aNodeIdx + 1),
689                  theCoords (3 * aNodeIdx + 2),
690                  theCoords (3 * aNodeIdx + 3));
691
692     if (theIsShrinked)
693     {
694       aPnt.SetX ((aPnt.X() - aCenterX) * theShrinkingCoef + aCenterX);
695       aPnt.SetY ((aPnt.Y() - aCenterY) * theShrinkingCoef + aCenterY);
696       aPnt.SetZ ((aPnt.Z() - aCenterZ) * theShrinkingCoef + aCenterZ);
697     }
698
699     aNodes.Append (aPnt);
700   }
701
702   for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx)
703   {
704     theSegments->AddVertex (aNodes.Value (aNodeIdx).X(),
705                             aNodes.Value (aNodeIdx).Y(),
706                             aNodes.Value (aNodeIdx).Z());
707
708     const Standard_Integer aNextIdx = (aNodeIdx + 1) % theNbNodes;
709
710     theSegments->AddVertex (aNodes.Value (aNextIdx).X(),
711                             aNodes.Value (aNextIdx).Y(),
712                             aNodes.Value (aNextIdx).Z());
713   }
714 }
715
716 //================================================================
717 // Function : AddFaceSolidPrs
718 // Purpose  :
719 //================================================================
720 void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer                    theID,
721                                              const TColStd_Array1OfReal&               theCoords,
722                                              const Standard_Integer                    theNbNodes,
723                                              const Standard_Integer                    theMaxNodes,
724                                              const Handle(Graphic3d_ArrayOfTriangles)& theTriangles,
725                                              const Standard_Boolean                    theIsShaded,
726                                              const Standard_Boolean                    theIsShrinked,
727                                              const Standard_Real                       theShrinkingCoef,
728                                              const Standard_Boolean                    theIsSmoothShading) const
729 {
730   Handle(MeshVS_DataSource) aDataSource = myParentMesh->GetDataSource();
731
732   if (aDataSource.IsNull())
733     return;
734
735   Standard_Real aCenterX = 0.0;
736   Standard_Real aCenterY = 0.0;
737   Standard_Real aCenterZ = 0.0;
738   Standard_Real aNormalX = 0.0;
739   Standard_Real aNormalY = 0.0;
740   Standard_Real aNormalZ = 0.0;
741
742   if (theIsShrinked)
743   {
744     CalculateCenter (theCoords, theNbNodes, aCenterX, aCenterY, aCenterZ);
745   }
746
747   NCollection_Vector<gp_XYZ> aVertexNormals (theMaxNodes);
748   
749   if (theIsShaded)
750   {
751     if (theIsSmoothShading)
752     {
753       for (Standard_Integer aNodeIdx = 1; aNodeIdx <= theNbNodes; ++aNodeIdx)
754       {
755         if (!aDataSource->GetNodeNormal (aNodeIdx, theID, aNormalX, aNormalY, aNormalZ))
756           break;
757
758         aVertexNormals.Append (gp_XYZ (aNormalX, aNormalY, aNormalZ));
759       }
760     }
761
762     if (!theIsSmoothShading || aVertexNormals.Size() != theNbNodes)
763     {
764       aDataSource->GetNormal (theID, theMaxNodes, aNormalX, aNormalY, aNormalZ);
765     }
766   }
767
768   NCollection_Vector<gp_XYZ> aNodes (theMaxNodes);
769
770   for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx)
771   {
772     gp_XYZ aPnt (theCoords (3 * aNodeIdx + 1),
773                  theCoords (3 * aNodeIdx + 2),
774                  theCoords (3 * aNodeIdx + 3));
775
776     if (theIsShrinked)
777     {
778       aPnt.SetX ((aPnt.X() - aCenterX) * theShrinkingCoef + aCenterX);
779       aPnt.SetY ((aPnt.Y() - aCenterY) * theShrinkingCoef + aCenterY);
780       aPnt.SetZ ((aPnt.Z() - aCenterZ) * theShrinkingCoef + aCenterZ);
781     }
782
783     aNodes.Append (aPnt);
784   }
785
786   // Triangulate polygon
787   for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes - 2; ++aNodeIdx)
788   {
789     for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx)
790     {
791       if (theIsShaded)
792       {
793         if (theIsSmoothShading && aVertexNormals.Size() == theNbNodes)
794         {
795           aNormalX = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X();
796           aNormalY = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y();
797           aNormalZ = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z();
798         }
799
800         theTriangles->AddVertex (aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X(),
801                                  aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y(),
802                                  aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z(),
803                                  aNormalX,
804                                  aNormalY,
805                                  aNormalZ);
806       }
807       else
808       {
809         theTriangles->AddVertex (aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X(),
810                                  aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y(),
811                                  aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z());
812       }
813     }
814   }
815 }
816
817 //================================================================
818 // Function : AddVolumePrs
819 // Purpose  :
820 //================================================================
821 void MeshVS_MeshPrsBuilder::AddVolumePrs (const Handle(MeshVS_HArray1OfSequenceOfInteger)& theTopo,
822                                           const TColStd_Array1OfReal&                      theNodes,
823                                           const Standard_Integer                           theNbNodes,
824                                           const Handle(Graphic3d_ArrayOfPrimitives)&       theArray,
825                                           const Standard_Boolean                           theIsShaded,
826                                           const Standard_Boolean                           theIsShrinked,
827                                           const Standard_Boolean                           theIsSelected,
828                                           const Standard_Real                              theShrinkCoef)
829 {
830   Standard_Real aCenter[] = { 0.0, 0.0, 0.0 };
831
832   Standard_Integer aLow = theNodes.Lower();
833
834   if (theTopo.IsNull() || theArray.IsNull())
835     return;
836
837   if (theIsShrinked)
838   {
839     for (Standard_Integer aNodeIdx = 0; aNodeIdx < 3 * theNbNodes; ++aNodeIdx)
840     {
841       aCenter[aNodeIdx % 3] += theNodes.Value (aLow + aNodeIdx);
842     }
843
844     aCenter[0] /= theNbNodes;
845     aCenter[1] /= theNbNodes;
846     aCenter[2] /= theNbNodes;
847   }
848
849   Standard_Boolean aIsPolygons = theArray->IsKind (STANDARD_TYPE (Graphic3d_ArrayOfTriangles));
850
851   if (aIsPolygons)
852   {
853     for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
854     {
855       const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
856       const Standard_Integer aNbPolyNodes = aFaceNodes.Length();
857       
858       Standard_Real* aPolyNodesBuf = (Standard_Real*) alloca ((3 * aNbPolyNodes + 1) * sizeof (Standard_Real));
859       TColStd_Array1OfReal aPolyNodes (*aPolyNodesBuf, 0, 3 * aNbPolyNodes);
860
861       for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbPolyNodes; ++aNodeIdx)
862       {
863         Standard_Integer anIdx = aFaceNodes.Value (aNodeIdx + 1);
864
865         Standard_Real aX = theNodes.Value (aLow + 3 * anIdx + 0);
866         Standard_Real aY = theNodes.Value (aLow + 3 * anIdx + 1);
867         Standard_Real aZ = theNodes.Value (aLow + 3 * anIdx + 2);
868
869         if (theIsShrinked)
870         {
871           aX = aCenter[0] + theShrinkCoef * (aX - aCenter[0]);
872           aY = aCenter[1] + theShrinkCoef * (aY - aCenter[1]);
873           aZ = aCenter[2] + theShrinkCoef * (aZ - aCenter[2]);
874         }
875
876         aPolyNodes.SetValue (3 * aNodeIdx + 1, aX);
877         aPolyNodes.SetValue (3 * aNodeIdx + 2, aY);
878         aPolyNodes.SetValue (3 * aNodeIdx + 3, aZ);
879       }
880       
881       gp_Vec aNorm;
882
883       if (theIsShaded)
884       {
885         aPolyNodes.SetValue (0, aNbPolyNodes);
886         
887         if (!MeshVS_Tool::GetAverageNormal (aPolyNodes, aNorm))
888         {
889           aNorm.SetCoord (0.0, 0.0, 1.0);
890         }
891       }
892
893       for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbPolyNodes - 2; ++aNodeIdx) // triangulate polygon
894       {
895         for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle
896         {
897           if (theIsShaded)
898           {
899             theArray->AddVertex (aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
900                                  aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
901                                  aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3),
902                                  aNorm.X(),
903                                  aNorm.Y(),
904                                  aNorm.Z());
905           }
906           else
907           {
908             theArray->AddVertex (aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
909                                  aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
910                                  aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
911           }
912         }
913       }
914     }
915   }
916   else if (theIsSelected)
917   {
918     for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
919     {
920       const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
921
922       Standard_Real aFaceCenter[] = { 0.0, 0.0, 0.0 };
923
924       for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aFaceNodes.Length(); ++aNodeIdx)
925       {
926         for (Standard_Integer aAxisIdx = 0; aAxisIdx < 3; ++aAxisIdx)
927         {
928           aFaceCenter[aAxisIdx] += theNodes.Value (aLow + 3 * aFaceNodes.Value (aNodeIdx) + aAxisIdx);
929         }
930       }
931
932       aFaceCenter[0] /= aFaceNodes.Length();
933       aFaceCenter[1] /= aFaceNodes.Length();
934       aFaceCenter[2] /= aFaceNodes.Length();
935
936       for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx)
937       {
938         for (Standard_Integer aSubIdx = 0; aSubIdx < 2; ++aSubIdx) // add segment
939         {
940           Standard_Integer anIdx = aFaceNodes.Value ((aNodeIdx + aSubIdx) % aNbNodes + 1);
941
942           Standard_Real aX = theNodes.Value (aLow + 3 * anIdx + 0);
943           Standard_Real aY = theNodes.Value (aLow + 3 * anIdx + 1);
944           Standard_Real aZ = theNodes.Value (aLow + 3 * anIdx + 2);
945
946           theArray->AddVertex (aFaceCenter[0] + theShrinkCoef * (aX - aFaceCenter[0]),
947                                aFaceCenter[1] + theShrinkCoef * (aY - aFaceCenter[1]),
948                                aFaceCenter[2] + theShrinkCoef * (aZ - aFaceCenter[2]));
949         }
950       }
951     }
952   }
953   else
954   {
955     // Find all pairs of nodes (edges) to draw (will be drawn only once)
956     NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher> aEdgeMap;
957
958     for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
959     {
960       const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
961       
962       for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx)
963       {
964         const Standard_Integer aNextIdx = (aNodeIdx + 1) % aNbNodes;
965
966         aEdgeMap.Add (MeshVS_NodePair (aFaceNodes.Value (aNodeIdx + 1),
967                                        aFaceNodes.Value (aNextIdx + 1)));
968       }
969     }
970
971     // Draw edges
972     for(NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher>::Iterator anIt (aEdgeMap); anIt.More(); anIt.Next())
973     {      
974       const Standard_Integer anIdx1 = aLow + 3 * anIt.Key().first;
975       const Standard_Integer anIdx2 = aLow + 3 * anIt.Key().second;
976
977       Standard_Real aX[] = { theNodes.Value (anIdx1 + 0), theNodes.Value (anIdx2 + 0) };
978       Standard_Real aY[] = { theNodes.Value (anIdx1 + 1), theNodes.Value (anIdx2 + 1) };
979       Standard_Real aZ[] = { theNodes.Value (anIdx1 + 2), theNodes.Value (anIdx2 + 2) };
980
981       if (theIsShrinked)
982       {
983         for (Standard_Integer anAxisIdx = 0; anAxisIdx < 2; ++anAxisIdx)
984         {
985           aX[anAxisIdx] = aCenter[0] + theShrinkCoef * (aX[anAxisIdx] - aCenter[0]);
986           aY[anAxisIdx] = aCenter[1] + theShrinkCoef * (aY[anAxisIdx] - aCenter[1]);
987           aZ[anAxisIdx] = aCenter[2] + theShrinkCoef * (aZ[anAxisIdx] - aCenter[2]);
988         }
989       }
990
991       theArray->AddVertex (aX[0], aY[0], aZ[0]);
992       theArray->AddVertex (aX[1], aY[1], aZ[1]);
993     }
994   }
995 }
996
997 //================================================================
998 // Function : HowManyPrimitives
999 // Purpose  :
1000 //================================================================
1001 void MeshVS_MeshPrsBuilder::HowManyPrimitives (const Handle(MeshVS_HArray1OfSequenceOfInteger)& Topo,
1002                                                const Standard_Boolean AsPolygons,
1003                                                const Standard_Boolean IsSelect,
1004                                                const Standard_Integer NbNodes,
1005                                                Standard_Integer& Vertices,
1006                                                Standard_Integer& Bounds)
1007 {
1008   if( !Topo.IsNull() ) {
1009     if( AsPolygons || IsSelect )
1010     {
1011       Standard_Integer B = Topo->Upper()-Topo->Lower()+1;
1012       Bounds += B;
1013       for( Standard_Integer i=Topo->Lower(), n=Topo->Upper(); i<=n; i++ )
1014         Vertices += Topo->Value( i ).Length();      
1015
1016       if( IsSelect )
1017         Vertices+=B;
1018     }
1019     else
1020     {
1021       Standard_Integer F = Topo->Upper()-Topo->Lower()+1,
1022                        E = NbNodes + F - 2;
1023       // number of edges is obtained by Euler's expression for polyhedrons
1024       
1025       Bounds += E;
1026       Vertices += 2*E;
1027     }
1028   }
1029 }
1030
1031 //================================================================
1032 // Function : DrawArrays
1033 // Purpose  :
1034 //================================================================
1035 void MeshVS_MeshPrsBuilder::DrawArrays( const Handle(Prs3d_Presentation)& Prs,
1036                                         const Handle(Graphic3d_ArrayOfPrimitives)& thePolygons,
1037                                         const Handle(Graphic3d_ArrayOfPrimitives)& theLines,
1038                                         const Handle(Graphic3d_ArrayOfPrimitives)& theLinkLines,
1039                                         const Handle(Graphic3d_ArrayOfPrimitives)& theVolumesInShad,
1040                                         const Standard_Boolean IsPolygonsEdgesOff,
1041                                         const Standard_Boolean IsSelected,
1042                                         const Handle(Graphic3d_AspectFillArea3d)& theFillAsp,
1043                                         const Handle(Graphic3d_AspectLine3d)& theLineAsp ) const
1044 {
1045   if ( theFillAsp.IsNull() )
1046     return;
1047
1048   Standard_Boolean IsFacePolygons   = ( !thePolygons.IsNull() && thePolygons->ItemNumber() > 0 ),
1049                    IsVolumePolygons = ( !theVolumesInShad.IsNull() && theVolumesInShad->ItemNumber() > 0 ),
1050                    IsPolygons       = IsFacePolygons || IsVolumePolygons,
1051                    IsPolylines      = ( !theLines.IsNull() && theLines->ItemNumber() > 0 ),
1052                    IsLinkPolylines  = ( !theLinkLines.IsNull() && theLinkLines->ItemNumber() > 0 );
1053
1054   Quantity_Color anIntColor  = theFillAsp->InteriorColor();
1055   Quantity_Color aBackColor  = theFillAsp->BackInteriorColor();
1056   Quantity_Color anEdgeColor = theFillAsp->EdgeColor();
1057   Standard_Real  aWidth      = theFillAsp->EdgeWidth();
1058
1059   Standard_Boolean isSupressBackFaces = Standard_False;
1060   Handle(MeshVS_Drawer) aDrawer = GetDrawer();
1061   if (!aDrawer.IsNull())
1062   {
1063     aDrawer->GetBoolean (MeshVS_DA_SupressBackFaces, isSupressBackFaces);
1064   }
1065
1066   if ( IsPolygons && theFillAsp->FrontMaterial().Transparency()<0.01 )
1067   {
1068     Prs3d_Root::NewGroup ( Prs );
1069     Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup ( Prs );
1070     aGroup->SetClosed (isSupressBackFaces == Standard_True);
1071     Handle(Graphic3d_AspectFillArea3d) aFillAsp = new Graphic3d_AspectFillArea3d (*theFillAsp);
1072     //if ( IsPolygonsEdgesOff )
1073       aFillAsp->SetEdgeOff ();
1074     //else
1075     //  aFillAsp->SetEdgeOn ();
1076
1077     if( anIntColor!=aBackColor )
1078       aFillAsp->SetDistinguishOn();
1079     else
1080       aFillAsp->SetDistinguishOff();
1081
1082     aGroup->SetPrimitivesAspect (aFillAsp);
1083
1084     if( IsFacePolygons )
1085     {
1086       aGroup->AddPrimitiveArray ( thePolygons );
1087     }
1088
1089     if( IsVolumePolygons )
1090     {
1091       aGroup->AddPrimitiveArray ( theVolumesInShad );
1092     }
1093   }
1094
1095   if ( IsPolylines && !IsPolygonsEdgesOff )
1096   {
1097     Prs3d_Root::NewGroup ( Prs );
1098     Handle (Graphic3d_Group) aLGroup = Prs3d_Root::CurrentGroup ( Prs );
1099
1100     if ( IsSelected )
1101       aLGroup->SetPrimitivesAspect ( theLineAsp );
1102     else
1103     {
1104       aLGroup->SetPrimitivesAspect ( theFillAsp );
1105       aLGroup->SetPrimitivesAspect ( new Graphic3d_AspectLine3d
1106         ( anEdgeColor, Aspect_TOL_SOLID, aWidth ) );
1107     }
1108     aLGroup->AddPrimitiveArray ( theLines );
1109   }
1110
1111   if ( IsLinkPolylines )
1112   {
1113     Prs3d_Root::NewGroup ( Prs );
1114     Handle (Graphic3d_Group) aBeamGroup = Prs3d_Root::CurrentGroup ( Prs );
1115     if ( !IsSelected )
1116       aBeamGroup->SetPrimitivesAspect ( theFillAsp );
1117     aBeamGroup->SetPrimitivesAspect ( theLineAsp );
1118     aBeamGroup->AddPrimitiveArray ( theLinkLines );
1119   }
1120
1121   if ( IsPolygons && theFillAsp->FrontMaterial().Transparency()>=0.01 )
1122   {
1123     Prs3d_Root::NewGroup ( Prs );
1124     Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup ( Prs );
1125     aGroup->SetClosed (isSupressBackFaces == Standard_True);
1126     Handle(Graphic3d_AspectFillArea3d) aFillAsp = new Graphic3d_AspectFillArea3d (*theFillAsp);
1127     //if ( IsPolygonsEdgesOff )
1128       aFillAsp->SetEdgeOff ();
1129     //else
1130     //  aFillAsp->SetEdgeOn ();
1131
1132     if( anIntColor!=aBackColor )
1133       aFillAsp->SetDistinguishOn();
1134     else
1135       aFillAsp->SetDistinguishOff();
1136
1137     aGroup->SetPrimitivesAspect (aFillAsp);
1138
1139     if( IsFacePolygons )
1140     {
1141       aGroup->AddPrimitiveArray ( thePolygons );
1142     }
1143
1144     if( IsVolumePolygons )
1145     {
1146       aGroup->AddPrimitiveArray ( theVolumesInShad );
1147     }
1148   }
1149 }
1150
1151 //================================================================
1152 // Function : CalculateCenter
1153 // Purpose  :
1154 //================================================================
1155 void MeshVS_MeshPrsBuilder::CalculateCenter (const TColStd_Array1OfReal& theCoords,
1156                                              const Standard_Integer NbNodes,
1157                                              Standard_Real &xG,
1158                                              Standard_Real &yG,
1159                                              Standard_Real &zG)
1160 {
1161   xG = yG = zG = 0;
1162   if ( NbNodes < 4 )
1163   {
1164     for ( Standard_Integer k=1; k<=NbNodes; k++)
1165     {
1166       xG += theCoords(3*k-2);
1167       yG += theCoords(3*k-1);
1168       zG += theCoords(3*k);
1169     }
1170     xG /= Standard_Real(NbNodes);
1171     yG /= Standard_Real(NbNodes);
1172     zG /= Standard_Real(NbNodes);
1173   }
1174   else
1175   {
1176     Standard_Integer a = 1, b = 3;
1177     xG = ( theCoords( 3*a-2 ) + theCoords( 3*b-2 ) ) / 2.0;
1178     yG = ( theCoords( 3*a-1 ) + theCoords( 3*b-1 ) ) / 2.0;
1179     zG = ( theCoords( 3*a )   + theCoords( 3*b   ) ) / 2.0;
1180   }
1181 }