0027536: Visualization - incorrect behavior of zoom persisted objects
[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;
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, IsMeshAllowOverlap, IsReflect, IsMeshSmoothShading = Standard_False;
207
208   aDrawer->GetBoolean  ( MeshVS_DA_Reflection, IsMeshReflect );
209   aDrawer->GetBoolean  ( MeshVS_DA_IsAllowOverlapped, IsMeshAllowOverlap );
210   IsReflect      = ( IsMeshReflect && !HasHilightFlag );
211   aDrawer->GetBoolean  ( MeshVS_DA_SmoothShading, IsMeshSmoothShading );
212
213   // display mode for highlighted prs of groups
214   IsShrink       = ( IsShrink && !HasHilightFlag );
215   IsShading      = ( IsShading || HasHilightFlag );
216
217   //---------- Creating AspectFillArea3d and AspectLine3d -------------
218   Graphic3d_MaterialAspect AMat;
219   aDrawer->GetMaterial ( MeshVS_DA_FrontMaterial, AMat );
220   if ( !IsReflect )
221   {
222     AMat.SetReflectionModeOff(Graphic3d_TOR_AMBIENT);
223     AMat.SetReflectionModeOff(Graphic3d_TOR_DIFFUSE);
224     AMat.SetReflectionModeOff(Graphic3d_TOR_SPECULAR);
225     AMat.SetReflectionModeOff(Graphic3d_TOR_EMISSION);
226   }
227   Handle( Graphic3d_AspectFillArea3d ) aFill = MeshVS_Tool::CreateAspectFillArea3d( GetDrawer(), AMat );
228   Handle( Graphic3d_AspectLine3d ) aBeam = MeshVS_Tool::CreateAspectLine3d ( GetDrawer() );
229   //-------------------------------------------------------------------
230
231   Standard_Boolean IsOverlapControl =
232     !IsMeshAllowOverlap && ( IsWireFrame || IsShading ) && !HasSelectFlag;
233
234   // subtract the hidden elements and ids to exclude (to minimize allocated memory)
235   TColStd_PackedMapOfInteger anIDs;
236   anIDs.Assign( IDs );
237   Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
238   if ( !aHiddenElems.IsNull() )
239     anIDs.Subtract( aHiddenElems->Map() );
240   anIDs.Subtract( IDsToExclude );
241
242   Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
243   TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
244
245   Standard_Boolean showEdges = Standard_True;
246   aDrawer->GetBoolean( MeshVS_DA_ShowEdges, showEdges );
247
248   showEdges = IsWireFrame || showEdges;
249
250   Standard_Integer* aNodesBuf  = (Standard_Integer*) alloca (maxnodes * sizeof (Standard_Integer));
251   Standard_Real*    aCoordsBuf = (Standard_Real*)    alloca (3 * maxnodes * sizeof (Standard_Real));
252
253   TColStd_Array1OfInteger aNodes  (*aNodesBuf, 1, maxnodes);
254   TColStd_Array1OfReal    aCoords (*aCoordsBuf, 1, 3 * maxnodes);
255
256   Standard_Integer aNbFacePrimitives = 0;
257   Standard_Integer aNbVolmPrimitives = 0;
258   Standard_Integer aNbEdgePrimitives = 0;
259   Standard_Integer aNbLinkPrimitives = 0;
260
261   MeshVS_EntityType aType;
262
263   for (it.Reset(); it.More(); it.Next())
264   {
265     Standard_Integer aNbNodes = 0;
266
267     if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType))
268       continue;
269
270     if (aType == MeshVS_ET_Volume)
271     {
272       if (aSource->Get3DGeom (it.Key(), aNbNodes, aTopo))
273       {
274         for (Standard_Integer aFaceIdx = aTopo->Lower(); aFaceIdx <= aTopo->Upper(); ++aFaceIdx)
275         {
276           const TColStd_SequenceOfInteger& aFaceNodes = aTopo->Value (aFaceIdx);
277           
278           if (showEdges) // add edge segments
279           {
280             aNbEdgePrimitives += aFaceNodes.Length();
281           }
282           
283           if (IsShading || IsShrink) // add volumetric cell triangles
284           {
285             if (!HasSelectFlag)
286               aNbVolmPrimitives += aFaceNodes.Length() - 2;
287           }
288         }
289       }
290     }
291     else if (aType == MeshVS_ET_Link)
292     {
293       if (showEdges)
294       {
295         aNbLinkPrimitives += 1; // add link segment
296       }
297     }
298     else if (aType == MeshVS_ET_Face)
299     {
300       if (showEdges)
301       {
302         aNbEdgePrimitives += aNbNodes; // add edge segments
303       }
304
305       if (!IsOverlapControl || IsShading)
306       {
307         if ((IsShading || IsShrink) && !HasSelectFlag)
308         {
309           aNbFacePrimitives += aNbNodes - 2; // add face triangles
310         }
311       }
312     }
313   }
314
315   // Here we do not use indices arrays because they are not effective for some mesh
316   // drawing modes: shrinking mode (displaces the vertices inside the polygon), 3D
317   // cell rendering (normal interpolation is not always applicable - flat shading),
318   // elemental coloring (color interpolation is impossible)
319   Handle (Graphic3d_ArrayOfTriangles) aVolmTriangles =
320     new Graphic3d_ArrayOfTriangles (aNbVolmPrimitives * 3, 0, IsReflect);
321   Handle (Graphic3d_ArrayOfTriangles) aFaceTriangles =
322     new Graphic3d_ArrayOfTriangles (aNbFacePrimitives * 3, 0, IsReflect);
323
324   Handle (Graphic3d_ArrayOfSegments) aLinkSegments;
325   Handle (Graphic3d_ArrayOfSegments) aEdgeSegments;
326
327   if (showEdges)
328   {
329     aLinkSegments = new Graphic3d_ArrayOfSegments (aNbLinkPrimitives * 2);
330     aEdgeSegments = new Graphic3d_ArrayOfSegments (aNbEdgePrimitives * 2);
331   }
332
333   TColStd_PackedMapOfInteger aCustomElements;
334
335   Quantity_Color       anOldEdgeColor;
336   Quantity_Color       anEdgeColor;
337   Quantity_Color       anIntColor;
338   Aspect_InteriorStyle anIntType;
339   Aspect_TypeOfLine    aLine;
340   Standard_Real        aWidth;
341
342   aFill->Values (anIntType, anIntColor, anEdgeColor, aLine, aWidth);
343   
344   MeshVS_MapOfTwoNodes aLinkNodes;
345   
346   // Forbid drawings of edges which overlap with some links
347   if (showEdges && IsOverlapControl)
348   {
349     for (it.Reset(); it.More(); it.Next())
350     {
351       if (aSource->GetGeomType (it.Key(), Standard_True, aType) && aType == MeshVS_ET_Link)
352       {
353         Standard_Integer aNbNodes;
354
355         if (aSource->GetNodesByElement (it.Key(), aNodes, aNbNodes) && aNbNodes == 2)
356         {
357           aLinkNodes.Add (MeshVS_TwoNodes (aNodes(1), aNodes(2)));
358         }
359       }
360     }
361   }
362
363   NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher> aSegmentMap;
364
365   for (it.Reset(); it.More(); it.Next())
366   {
367     const Standard_Integer aKey = it.Key();
368
369     Standard_Integer NbNodes;
370     if (!aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType))
371       continue;
372
373     if (!aSource->GetNodesByElement (aKey, aNodes, NbNodes))
374       continue;
375
376     switch (aType)
377     {
378       case MeshVS_ET_Volume:
379       {
380         if (IsExcludingOn())
381           IDsToExclude.Add (aKey);
382
383         if (aSource->Get3DGeom (aKey, NbNodes, aTopo))
384         {
385           // Add wire-frame presentation (draw edges for shading mode as well)
386           if (showEdges)
387           {
388             AddVolumePrs (aTopo, aCoords, NbNodes,
389               aEdgeSegments, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef);
390           }
391
392           // Add shading presentation
393           if ((IsShading || IsShrink) && !HasSelectFlag)
394           {
395             AddVolumePrs (aTopo, aCoords, NbNodes,
396               aVolmTriangles, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef);
397           }
398         }
399       }
400       break;
401
402       case MeshVS_ET_Link:
403       {
404         if (IsExcludingOn())
405           IDsToExclude.Add (aKey);
406
407         if (showEdges)
408         {
409           AddLinkPrs (aCoords, aLinkSegments, IsShrink || HasSelectFlag, aShrinkCoef);
410         }
411       }
412       break;
413
414       case MeshVS_ET_Face:
415       {
416         if (IsExcludingOn())
417           IDsToExclude.Add (aKey);
418
419         if (showEdges && IsOverlapControl)
420         {
421           Standard_Integer Last = 0;
422
423           MeshVS_TwoNodes aTwoNodes (aNodes (1));
424
425           for (Standard_Integer i = 1; i <= NbNodes; ++i)
426           {
427             if (i > 1)
428               aTwoNodes.First = aTwoNodes.Second;
429
430             aTwoNodes.Second = (i < NbNodes) ? aNodes (i+1) : aNodes (1);
431
432             if (aLinkNodes.Contains (aTwoNodes))
433             {
434               for (Standard_Integer aNodeIdx = Last + 1; aNodeIdx < i; ++aNodeIdx)
435               {
436                 const Standard_Integer aNextIdx = aNodeIdx + 1;
437
438                 aEdgeSegments->AddVertex (
439                   aCoords (3 * aNodeIdx - 2), aCoords (3 * aNodeIdx - 1), aCoords (3 * aNodeIdx));
440                 aEdgeSegments->AddVertex (
441                   aCoords (3 * aNextIdx - 2), aCoords (3 * aNextIdx - 1), aCoords (3 * aNextIdx));
442               }
443
444               Last = i;
445             }
446           }
447
448           if (NbNodes - Last > 0)
449           {
450             for (Standard_Integer aNodeIdx = Last; aNodeIdx < NbNodes; ++aNodeIdx)
451             {
452               const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes;
453               
454               const MeshVS_NodePair aSegment (aNodes (aNodeIdx + 1),
455                                               aNodes (aNextIdx + 1));
456
457               if (!aSegmentMap.Contains (aSegment))
458               {
459                 aEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
460                                           aCoords (3 * aNodeIdx + 2),
461                                           aCoords (3 * aNodeIdx + 3));
462
463                 aEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1),
464                                           aCoords (3 * aNextIdx + 2),
465                                           aCoords (3 * aNextIdx + 3));
466
467                 aSegmentMap.Add (aSegment);
468               }
469             }
470           }
471         }
472
473         if (!IsOverlapControl || IsShading)
474         {
475           if (!IsOverlapControl && showEdges)
476           {
477             AddFaceWirePrs (aCoords, NbNodes,
478               aEdgeSegments, IsShrink || HasSelectFlag, aShrinkCoef);
479           }
480
481           if ((IsShading || IsShrink) && !HasSelectFlag)
482           {
483             AddFaceSolidPrs (aKey, aCoords, NbNodes, maxnodes, aFaceTriangles, IsReflect,
484               IsShrink || HasSelectFlag, aShrinkCoef, IsMeshSmoothShading);
485           }
486         }
487       }
488       break;
489
490       default:
491       {
492         aCustomElements.Add (aKey);
493       }
494     }
495   }
496
497   if (IsShrink)
498   {
499     anOldEdgeColor = anEdgeColor;
500     aFill->SetEdgeColor (Quantity_NOC_BLACK);
501   }
502
503   //std::cout << "Actual extents: " << std::endl
504   //  << "Face tris: " << aFaceTriangles->ItemNumber() << " from " << aNbFacePrimitives << std::endl
505   //  << "Volm tris: " << aVolmTriangles->ItemNumber()  << " from " << aNbVolmPrimitives << std::endl
506   //  << "Face segs: " << aEdgeSegments->ItemNumber()  << " from " << aNbEdgePrimitives << std::endl
507   //  << "Link segs: " << aLinkSegments->ItemNumber()  << " from " << aNbLinkPrimitives << std::endl;
508
509   DrawArrays ( Prs, aFaceTriangles, aEdgeSegments, aLinkSegments, aVolmTriangles,
510     !showEdges, HasSelectFlag, aFill, aBeam );
511
512   if ( !aCustomElements.IsEmpty() )
513     CustomBuild ( Prs, aCustomElements, IDsToExclude, DisplayMode );
514
515   if( IsShrink )
516     aFill->SetEdgeColor( anOldEdgeColor );
517 }
518
519 //================================================================
520 // Function : BuildHilightPrs
521 // Purpose  :
522 //================================================================
523 void MeshVS_MeshPrsBuilder::BuildHilightPrs ( const Handle(Prs3d_Presentation)& Prs,
524                                               const TColStd_PackedMapOfInteger& IDs,
525                                               const Standard_Boolean IsElement ) const
526 {
527   Standard_Integer maxnodes;
528
529   Handle (MeshVS_DataSource) aSource = GetDataSource();
530   if ( aSource.IsNull() || IDs.IsEmpty() )
531     return;
532
533   Handle( MeshVS_Drawer ) aDrawer = GetDrawer();
534   if ( aDrawer.IsNull() || !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, maxnodes ) ||
535        maxnodes <= 0 )
536     return;
537
538   MeshVS_Buffer aCoordsBuf (3*maxnodes*sizeof(Standard_Real));
539   TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3*maxnodes);
540
541   Graphic3d_MaterialAspect AMat;
542   aDrawer->GetMaterial ( MeshVS_DA_FrontMaterial, AMat );
543   AMat.SetReflectionModeOff(Graphic3d_TOR_AMBIENT);
544   AMat.SetReflectionModeOff(Graphic3d_TOR_DIFFUSE);
545   AMat.SetReflectionModeOff(Graphic3d_TOR_SPECULAR);
546   AMat.SetReflectionModeOff(Graphic3d_TOR_EMISSION);
547
548   Handle( Graphic3d_AspectFillArea3d ) aFill     = MeshVS_Tool::CreateAspectFillArea3d( GetDrawer(), AMat );
549   Handle( Graphic3d_AspectLine3d )     aBeam     = MeshVS_Tool::CreateAspectLine3d( GetDrawer() );
550   Handle( Graphic3d_AspectMarker3d )   aNodeMark = MeshVS_Tool::CreateAspectMarker3d( GetDrawer() );
551
552   // Hilight one element or node
553   TColStd_MapIteratorOfPackedMapOfInteger it (IDs);
554   Standard_Integer ID = it.Key(), NbNodes;
555   MeshVS_EntityType aType;
556
557   if ( !aSource->GetGeom ( ID, IsElement, aCoords, NbNodes, aType ) )
558     return;
559
560   Prs3d_Root::NewGroup ( Prs );
561   Handle (Graphic3d_Group) aHilightGroup = Prs3d_Root::CurrentGroup ( Prs );
562
563   switch ( aType )
564   {
565     case MeshVS_ET_Node :
566     {
567       aHilightGroup->SetPrimitivesAspect (aNodeMark);
568       Handle(Graphic3d_ArrayOfPoints) anArrayOfPoints = new Graphic3d_ArrayOfPoints (1);
569       anArrayOfPoints->AddVertex (aCoords(1), aCoords(2), aCoords(3));
570       aHilightGroup->AddPrimitiveArray (anArrayOfPoints);
571     }
572     break;
573
574     case MeshVS_ET_Link:
575     {
576       aHilightGroup->SetPrimitivesAspect ( aBeam );
577       Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(2);
578       aPrims->AddVertex(aCoords(1),aCoords(2),aCoords(3));
579       aPrims->AddVertex(aCoords(4),aCoords(5),aCoords(6));
580       aHilightGroup->AddPrimitiveArray(aPrims);
581     }
582     break;
583
584     case MeshVS_ET_Face:
585     if ( NbNodes > 0 )
586     {
587       aHilightGroup->SetPrimitivesAspect ( aFill );
588       Handle(Graphic3d_ArrayOfPolygons) aPrims = new Graphic3d_ArrayOfPolygons(NbNodes);
589       for ( Standard_Integer k=1; k<=NbNodes; k++)
590         aPrims->AddVertex(aCoords(3*k-2),aCoords(3*k-1),aCoords(3*k));
591       aHilightGroup->AddPrimitiveArray(aPrims);
592     }
593     break;
594
595     case MeshVS_ET_Volume:
596     if( NbNodes > 0 )
597     {
598       Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
599
600       aHilightGroup->SetPrimitivesAspect ( aFill );
601
602       if( aSource->Get3DGeom( ID, NbNodes, aTopo ) )
603       {
604         const Standard_Integer up = aTopo->Upper();
605         const Standard_Integer lo = aTopo->Lower();
606         Standard_Integer nbnodes = 0, i, j;
607         for( i=lo; i<=up; i++ )
608           nbnodes += aTopo->Value( i ).Length();
609
610         Handle(Graphic3d_ArrayOfPolygons) aPrims = new Graphic3d_ArrayOfPolygons(nbnodes,aTopo->Length());
611         for( i=lo; i<=up; i++ )
612         {
613           const TColStd_SequenceOfInteger& aSeq = aTopo->Value( i );
614           const Standard_Integer m = aSeq.Length();
615           aPrims->AddBound(m);
616           for( j=1; j<=m; j++ )
617           {
618             const Standard_Integer ind = 3*aSeq.Value( j );
619             aPrims->AddVertex(aCoords(ind+1),aCoords(ind+2),aCoords(ind+3));
620           }
621         }
622         aHilightGroup->AddPrimitiveArray(aPrims);
623       }
624     }
625     break;
626
627     default:
628       {
629         TColStd_PackedMapOfInteger tmp;
630         CustomBuild ( Prs, IDs, tmp, MeshVS_DMF_HilightPrs );
631       }
632     break;
633   }
634 }
635
636 //================================================================
637 // Function : AddLinkPrs
638 // Purpose  :
639 //================================================================
640 void MeshVS_MeshPrsBuilder::AddLinkPrs (const TColStd_Array1OfReal&              theCoords,
641                                         const Handle(Graphic3d_ArrayOfSegments)& theSegments,
642                                         const Standard_Boolean                   theIsShrinked,
643                                         const Standard_Real                      theShrinkCoef) const
644 {
645   Standard_Real aX1 = theCoords (1);
646   Standard_Real aY1 = theCoords (2);
647   Standard_Real aZ1 = theCoords (3);
648   Standard_Real aX2 = theCoords (4);
649   Standard_Real aY2 = theCoords (5);
650   Standard_Real aZ2 = theCoords (6);
651
652   if (theIsShrinked)
653   {
654     const Standard_Real xG = (aX1 + aX2) * 0.5;
655     const Standard_Real yG = (aY1 + aY2) * 0.5;
656     const Standard_Real zG = (aZ1 + aZ2) * 0.5;
657
658     aX1 = (aX1 - xG) * theShrinkCoef + xG;
659     aY1 = (aY1 - yG) * theShrinkCoef + yG;
660     aZ1 = (aZ1 - zG) * theShrinkCoef + zG;
661
662     aX2 = 2.0 * xG - aX1;
663     aY2 = 2.0 * yG - aY1;
664     aZ2 = 2.0 * zG - aZ1;
665   }
666
667   theSegments->AddVertex (aX1, aY1, aZ1);
668   theSegments->AddVertex (aX2, aY2, aZ2);
669 }
670
671 //================================================================
672 // Function : AddFaceWirePrs
673 // Purpose  :
674 //================================================================
675 void MeshVS_MeshPrsBuilder::AddFaceWirePrs (const TColStd_Array1OfReal&              theCoords,
676                                             const Standard_Integer                   theNbNodes,
677                                             const Handle(Graphic3d_ArrayOfSegments)& theSegments,
678                                             const Standard_Boolean                   theIsShrinked,
679                                             const Standard_Real                      theShrinkingCoef) const
680 {
681   Standard_Real aCenterX = 0.0;
682   Standard_Real aCenterY = 0.0;
683   Standard_Real aCenterZ = 0.0;
684
685   if (theIsShrinked)
686   {
687     CalculateCenter (theCoords, theNbNodes, aCenterX, aCenterY, aCenterZ);
688   }
689
690   NCollection_Vector<gp_XYZ> aNodes (theNbNodes);
691
692   for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx)
693   {
694     gp_XYZ aPnt (theCoords (3 * aNodeIdx + 1),
695                  theCoords (3 * aNodeIdx + 2),
696                  theCoords (3 * aNodeIdx + 3));
697
698     if (theIsShrinked)
699     {
700       aPnt.SetX ((aPnt.X() - aCenterX) * theShrinkingCoef + aCenterX);
701       aPnt.SetY ((aPnt.Y() - aCenterY) * theShrinkingCoef + aCenterY);
702       aPnt.SetZ ((aPnt.Z() - aCenterZ) * theShrinkingCoef + aCenterZ);
703     }
704
705     aNodes.Append (aPnt);
706   }
707
708   for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx)
709   {
710     theSegments->AddVertex (aNodes.Value (aNodeIdx).X(),
711                             aNodes.Value (aNodeIdx).Y(),
712                             aNodes.Value (aNodeIdx).Z());
713
714     const Standard_Integer aNextIdx = (aNodeIdx + 1) % theNbNodes;
715
716     theSegments->AddVertex (aNodes.Value (aNextIdx).X(),
717                             aNodes.Value (aNextIdx).Y(),
718                             aNodes.Value (aNextIdx).Z());
719   }
720 }
721
722 //================================================================
723 // Function : AddFaceSolidPrs
724 // Purpose  :
725 //================================================================
726 void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer                    theID,
727                                              const TColStd_Array1OfReal&               theCoords,
728                                              const Standard_Integer                    theNbNodes,
729                                              const Standard_Integer                    theMaxNodes,
730                                              const Handle(Graphic3d_ArrayOfTriangles)& theTriangles,
731                                              const Standard_Boolean                    theIsShaded,
732                                              const Standard_Boolean                    theIsShrinked,
733                                              const Standard_Real                       theShrinkingCoef,
734                                              const Standard_Boolean                    theIsSmoothShading) const
735 {
736   Handle(MeshVS_DataSource) aDataSource = myParentMesh->GetDataSource();
737
738   if (aDataSource.IsNull())
739     return;
740
741   Standard_Real aCenterX = 0.0;
742   Standard_Real aCenterY = 0.0;
743   Standard_Real aCenterZ = 0.0;
744   Standard_Real aNormalX = 0.0;
745   Standard_Real aNormalY = 0.0;
746   Standard_Real aNormalZ = 0.0;
747
748   if (theIsShrinked)
749   {
750     CalculateCenter (theCoords, theNbNodes, aCenterX, aCenterY, aCenterZ);
751   }
752
753   NCollection_Vector<gp_XYZ> aVertexNormals (theMaxNodes);
754   
755   if (theIsShaded)
756   {
757     if (theIsSmoothShading)
758     {
759       for (Standard_Integer aNodeIdx = 1; aNodeIdx <= theNbNodes; ++aNodeIdx)
760       {
761         if (!aDataSource->GetNodeNormal (aNodeIdx, theID, aNormalX, aNormalY, aNormalZ))
762           break;
763
764         aVertexNormals.Append (gp_XYZ (aNormalX, aNormalY, aNormalZ));
765       }
766     }
767
768     if (!theIsSmoothShading || aVertexNormals.Size() != theNbNodes)
769     {
770       aDataSource->GetNormal (theID, theMaxNodes, aNormalX, aNormalY, aNormalZ);
771     }
772   }
773
774   NCollection_Vector<gp_XYZ> aNodes (theMaxNodes);
775
776   for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx)
777   {
778     gp_XYZ aPnt (theCoords (3 * aNodeIdx + 1),
779                  theCoords (3 * aNodeIdx + 2),
780                  theCoords (3 * aNodeIdx + 3));
781
782     if (theIsShrinked)
783     {
784       aPnt.SetX ((aPnt.X() - aCenterX) * theShrinkingCoef + aCenterX);
785       aPnt.SetY ((aPnt.Y() - aCenterY) * theShrinkingCoef + aCenterY);
786       aPnt.SetZ ((aPnt.Z() - aCenterZ) * theShrinkingCoef + aCenterZ);
787     }
788
789     aNodes.Append (aPnt);
790   }
791
792   // Triangulate polygon
793   for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes - 2; ++aNodeIdx)
794   {
795     for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx)
796     {
797       if (theIsShaded)
798       {
799         if (theIsSmoothShading && aVertexNormals.Size() == theNbNodes)
800         {
801           aNormalX = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X();
802           aNormalY = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y();
803           aNormalZ = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z();
804         }
805
806         theTriangles->AddVertex (aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X(),
807                                  aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y(),
808                                  aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z(),
809                                  aNormalX,
810                                  aNormalY,
811                                  aNormalZ);
812       }
813       else
814       {
815         theTriangles->AddVertex (aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X(),
816                                  aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y(),
817                                  aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z());
818       }
819     }
820   }
821 }
822
823 //================================================================
824 // Function : AddVolumePrs
825 // Purpose  :
826 //================================================================
827 void MeshVS_MeshPrsBuilder::AddVolumePrs (const Handle(MeshVS_HArray1OfSequenceOfInteger)& theTopo,
828                                           const TColStd_Array1OfReal&                      theNodes,
829                                           const Standard_Integer                           theNbNodes,
830                                           const Handle(Graphic3d_ArrayOfPrimitives)&       theArray,
831                                           const Standard_Boolean                           theIsShaded,
832                                           const Standard_Boolean                           theIsShrinked,
833                                           const Standard_Boolean                           theIsSelected,
834                                           const Standard_Real                              theShrinkCoef)
835 {
836   Standard_Real aCenter[] = { 0.0, 0.0, 0.0 };
837
838   Standard_Integer aLow = theNodes.Lower();
839
840   if (theTopo.IsNull() || theArray.IsNull())
841     return;
842
843   if (theIsShrinked)
844   {
845     for (Standard_Integer aNodeIdx = 0; aNodeIdx < 3 * theNbNodes; ++aNodeIdx)
846     {
847       aCenter[aNodeIdx % 3] += theNodes.Value (aLow + aNodeIdx);
848     }
849
850     aCenter[0] /= theNbNodes;
851     aCenter[1] /= theNbNodes;
852     aCenter[2] /= theNbNodes;
853   }
854
855   Standard_Boolean aIsPolygons = theArray->IsKind (STANDARD_TYPE (Graphic3d_ArrayOfTriangles));
856
857   if (aIsPolygons)
858   {
859     for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
860     {
861       const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
862       const Standard_Integer aNbPolyNodes = aFaceNodes.Length();
863       
864       Standard_Real* aPolyNodesBuf = (Standard_Real*) alloca ((3 * aNbPolyNodes + 1) * sizeof (Standard_Real));
865       TColStd_Array1OfReal aPolyNodes (*aPolyNodesBuf, 0, 3 * aNbPolyNodes);
866
867       for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbPolyNodes; ++aNodeIdx)
868       {
869         Standard_Integer anIdx = aFaceNodes.Value (aNodeIdx + 1);
870
871         Standard_Real aX = theNodes.Value (aLow + 3 * anIdx + 0);
872         Standard_Real aY = theNodes.Value (aLow + 3 * anIdx + 1);
873         Standard_Real aZ = theNodes.Value (aLow + 3 * anIdx + 2);
874
875         if (theIsShrinked)
876         {
877           aX = aCenter[0] + theShrinkCoef * (aX - aCenter[0]);
878           aY = aCenter[1] + theShrinkCoef * (aY - aCenter[1]);
879           aZ = aCenter[2] + theShrinkCoef * (aZ - aCenter[2]);
880         }
881
882         aPolyNodes.SetValue (3 * aNodeIdx + 1, aX);
883         aPolyNodes.SetValue (3 * aNodeIdx + 2, aY);
884         aPolyNodes.SetValue (3 * aNodeIdx + 3, aZ);
885       }
886       
887       gp_Vec aNorm;
888
889       if (theIsShaded)
890       {
891         aPolyNodes.SetValue (0, aNbPolyNodes);
892         
893         if (!MeshVS_Tool::GetAverageNormal (aPolyNodes, aNorm))
894         {
895           aNorm.SetCoord (0.0, 0.0, 1.0);
896         }
897       }
898
899       for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbPolyNodes - 2; ++aNodeIdx) // triangulate polygon
900       {
901         for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle
902         {
903           if (theIsShaded)
904           {
905             theArray->AddVertex (aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
906                                  aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
907                                  aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3),
908                                  aNorm.X(),
909                                  aNorm.Y(),
910                                  aNorm.Z());
911           }
912           else
913           {
914             theArray->AddVertex (aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
915                                  aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
916                                  aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
917           }
918         }
919       }
920     }
921   }
922   else if (theIsSelected)
923   {
924     for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
925     {
926       const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
927
928       Standard_Real aFaceCenter[] = { 0.0, 0.0, 0.0 };
929
930       for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aFaceNodes.Length(); ++aNodeIdx)
931       {
932         for (Standard_Integer aAxisIdx = 0; aAxisIdx < 3; ++aAxisIdx)
933         {
934           aFaceCenter[aAxisIdx] += theNodes.Value (aLow + 3 * aFaceNodes.Value (aNodeIdx) + aAxisIdx);
935         }
936       }
937
938       aFaceCenter[0] /= aFaceNodes.Length();
939       aFaceCenter[1] /= aFaceNodes.Length();
940       aFaceCenter[2] /= aFaceNodes.Length();
941
942       for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx)
943       {
944         for (Standard_Integer aSubIdx = 0; aSubIdx < 2; ++aSubIdx) // add segment
945         {
946           Standard_Integer anIdx = aFaceNodes.Value ((aNodeIdx + aSubIdx) % aNbNodes + 1);
947
948           Standard_Real aX = theNodes.Value (aLow + 3 * anIdx + 0);
949           Standard_Real aY = theNodes.Value (aLow + 3 * anIdx + 1);
950           Standard_Real aZ = theNodes.Value (aLow + 3 * anIdx + 2);
951
952           theArray->AddVertex (aFaceCenter[0] + theShrinkCoef * (aX - aFaceCenter[0]),
953                                aFaceCenter[1] + theShrinkCoef * (aY - aFaceCenter[1]),
954                                aFaceCenter[2] + theShrinkCoef * (aZ - aFaceCenter[2]));
955         }
956       }
957     }
958   }
959   else
960   {
961     // Find all pairs of nodes (edges) to draw (will be drawn only once)
962     NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher> aEdgeMap;
963
964     for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
965     {
966       const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
967       
968       for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx)
969       {
970         const Standard_Integer aNextIdx = (aNodeIdx + 1) % aNbNodes;
971
972         aEdgeMap.Add (MeshVS_NodePair (aFaceNodes.Value (aNodeIdx + 1),
973                                        aFaceNodes.Value (aNextIdx + 1)));
974       }
975     }
976
977     // Draw edges
978     for(NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher>::Iterator anIt (aEdgeMap); anIt.More(); anIt.Next())
979     {      
980       const Standard_Integer anIdx1 = aLow + 3 * anIt.Key().first;
981       const Standard_Integer anIdx2 = aLow + 3 * anIt.Key().second;
982
983       Standard_Real aX[] = { theNodes.Value (anIdx1 + 0), theNodes.Value (anIdx2 + 0) };
984       Standard_Real aY[] = { theNodes.Value (anIdx1 + 1), theNodes.Value (anIdx2 + 1) };
985       Standard_Real aZ[] = { theNodes.Value (anIdx1 + 2), theNodes.Value (anIdx2 + 2) };
986
987       if (theIsShrinked)
988       {
989         for (Standard_Integer anAxisIdx = 0; anAxisIdx < 2; ++anAxisIdx)
990         {
991           aX[anAxisIdx] = aCenter[0] + theShrinkCoef * (aX[anAxisIdx] - aCenter[0]);
992           aY[anAxisIdx] = aCenter[1] + theShrinkCoef * (aY[anAxisIdx] - aCenter[1]);
993           aZ[anAxisIdx] = aCenter[2] + theShrinkCoef * (aZ[anAxisIdx] - aCenter[2]);
994         }
995       }
996
997       theArray->AddVertex (aX[0], aY[0], aZ[0]);
998       theArray->AddVertex (aX[1], aY[1], aZ[1]);
999     }
1000   }
1001 }
1002
1003 //================================================================
1004 // Function : HowManyPrimitives
1005 // Purpose  :
1006 //================================================================
1007 void MeshVS_MeshPrsBuilder::HowManyPrimitives (const Handle(MeshVS_HArray1OfSequenceOfInteger)& Topo,
1008                                                const Standard_Boolean AsPolygons,
1009                                                const Standard_Boolean IsSelect,
1010                                                const Standard_Integer NbNodes,
1011                                                Standard_Integer& Vertices,
1012                                                Standard_Integer& Bounds)
1013 {
1014   if( !Topo.IsNull() ) {
1015     if( AsPolygons || IsSelect )
1016     {
1017       Standard_Integer B = Topo->Upper()-Topo->Lower()+1;
1018       Bounds += B;
1019       for( Standard_Integer i=Topo->Lower(), n=Topo->Upper(); i<=n; i++ )
1020         Vertices += Topo->Value( i ).Length();      
1021
1022       if( IsSelect )
1023         Vertices+=B;
1024     }
1025     else
1026     {
1027       Standard_Integer F = Topo->Upper()-Topo->Lower()+1,
1028                        E = NbNodes + F - 2;
1029       // number of edges is obtained by Euler's expression for polyhedrons
1030       
1031       Bounds += E;
1032       Vertices += 2*E;
1033     }
1034   }
1035 }
1036
1037 //================================================================
1038 // Function : DrawArrays
1039 // Purpose  :
1040 //================================================================
1041 void MeshVS_MeshPrsBuilder::DrawArrays( const Handle(Prs3d_Presentation)& Prs,
1042                                         const Handle(Graphic3d_ArrayOfPrimitives)& thePolygons,
1043                                         const Handle(Graphic3d_ArrayOfPrimitives)& theLines,
1044                                         const Handle(Graphic3d_ArrayOfPrimitives)& theLinkLines,
1045                                         const Handle(Graphic3d_ArrayOfPrimitives)& theVolumesInShad,
1046                                         const Standard_Boolean IsPolygonsEdgesOff,
1047                                         const Standard_Boolean IsSelected,
1048                                         const Handle(Graphic3d_AspectFillArea3d)& theFillAsp,
1049                                         const Handle(Graphic3d_AspectLine3d)& theLineAsp ) const
1050 {
1051   if ( theFillAsp.IsNull() )
1052     return;
1053
1054   Standard_Boolean IsFacePolygons   = ( !thePolygons.IsNull() && thePolygons->ItemNumber() > 0 ),
1055                    IsVolumePolygons = ( !theVolumesInShad.IsNull() && theVolumesInShad->ItemNumber() > 0 ),
1056                    IsPolygons       = IsFacePolygons || IsVolumePolygons,
1057                    IsPolylines      = ( !theLines.IsNull() && theLines->ItemNumber() > 0 ),
1058                    IsLinkPolylines  = ( !theLinkLines.IsNull() && theLinkLines->ItemNumber() > 0 );
1059
1060   Aspect_InteriorStyle aStyle;
1061   Quantity_Color anIntColor, aBackColor, anEdgeColor; 
1062   Aspect_TypeOfLine aType;
1063   Standard_Real aWidth;
1064
1065   theFillAsp->Values( aStyle, anIntColor, aBackColor, anEdgeColor, aType, aWidth );
1066
1067   Standard_Boolean isSupressBackFaces = Standard_False;
1068   Handle(MeshVS_Drawer) aDrawer = GetDrawer();
1069   if (!aDrawer.IsNull())
1070   {
1071     aDrawer->GetBoolean (MeshVS_DA_SupressBackFaces, isSupressBackFaces);
1072   }
1073
1074   if ( IsPolygons && theFillAsp->FrontMaterial().Transparency()<0.01 )
1075   {
1076     Prs3d_Root::NewGroup ( Prs );
1077     Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup ( Prs );
1078
1079     //if ( IsPolygonsEdgesOff )
1080       theFillAsp->SetEdgeOff ();
1081     //else
1082     //  theFillAsp->SetEdgeOn ();
1083
1084     if( anIntColor!=aBackColor )
1085       theFillAsp->SetDistinguishOn();
1086     else
1087       theFillAsp->SetDistinguishOff();
1088
1089     aGroup->SetClosed (isSupressBackFaces);
1090     Handle(Graphic3d_AspectFillArea3d) aFillAsp = new Graphic3d_AspectFillArea3d (*(theFillAsp.operator->()));
1091     if (isSupressBackFaces)
1092     {
1093       aFillAsp->SuppressBackFace();
1094     }
1095     aGroup->SetPrimitivesAspect (aFillAsp);
1096
1097     if( IsFacePolygons )
1098     {
1099       aGroup->AddPrimitiveArray ( thePolygons );
1100     }
1101
1102     if( IsVolumePolygons )
1103     {
1104       aGroup->AddPrimitiveArray ( theVolumesInShad );
1105     }
1106   }
1107
1108   if ( IsPolylines && !IsPolygonsEdgesOff )
1109   {
1110     Prs3d_Root::NewGroup ( Prs );
1111     Handle (Graphic3d_Group) aLGroup = Prs3d_Root::CurrentGroup ( Prs );
1112
1113     theFillAsp->SetEdgeOff();
1114     if ( IsSelected )
1115       aLGroup->SetPrimitivesAspect ( theLineAsp );
1116     else
1117     {
1118       aLGroup->SetPrimitivesAspect ( theFillAsp );
1119       aLGroup->SetPrimitivesAspect ( new Graphic3d_AspectLine3d
1120         ( anEdgeColor, Aspect_TOL_SOLID, aWidth ) );
1121     }
1122     aLGroup->AddPrimitiveArray ( theLines );
1123     theFillAsp->SetEdgeOn();
1124   }
1125
1126   if ( IsLinkPolylines )
1127   {
1128     Prs3d_Root::NewGroup ( Prs );
1129     Handle (Graphic3d_Group) aBeamGroup = Prs3d_Root::CurrentGroup ( Prs );
1130
1131     theFillAsp->SetEdgeOff();
1132     if ( !IsSelected )
1133       aBeamGroup->SetPrimitivesAspect ( theFillAsp );
1134     aBeamGroup->SetPrimitivesAspect ( theLineAsp );
1135     aBeamGroup->AddPrimitiveArray ( theLinkLines );
1136     theFillAsp->SetEdgeOn();
1137   }
1138
1139   if ( IsPolygons && theFillAsp->FrontMaterial().Transparency()>=0.01 )
1140   {
1141     Prs3d_Root::NewGroup ( Prs );
1142     Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup ( Prs );
1143
1144     //if ( IsPolygonsEdgesOff )
1145       theFillAsp->SetEdgeOff ();
1146     //else
1147     //  theFillAsp->SetEdgeOn ();
1148
1149     if( anIntColor!=aBackColor )
1150       theFillAsp->SetDistinguishOn();
1151     else
1152       theFillAsp->SetDistinguishOff();
1153
1154     aGroup->SetClosed (isSupressBackFaces);
1155     Handle(Graphic3d_AspectFillArea3d) aFillAsp = new Graphic3d_AspectFillArea3d (*(theFillAsp.operator->()));
1156     if (isSupressBackFaces)
1157     {
1158       aFillAsp->SuppressBackFace();
1159     }
1160     aGroup->SetPrimitivesAspect (aFillAsp);
1161
1162     if( IsFacePolygons )
1163     {
1164       aGroup->AddPrimitiveArray ( thePolygons );
1165     }
1166
1167     if( IsVolumePolygons )
1168     {
1169       aGroup->AddPrimitiveArray ( theVolumesInShad );
1170     }
1171   }
1172 }
1173
1174 //================================================================
1175 // Function : CalculateCenter
1176 // Purpose  :
1177 //================================================================
1178 void MeshVS_MeshPrsBuilder::CalculateCenter (const TColStd_Array1OfReal& theCoords,
1179                                              const Standard_Integer NbNodes,
1180                                              Standard_Real &xG,
1181                                              Standard_Real &yG,
1182                                              Standard_Real &zG)
1183 {
1184   xG = yG = zG = 0;
1185   if ( NbNodes < 4 )
1186   {
1187     for ( Standard_Integer k=1; k<=NbNodes; k++)
1188     {
1189       xG += theCoords(3*k-2);
1190       yG += theCoords(3*k-1);
1191       zG += theCoords(3*k);
1192     }
1193     xG /= Standard_Real(NbNodes);
1194     yG /= Standard_Real(NbNodes);
1195     zG /= Standard_Real(NbNodes);
1196   }
1197   else
1198   {
1199     Standard_Integer a = 1, b = 3;
1200     xG = ( theCoords( 3*a-2 ) + theCoords( 3*b-2 ) ) / 2.0;
1201     yG = ( theCoords( 3*a-1 ) + theCoords( 3*b-1 ) ) / 2.0;
1202     zG = ( theCoords( 3*a )   + theCoords( 3*b   ) ) / 2.0;
1203   }
1204 }