0024428: Implementation of LGPL license
[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
8 // under the terms of the GNU Lesser General Public 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 #include <MeshVS_MeshPrsBuilder.ixx>
17
18 #include <Prs3d_Root.hxx>
19 #include <Prs3d_ShadingAspect.hxx>
20 #include <Prs3d_LineAspect.hxx>
21 #include <Prs3d_PointAspect.hxx>
22
23 #include <Graphic3d_AspectLine3d.hxx>
24 #include <Graphic3d_AspectFillArea3d.hxx>
25 #include <Graphic3d_AspectMarker3d.hxx>
26 #include <Graphic3d_ArrayOfPolygons.hxx>
27 #include <Graphic3d_ArrayOfSegments.hxx>
28 #include <Graphic3d_ArrayOfPoints.hxx>
29 #include <Graphic3d_ArrayOfPolylines.hxx>
30 #include <Graphic3d_Group.hxx>
31
32 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
33 #include <TColStd_ListIteratorOfListOfReal.hxx>
34 #include <TColStd_MapIntegerHasher.hxx>
35 #include <TColStd_Array1OfReal.hxx>
36 #include <TColStd_Array1OfInteger.hxx>
37 #include <TColStd_SequenceOfInteger.hxx>
38 #include <TColStd_PackedMapOfInteger.hxx>
39 #include <TColStd_HPackedMapOfInteger.hxx>
40
41 #include <Quantity_NameOfColor.hxx>
42 #include <Aspect_InteriorStyle.hxx>
43 #include <Select3D_SensitivePoint.hxx>
44
45 #include <MeshVS_DataSource.hxx>
46 #include <MeshVS_Drawer.hxx>
47 #include <MeshVS_Mesh.hxx>
48 #include <MeshVS_Tool.hxx>
49 #include <MeshVS_DrawerAttribute.hxx>
50 #include <MeshVS_MapOfTwoNodes.hxx>
51 #include <MeshVS_Buffer.hxx>
52
53 //================================================================
54 // Function : Constructor MeshVS_MeshPrsBuilder
55 // Purpose  :
56 //================================================================
57 MeshVS_MeshPrsBuilder::MeshVS_MeshPrsBuilder ( const Handle(MeshVS_Mesh)& Parent,
58                                                const Standard_Integer& DisplayModeMask,
59                                                const Handle (MeshVS_DataSource)& DS,
60                                                const Standard_Integer Id,
61                                                const MeshVS_BuilderPriority& Priority )
62 : MeshVS_PrsBuilder ( Parent, DisplayModeMask, DS, Id, Priority )
63 {
64 }
65
66 //================================================================
67 // Function : Build
68 // Purpose  :
69 //================================================================
70 void MeshVS_MeshPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
71                                     const TColStd_PackedMapOfInteger& IDs,
72                                     TColStd_PackedMapOfInteger& IDsToExclude,
73                                     const Standard_Boolean IsElement,
74                                     const Standard_Integer DisplayMode ) const
75 {
76   if ( DisplayMode <= 0 )
77     return;
78
79   Standard_Boolean HasHilightFlag = ( ( DisplayMode & MeshVS_DMF_HilightPrs ) != 0 );
80   Standard_Integer Extent = IDs.Extent();
81
82   if ( HasHilightFlag && Extent == 1)
83     BuildHilightPrs ( Prs, IDs, IsElement );
84   else if ( IsElement )
85     BuildElements ( Prs, IDs, IDsToExclude, DisplayMode );
86   else
87     BuildNodes ( Prs, IDs, IDsToExclude, DisplayMode );
88 }
89
90 //================================================================
91 // Function : BuildNodes
92 // Purpose  :
93 //================================================================
94 void MeshVS_MeshPrsBuilder::BuildNodes ( const Handle(Prs3d_Presentation)& Prs,
95                                          const TColStd_PackedMapOfInteger& IDs,
96                                          TColStd_PackedMapOfInteger& IDsToExclude,
97                                          const Standard_Integer DisplayMode ) const
98 {
99   Handle( MeshVS_DataSource ) aSource = GetDataSource();
100   Handle( MeshVS_Drawer )     aDrawer = GetDrawer();
101   Handle (Graphic3d_AspectMarker3d) aNodeMark =
102     MeshVS_Tool::CreateAspectMarker3d( GetDrawer() );
103   if ( aSource.IsNull() || aDrawer.IsNull() || aNodeMark.IsNull() )
104     return;
105
106   Standard_Boolean DisplayFreeNodes = Standard_True;
107   aDrawer->GetBoolean( MeshVS_DA_DisplayNodes, DisplayFreeNodes );
108   Standard_Boolean HasSelectFlag = ( ( DisplayMode & MeshVS_DMF_SelectionPrs ) != 0 );
109   Standard_Boolean HasHilightFlag = ( ( DisplayMode & MeshVS_DMF_HilightPrs ) != 0 );
110
111   Standard_Real aCoordsBuf[ 3 ];
112   TColStd_Array1OfReal aCoords( *aCoordsBuf, 1, 3 );
113   Standard_Integer NbNodes;
114   MeshVS_EntityType aType;
115
116   if ( !DisplayFreeNodes )
117     return;
118
119   TColStd_PackedMapOfInteger anIDs;
120   anIDs.Assign( IDs );
121   if ( !HasSelectFlag && !HasHilightFlag )
122   {
123     // subtract the hidden nodes and ids to exclude (to minimise allocated memory)
124     Handle(TColStd_HPackedMapOfInteger) aHiddenNodes = myParentMesh->GetHiddenNodes();
125     if ( !aHiddenNodes.IsNull() )
126       anIDs.Subtract( aHiddenNodes->Map() );
127   }
128   anIDs.Subtract( IDsToExclude );
129
130   Standard_Integer upper = anIDs.Extent();
131   if ( upper<=0 )
132     return;
133
134   Handle(Graphic3d_ArrayOfPoints) aNodePoints = new Graphic3d_ArrayOfPoints (upper);
135   Standard_Integer k=0;
136   TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
137   for( ; it.More(); it.Next() )
138   {
139     Standard_Integer aKey = it.Key();
140     if ( aSource->GetGeom ( aKey, Standard_False, aCoords, NbNodes, aType ) )
141     {
142       if ( IsExcludingOn() )
143         IDsToExclude.Add (aKey);
144       k++;
145       aNodePoints->AddVertex (aCoords(1), aCoords(2), aCoords(3));
146     }
147   }
148
149   if ( k>0 )
150   {
151     Prs3d_Root::NewGroup ( Prs );
152     Handle (Graphic3d_Group) aNodeGroup = Prs3d_Root::CurrentGroup ( Prs );
153     aNodeGroup->SetPrimitivesAspect ( aNodeMark );
154     aNodeGroup->AddPrimitiveArray (aNodePoints);
155   }
156 }
157
158 //================================================================
159 // Function : BuildElements
160 // Purpose  :
161 //================================================================
162 void MeshVS_MeshPrsBuilder::BuildElements( const Handle(Prs3d_Presentation)& Prs,
163                                            const TColStd_PackedMapOfInteger& IDs,
164                                            TColStd_PackedMapOfInteger& IDsToExclude,
165                                            const Standard_Integer DisplayMode ) const
166 {
167   Standard_Integer maxnodes;   
168
169   Handle (MeshVS_DataSource) aSource = GetDataSource();
170   if ( aSource.IsNull() )
171     return;
172
173   Handle( MeshVS_Drawer ) aDrawer = GetDrawer();
174   if ( aDrawer.IsNull() || !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, maxnodes ) ||
175        maxnodes <= 0 )
176     return;
177
178   //----------- extract useful display mode flags ----------
179   Standard_Integer aDispMode = ( DisplayMode & GetFlags() );
180   if ( ( aDispMode & MeshVS_DMF_DeformedMask) != 0 )
181   {
182     aDispMode /= MeshVS_DMF_DeformedPrsWireFrame;
183     // This transformation turns deformed mesh flags to real display modes
184   }
185   aDispMode &= MeshVS_DMF_OCCMask;
186   //--------------------------------------------------------
187
188   Standard_Real aShrinkCoef;
189   aDrawer->GetDouble ( MeshVS_DA_ShrinkCoeff, aShrinkCoef );
190
191   Standard_Boolean IsWireFrame    = ( aDispMode==MeshVS_DMF_WireFrame ),
192                    IsShading      = ( aDispMode==MeshVS_DMF_Shading ),
193                    IsShrink       = ( aDispMode==MeshVS_DMF_Shrink ),
194                    HasHilightFlag = ( ( DisplayMode & MeshVS_DMF_HilightPrs )   != 0 ),
195                    HasSelectFlag  = ( ( DisplayMode & MeshVS_DMF_SelectionPrs ) != 0 ),
196                    IsMeshReflect, IsMeshAllowOverlap, IsReflect, IsMeshSmoothShading = Standard_False;
197
198   aDrawer->GetBoolean  ( MeshVS_DA_Reflection, IsMeshReflect );
199   aDrawer->GetBoolean  ( MeshVS_DA_IsAllowOverlapped, IsMeshAllowOverlap );
200   IsReflect      = ( IsMeshReflect && !HasHilightFlag );
201   aDrawer->GetBoolean  ( MeshVS_DA_SmoothShading, IsMeshSmoothShading );
202
203   // display mode for hilighted prs of groups
204   IsShrink       = ( IsShrink && !HasHilightFlag );
205   IsShading      = ( IsShading || HasHilightFlag );
206
207   //---------- Creating AspectFillArea3d and AspectLine3d -------------
208   Graphic3d_MaterialAspect AMat;
209   aDrawer->GetMaterial ( MeshVS_DA_FrontMaterial, AMat );
210   if ( !IsReflect )
211   {
212     AMat.SetReflectionModeOff(Graphic3d_TOR_AMBIENT);
213     AMat.SetReflectionModeOff(Graphic3d_TOR_DIFFUSE);
214     AMat.SetReflectionModeOff(Graphic3d_TOR_SPECULAR);
215     AMat.SetReflectionModeOff(Graphic3d_TOR_EMISSION);
216   }
217   Handle( Graphic3d_AspectFillArea3d ) aFill = MeshVS_Tool::CreateAspectFillArea3d( GetDrawer(), AMat );
218   Handle( Graphic3d_AspectLine3d ) aBeam = MeshVS_Tool::CreateAspectLine3d ( GetDrawer() );
219   //-------------------------------------------------------------------
220
221   Standard_Boolean IsOverlapControl =
222     !IsMeshAllowOverlap && ( IsWireFrame || IsShading ) && !HasSelectFlag;
223
224   Handle (Graphic3d_ArrayOfPolygons)  aPolygons, aVolumes;
225   Handle (Graphic3d_ArrayOfPolylines) aPolylines, aLinkPolylines;
226
227   Standard_Integer PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0,
228                    PolylineVerticesFor3D = 0, PolylineBoundsFor3D = 0,
229                    NbNodes;
230     
231   // subtract the hidden elements and ids to exclude (to minimise allocated memory)
232   TColStd_PackedMapOfInteger anIDs;
233   anIDs.Assign( IDs );
234   Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
235   if ( !aHiddenElems.IsNull() )
236     anIDs.Subtract( aHiddenElems->Map() );
237   anIDs.Subtract( IDsToExclude );
238
239   Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
240   TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
241   for( ; it.More(); it.Next() )
242   {
243     Standard_Integer aKey = it.Key();
244     if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
245     {
246       if( !HasSelectFlag )
247         HowManyPrimitives( aTopo, Standard_True,  HasSelectFlag, NbNodes,
248                            PolygonVerticesFor3D, PolygonBoundsFor3D );      
249       HowManyPrimitives( aTopo, Standard_False, HasSelectFlag, NbNodes,
250                          PolylineVerticesFor3D, PolylineBoundsFor3D );
251     }
252   }
253
254   Standard_Integer Extent = anIDs.Extent();
255
256   if ( IsReflect )
257   {
258     aPolygons = new Graphic3d_ArrayOfPolygons
259       ( maxnodes*Extent, Extent, 0, Standard_True );
260     aVolumes = new Graphic3d_ArrayOfPolygons
261       ( PolygonVerticesFor3D, PolygonBoundsFor3D, 0, Standard_True );
262   }
263   else
264   {
265     aPolygons = new Graphic3d_ArrayOfPolygons( maxnodes*Extent, Extent );
266     aVolumes = new Graphic3d_ArrayOfPolygons ( PolygonVerticesFor3D, PolygonBoundsFor3D );
267   }
268
269   Standard_Integer howMany = 1;
270   if ( IsOverlapControl )
271     howMany = 2;
272
273   Standard_Boolean showEdges = Standard_True;
274   aDrawer->GetBoolean( MeshVS_DA_ShowEdges, showEdges );
275
276   showEdges = IsWireFrame || showEdges;
277   if ( showEdges )
278   {
279     aPolylines = new Graphic3d_ArrayOfPolylines ( ( maxnodes+1 )*Extent + PolylineVerticesFor3D,
280                                                   howMany * Extent + PolylineBoundsFor3D );
281     aLinkPolylines = new Graphic3d_ArrayOfPolylines ( 2*Extent, Extent );
282   }
283
284   MeshVS_Buffer aCoordsBuf (3*maxnodes*sizeof(Standard_Real));
285   TColStd_Array1OfReal aCoords( aCoordsBuf, 1, 3*maxnodes );  
286   MeshVS_EntityType aType;
287
288   TColStd_PackedMapOfInteger aCustomElements;
289
290   Quantity_Color       anOldEdgeColor;
291   Aspect_InteriorStyle anIntType;
292   Quantity_Color       anIntColor, anEdgeColor;
293   Aspect_TypeOfLine    aLine;
294   Standard_Real        aWidth;
295
296   MeshVS_TwoNodes aTwoNodes;
297   aFill->Values ( anIntType, anIntColor, anEdgeColor, aLine, aWidth );
298   
299   MeshVS_MapOfTwoNodes aLinkNodes;
300   if ( showEdges && IsOverlapControl )
301     // Forbid drawings of edges, which overlap with some links
302     for( it.Reset(); it.More(); it.Next() )
303     {
304       Standard_Integer aKey = it.Key();
305       if ( aSource->GetGeomType ( aKey, Standard_True, aType ) &&
306            aType == MeshVS_ET_Link )
307       {
308         MeshVS_Buffer aNodesBuf (maxnodes * sizeof(Standard_Integer));
309         TColStd_Array1OfInteger aNodes (aNodesBuf, 1, maxnodes);
310         Standard_Integer nbNodes;
311         if ( aSource->GetNodesByElement( aKey, aNodes, nbNodes ) &&
312              nbNodes == 2 )
313         {
314           aTwoNodes.First = aNodes(1);
315           aTwoNodes.Second = aNodes(2);
316           aLinkNodes.Add ( aTwoNodes );
317         }
318       }
319     }
320
321   for( it.Reset(); it.More(); it.Next() )
322   {
323     Standard_Integer aKey = it.Key();
324
325     if ( ! aSource->GetGeom ( aKey, Standard_True, aCoords, NbNodes, aType ) )
326       continue;
327
328     switch ( aType )
329     {
330       case MeshVS_ET_Volume :
331         if( IsExcludingOn() )
332           IDsToExclude.Add (aKey);
333         if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
334         {
335           // !!! TO DO: Overlap control
336           // add wireframe presentation (draw edges for shading mode as well)
337           if ( showEdges )
338             AddVolumePrs ( aTopo, aCoords, NbNodes, aPolylines, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef );
339
340           // add shading presentation
341           if ( ( IsShading || IsShrink ) && !HasSelectFlag )
342             AddVolumePrs ( aTopo, aCoords, NbNodes, aVolumes, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef );
343         }
344         break;
345
346       case MeshVS_ET_Link :
347         if( IsExcludingOn() )
348           IDsToExclude.Add (aKey);
349         if ( showEdges )
350           AddLinkPrs ( aCoords, aLinkPolylines, IsShrink || HasSelectFlag, aShrinkCoef );
351         break;
352
353       case MeshVS_ET_Face :
354         if( IsExcludingOn() )
355           IDsToExclude.Add (aKey);
356         if ( showEdges && IsOverlapControl )
357         {
358           MeshVS_Buffer aNodesBuf (NbNodes * sizeof(Standard_Integer));
359           TColStd_Array1OfInteger aNodes (aNodesBuf, 1, NbNodes);
360           if ( !aSource->GetNodesByElement( aKey, aNodes, NbNodes ) )
361             continue;
362
363           Standard_Integer Last = 0;
364           for ( Standard_Integer i=1; i<=NbNodes; i++ )
365           {
366             if ( i==1 )
367               aTwoNodes.First = aNodes(i);
368             else
369               aTwoNodes.First = aTwoNodes.Second;
370
371             aTwoNodes.Second = ( i<NbNodes ? aNodes(i+1) : aNodes(1) );
372             if ( aLinkNodes.Contains ( aTwoNodes ) )
373               {
374                 aPolylines->AddBound ( i-Last );
375                 for (Standard_Integer j = Last+1; j<=i; j++)
376                   aPolylines->AddVertex ( aCoords(3*j-2), aCoords(3*j-1), aCoords(3*j) );
377                 Last = i;
378               }
379           }
380           if ( NbNodes-Last > 0 )
381           {
382             aPolylines->AddBound ( NbNodes-Last+1 );
383             for (Standard_Integer j = Last+1; j<=NbNodes; j++)
384               aPolylines->AddVertex ( aCoords(3*j-2), aCoords(3*j-1), aCoords(3*j) );
385
386             aPolylines->AddVertex ( aCoords(1), aCoords(2), aCoords(3) );
387           }
388         }
389
390         if ( !IsOverlapControl || IsShading )
391         {
392           if ( !IsOverlapControl && showEdges )
393             AddFaceWirePrs(aCoords, NbNodes, aPolylines,
394                            IsShrink || HasSelectFlag, aShrinkCoef );
395           if ( ( IsShading || IsShrink ) && !HasSelectFlag )
396             AddFaceSolidPrs(aKey, aCoords, NbNodes, maxnodes, aPolygons,
397                             IsReflect, IsShrink || HasSelectFlag,
398                             aShrinkCoef, IsMeshSmoothShading );
399         }
400         break;
401
402       default:
403         aCustomElements.Add( aKey );
404         break;
405     }
406   }
407
408   if ( IsShrink )
409   {
410     anOldEdgeColor = anEdgeColor;
411     aFill->SetEdgeColor ( Quantity_NOC_BLACK );
412   }
413
414   DrawArrays ( Prs, aPolygons, aPolylines, aLinkPolylines, aVolumes,
415     !showEdges, HasSelectFlag, aFill, aBeam );
416
417   if ( !aCustomElements.IsEmpty() )
418     CustomBuild ( Prs, aCustomElements, IDsToExclude, DisplayMode );
419
420   if( IsShrink )
421     aFill->SetEdgeColor( anOldEdgeColor );
422 }
423
424 //================================================================
425 // Function : BuildHilightPrs
426 // Purpose  :
427 //================================================================
428 void MeshVS_MeshPrsBuilder::BuildHilightPrs ( const Handle(Prs3d_Presentation)& Prs,
429                                               const TColStd_PackedMapOfInteger& IDs,
430                                               const Standard_Boolean IsElement ) const
431 {
432   Standard_Integer maxnodes;
433
434   Handle (MeshVS_DataSource) aSource = GetDataSource();
435   if ( aSource.IsNull() || IDs.IsEmpty() )
436     return;
437
438   Handle( MeshVS_Drawer ) aDrawer = GetDrawer();
439   if ( aDrawer.IsNull() || !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, maxnodes ) ||
440        maxnodes <= 0 )
441     return;
442
443   MeshVS_Buffer aCoordsBuf (3*maxnodes*sizeof(Standard_Real));
444   TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3*maxnodes);
445
446   Graphic3d_MaterialAspect AMat;
447   aDrawer->GetMaterial ( MeshVS_DA_FrontMaterial, AMat );
448   AMat.SetReflectionModeOff(Graphic3d_TOR_AMBIENT);
449   AMat.SetReflectionModeOff(Graphic3d_TOR_DIFFUSE);
450   AMat.SetReflectionModeOff(Graphic3d_TOR_SPECULAR);
451   AMat.SetReflectionModeOff(Graphic3d_TOR_EMISSION);
452
453   Handle( Graphic3d_AspectFillArea3d ) aFill     = MeshVS_Tool::CreateAspectFillArea3d( GetDrawer(), AMat );
454   Handle( Graphic3d_AspectLine3d )     aBeam     = MeshVS_Tool::CreateAspectLine3d( GetDrawer() );
455   Handle( Graphic3d_AspectMarker3d )   aNodeMark = MeshVS_Tool::CreateAspectMarker3d( GetDrawer() );
456
457   // Hilight one element or node
458   TColStd_MapIteratorOfPackedMapOfInteger it (IDs);
459   Standard_Integer ID = it.Key(), NbNodes;
460   MeshVS_EntityType aType;
461
462   if ( !aSource->GetGeom ( ID, IsElement, aCoords, NbNodes, aType ) )
463     return;
464
465   Prs3d_Root::NewGroup ( Prs );
466   Handle (Graphic3d_Group) aHilightGroup = Prs3d_Root::CurrentGroup ( Prs );
467
468   switch ( aType )
469   {
470     case MeshVS_ET_Node :
471     {
472       aHilightGroup->SetPrimitivesAspect (aNodeMark);
473       Handle(Graphic3d_ArrayOfPoints) anArrayOfPoints = new Graphic3d_ArrayOfPoints (1);
474       anArrayOfPoints->AddVertex (aCoords(1), aCoords(2), aCoords(3));
475       aHilightGroup->AddPrimitiveArray (anArrayOfPoints);
476     }
477     break;
478
479     case MeshVS_ET_Link:
480     {
481       aHilightGroup->SetPrimitivesAspect ( aBeam );
482       Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(2);
483       aPrims->AddVertex(aCoords(1),aCoords(2),aCoords(3));
484       aPrims->AddVertex(aCoords(4),aCoords(5),aCoords(6));
485       aHilightGroup->AddPrimitiveArray(aPrims);
486     }
487     break;
488
489     case MeshVS_ET_Face:
490     if ( NbNodes > 0 )
491     {
492       aHilightGroup->SetPrimitivesAspect ( aFill );
493       Handle(Graphic3d_ArrayOfPolygons) aPrims = new Graphic3d_ArrayOfPolygons(NbNodes);
494       for ( Standard_Integer k=1; k<=NbNodes; k++)
495         aPrims->AddVertex(aCoords(3*k-2),aCoords(3*k-1),aCoords(3*k));
496       aHilightGroup->AddPrimitiveArray(aPrims);
497     }
498     break;
499
500     case MeshVS_ET_Volume:
501     if( NbNodes > 0 )
502     {
503       Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
504
505       aHilightGroup->SetPrimitivesAspect ( aFill );
506
507       if( aSource->Get3DGeom( ID, NbNodes, aTopo ) )
508       {
509         const Standard_Integer up = aTopo->Upper();
510         const Standard_Integer lo = aTopo->Lower();
511         Standard_Integer nbnodes = 0, i, j;
512         for( i=lo; i<=up; i++ )
513           nbnodes += aTopo->Value( i ).Length();
514
515         Handle(Graphic3d_ArrayOfPolygons) aPrims = new Graphic3d_ArrayOfPolygons(nbnodes,aTopo->Length());
516         for( i=lo; i<=up; i++ )
517         {
518           const TColStd_SequenceOfInteger& aSeq = aTopo->Value( i );
519           const Standard_Integer m = aSeq.Length();
520           aPrims->AddBound(m);
521           for( j=1; j<=m; j++ )
522           {
523             const Standard_Integer ind = 3*aSeq.Value( j );
524             aPrims->AddVertex(aCoords(ind+1),aCoords(ind+2),aCoords(ind+3));
525           }
526         }
527         aHilightGroup->AddPrimitiveArray(aPrims);
528       }
529     }
530     break;
531
532     default:
533       {
534         TColStd_PackedMapOfInteger tmp;
535         CustomBuild ( Prs, IDs, tmp, MeshVS_DMF_HilightPrs );
536       }
537     break;
538   }
539 }
540
541 //================================================================
542 // Function : AddLinkPrs
543 // Purpose  :
544 //================================================================
545 void MeshVS_MeshPrsBuilder::AddLinkPrs (const TColStd_Array1OfReal& theCoords,
546                                         const Handle(Graphic3d_ArrayOfPolylines)& theLines,
547                                         const Standard_Boolean IsShrinked,
548                                         const Standard_Real ShrinkCoef) const
549 {
550   Standard_Real x1 = theCoords(1);
551   Standard_Real y1 = theCoords(2);
552   Standard_Real z1 = theCoords(3);
553   Standard_Real x2 = theCoords(4);
554   Standard_Real y2 = theCoords(5);
555   Standard_Real z2 = theCoords(6);
556   Standard_Real xG, yG, zG;
557
558   if ( IsShrinked )
559   {
560     xG = (x1+x2)/2.0;
561     yG = (y1+y2)/2.0;
562     zG = (z1+z2)/2.0;
563     x1 = (x1 - xG) * ShrinkCoef + xG;
564     x2 = 2.0*xG - x1;
565     y1 = (y1 - yG) * ShrinkCoef + yG;
566     y2 = 2.0*yG - y1;
567     z1 = (z1 - zG) * ShrinkCoef + zG;
568     z2 = 2.0*zG - z1;
569   }
570   theLines->AddBound ( 2 );
571   theLines->AddVertex ( x1, y1, z1 );
572   theLines->AddVertex ( x2, y2, z2 );
573 }
574
575 //================================================================
576 // Function : AddFaceWirePrs
577 // Purpose  :
578 //================================================================
579 void MeshVS_MeshPrsBuilder::AddFaceWirePrs (const TColStd_Array1OfReal& theCoords,
580                                             const Standard_Integer NbNodes,
581                                             const Handle(Graphic3d_ArrayOfPolylines)& theLines,
582                                             const Standard_Boolean IsShrinked,
583                                             const Standard_Real ShrinkCoef) const
584 {
585   Standard_Real xG = 0., yG = 0., zG = 0., X, Y, Z, startX=0., startY=0., startZ=0.;
586   theLines->AddBound ( NbNodes+1 );
587   if ( IsShrinked )
588     CalculateCenter( theCoords, NbNodes, xG, yG, zG );
589
590   for ( Standard_Integer k=1; k<=NbNodes; k++)
591   {
592     X = theCoords(3*k-2);
593     Y = theCoords(3*k-1);
594     Z = theCoords(3*k);
595     if ( IsShrinked )
596     {
597       X = (X - xG) * ShrinkCoef + xG;
598       Y = (Y - yG) * ShrinkCoef + yG;
599       Z = (Z - zG) * ShrinkCoef + zG;
600     }
601     if( k==1 )
602     {
603       startX = X; startY = Y; startZ = Z;
604     }
605     theLines->AddVertex ( X, Y, Z );
606   }
607   theLines->AddVertex( startX, startY, startZ );
608 }
609
610 //================================================================
611 // Function : AddFaceSolidPrs
612 // Purpose  :
613 //================================================================
614 void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer ID,
615                                              const TColStd_Array1OfReal& theCoords,
616                                              const Standard_Integer NbNodes,
617                                              const Standard_Integer MaxNodes,
618                                              const Handle(Graphic3d_ArrayOfPolygons)& thePolygons,
619                                              const Standard_Boolean IsReflected,
620                                              const Standard_Boolean IsShrinked,
621                                              const Standard_Real ShrinkCoef,
622                                              const Standard_Boolean IsMeshSmoothShading) const
623 {
624   Handle( MeshVS_DataSource ) aDS = myParentMesh->GetDataSource();
625   if ( aDS.IsNull() )
626     return;
627
628   Standard_Real xG = 0., yG = 0., zG = 0., X, Y, Z, nx = 0., ny = 0., nz = 0.;
629   thePolygons->AddBound ( NbNodes );
630   if ( IsShrinked )
631     CalculateCenter( theCoords, NbNodes, xG, yG, zG );
632
633   Standard_Boolean allNormals = Standard_True;
634   Standard_Integer k;
635
636   if( IsReflected )
637   {
638     if( IsMeshSmoothShading )
639       for( k=1; k<=NbNodes && allNormals; k++ )
640         allNormals = aDS->GetNodeNormal (k, ID, nx, ny, nz);
641     if( !IsMeshSmoothShading || !allNormals )
642       aDS->GetNormal( ID, MaxNodes, nx, ny, nz );
643   }
644
645   for ( k=1; k<=NbNodes; k++)
646   {
647     X = theCoords(3*k-2);
648     Y = theCoords(3*k-1);
649     Z = theCoords(3*k);
650     if ( IsShrinked )
651     {
652       X = (X - xG) * ShrinkCoef + xG;
653       Y = (Y - yG) * ShrinkCoef + yG;
654       Z = (Z - zG) * ShrinkCoef + zG;
655     }
656
657     if ( IsReflected )
658     {
659       if( IsMeshSmoothShading && allNormals )
660         aDS->GetNodeNormal (k, ID, nx, ny, nz);
661       thePolygons->AddVertex ( X, Y, Z, nx, ny, nz );
662     }
663     else
664       thePolygons->AddVertex ( X, Y, Z );
665   }
666 }
667
668 //================================================================
669 // Function : AddVolumePrs
670 // Purpose  :
671 //================================================================
672 void MeshVS_MeshPrsBuilder::AddVolumePrs (const Handle( MeshVS_HArray1OfSequenceOfInteger )& Topo,
673                                           const TColStd_Array1OfReal& Nodes,
674                                           const Standard_Integer NbNodes,
675                                           const Handle( Graphic3d_ArrayOfPrimitives )& Array,
676                                           const Standard_Boolean IsReflected,
677                                           const Standard_Boolean IsShrinked,
678                                           const Standard_Boolean IsSelect,
679                                           const Standard_Real ShrinkCoef)
680 {
681   Standard_Real c[3]; c[0] = c[1] = c[2] = 0.0;
682   Standard_Integer low = Nodes.Lower(), n=NbNodes;
683
684   if( Topo.IsNull() || Array.IsNull() )
685     return;
686
687   if( IsShrinked )
688   {
689     for( Standard_Integer i=0; i<3*n; i++ )
690       c[i%3] += Nodes.Value( low + i );
691
692     c[0] /= n;
693     c[1] /= n;
694     c[2] /= n;
695   }
696
697   Standard_Boolean IsPolygons = Array->IsKind( STANDARD_TYPE( Graphic3d_ArrayOfPolygons ) );
698   Standard_Real x[2], y[2], z[2];
699   Standard_Integer ind;
700   gp_Vec norm;  
701
702   if( IsPolygons )
703   {    
704     for( Standard_Integer i=Topo->Lower(), topoup=Topo->Upper(); i<=topoup; i++ )
705     {
706       const TColStd_SequenceOfInteger& aSeq = Topo->Value( i );
707       
708       Standard_Integer m = aSeq.Length();
709       Array->AddBound( m );
710       
711       norm.SetCoord( 0, 0, 0 );
712       if( IsReflected )
713       {
714         MeshVS_Buffer PolyNodesBuf (3*m*sizeof(Standard_Real));
715         TColStd_Array1OfReal PolyNodes( PolyNodesBuf, 0, 3*m );
716         PolyNodes.SetValue( 0, m );
717         for( Standard_Integer j=1; j<=m; j++ )
718         {          
719           ind = aSeq.Value( j );
720           PolyNodes.SetValue( 3*j-2, Nodes.Value( low+3*ind ) );
721           PolyNodes.SetValue( 3*j-1, Nodes.Value( low+3*ind+1 ) );
722           PolyNodes.SetValue( 3*j,   Nodes.Value( low+3*ind+2 ) );
723         }
724
725         // compute normal
726         // if( !MeshVS_Tool::GetNormal( PolyNodes, norm ) )
727         //   norm.SetCoord( 0, 0, 0 );
728         MeshVS_Tool::GetAverageNormal( PolyNodes, norm );
729       }
730
731       Standard_Real nx = norm.X(), ny = norm.Y(), nz = norm.Z();
732        
733
734       for( Standard_Integer j=1; j<=m; j++ )
735       {
736         ind = aSeq.Value( j );
737         x[0] = Nodes.Value( low + 3*ind   );
738         y[0] = Nodes.Value( low + 3*ind+1 );
739         z[0] = Nodes.Value( low + 3*ind+2 );
740
741         if( IsShrinked )
742         {
743           x[0] = c[0] + ShrinkCoef * ( x[0]-c[0] );
744           y[0] = c[1] + ShrinkCoef * ( y[0]-c[1] );
745           z[0] = c[2] + ShrinkCoef * ( z[0]-c[2] );
746         }
747     
748         if( IsReflected )
749           Array->AddVertex( x[0], y[0], z[0], nx, ny, nz );
750         else
751           Array->AddVertex( x[0], y[0], z[0] );
752       }
753     }
754   }
755   else if( IsSelect )
756   {
757     for( Standard_Integer i=Topo->Lower(), topoup=Topo->Upper(); i<=topoup; i++ )
758     {
759       const TColStd_SequenceOfInteger& aSeq = Topo->Value( i );
760       Standard_Real pc[3]; pc[0] = pc[1] = pc[2] = 0;
761       Standard_Integer j,m;
762       for( j=1, m=aSeq.Length(); j<=m; j++ )
763       {
764         ind = aSeq.Value( j );
765         for( Standard_Integer k=0; k<3; k++ )
766           pc[k] += Nodes.Value( low + 3*ind+k );
767       }
768       pc[0] /= m;
769       pc[1] /= m;
770       pc[2] /= m;
771
772       Array->AddBound( m+1 );
773       for( j=1, m=aSeq.Length(); j<=m+1; j++ )
774       {
775         ind = aSeq.Value( (j-1)%m + 1 );
776         x[0] = Nodes.Value( low + 3*ind   );
777         y[0] = Nodes.Value( low + 3*ind+1 );
778         z[0] = Nodes.Value( low + 3*ind+2 );
779         x[0] = pc[0] + ShrinkCoef * ( x[0]-pc[0] );
780         y[0] = pc[1] + ShrinkCoef * ( y[0]-pc[1] );
781         z[0] = pc[2] + ShrinkCoef * ( z[0]-pc[2] );
782         Array->AddVertex( x[0], y[0], z[0] );
783       }
784     }
785   }
786   else
787   {
788     Standard_Integer F, S=0, k;
789
790     // Find all pairs of nodes (edges) to draw;
791     // map is used to ensure that each edge will be drawn only once
792     TColStd_PackedMapOfInteger aMap;
793     for( Standard_Integer i=Topo->Lower(), topoup=Topo->Upper(); i<=topoup; i++ )
794     {
795       const TColStd_SequenceOfInteger& aSeq = Topo->Value( i );
796       for( Standard_Integer j=1, m=aSeq.Length(); j<=m; j++ )
797       {
798         if( j==1 )
799           F = aSeq.Value( j );
800         else
801           F = S;
802
803         S = j<m ? aSeq.Value( j+1 ) : aSeq.Value( 1 );
804
805         if( F<S )
806           aMap.Add( F + NbNodes * S );
807         else
808           aMap.Add( S + NbNodes * F );
809       }
810     }
811
812     // draw edges
813     TColStd_MapIteratorOfPackedMapOfInteger anIt( aMap );
814     for( ; anIt.More(); anIt.Next() )
815     {      
816       F = low + 3*(anIt.Key()%NbNodes);
817       S = low + 3*(anIt.Key()/NbNodes);
818
819       x[0] = Nodes.Value( F );
820       y[0] = Nodes.Value( F+1 );
821       z[0] = Nodes.Value( F+2 );
822       x[1] = Nodes.Value( S );
823       y[1] = Nodes.Value( S+1 );
824       z[1] = Nodes.Value( S+2 );
825
826       if( IsShrinked )
827         for( k=0; k<2; k++ )
828         {
829           x[k] = c[0] + ShrinkCoef * ( x[k]-c[0] );
830           y[k] = c[1] + ShrinkCoef * ( y[k]-c[1] );
831           z[k] = c[2] + ShrinkCoef * ( z[k]-c[2] );
832         }
833
834       Array->AddBound( 2 );
835       Array->AddVertex( x[0], y[0], z[0] );
836       Array->AddVertex( x[1], y[1], z[1] );
837     }
838   }
839 }
840
841 //================================================================
842 // Function : HowManyPrimitives
843 // Purpose  :
844 //================================================================
845 void MeshVS_MeshPrsBuilder::HowManyPrimitives (const Handle(MeshVS_HArray1OfSequenceOfInteger)& Topo,
846                                                const Standard_Boolean AsPolygons,
847                                                const Standard_Boolean IsSelect,
848                                                const Standard_Integer NbNodes,
849                                                Standard_Integer& Vertices,
850                                                Standard_Integer& Bounds)
851 {
852   if( !Topo.IsNull() ) {
853     if( AsPolygons || IsSelect )
854     {
855       Standard_Integer B = Topo->Upper()-Topo->Lower()+1;
856       Bounds += B;
857       for( Standard_Integer i=Topo->Lower(), n=Topo->Upper(); i<=n; i++ )
858         Vertices += Topo->Value( i ).Length();      
859
860       if( IsSelect )
861         Vertices+=B;
862     }
863     else
864     {
865       Standard_Integer F = Topo->Upper()-Topo->Lower()+1,
866                        E = NbNodes + F - 2;
867       // number of edges is obtained by Euler's expression for polyhedrons
868       
869       Bounds += E;
870       Vertices += 2*E;
871     }
872   }
873 }
874
875 //================================================================
876 // Function : DrawArrays
877 // Purpose  :
878 //================================================================
879 void MeshVS_MeshPrsBuilder::DrawArrays( const Handle(Prs3d_Presentation)& Prs,
880                                         const Handle(Graphic3d_ArrayOfPolygons)& thePolygons,
881                                         const Handle(Graphic3d_ArrayOfPolylines)& theLines,
882                                         const Handle(Graphic3d_ArrayOfPolylines)& theLinkLines,
883                                         const Handle(Graphic3d_ArrayOfPolygons)& theVolumesInShad,
884                                         const Standard_Boolean IsPolygonsEdgesOff,
885                                         const Standard_Boolean IsSelected,
886                                         const Handle(Graphic3d_AspectFillArea3d)& theFillAsp,
887                                         const Handle(Graphic3d_AspectLine3d)& theLineAsp ) const
888 {
889   if ( theFillAsp.IsNull() )
890     return;
891
892   Standard_Boolean IsFacePolygons   = ( !thePolygons.IsNull() && thePolygons->ItemNumber() > 0 ),
893                    IsVolumePolygons = ( !theVolumesInShad.IsNull() && theVolumesInShad->ItemNumber() > 0 ),
894                    IsPolygons       = IsFacePolygons || IsVolumePolygons,
895                    IsPolylines      = ( !theLines.IsNull() && theLines->ItemNumber() > 0 ),
896                    IsLinkPolylines  = ( !theLinkLines.IsNull() && theLinkLines->ItemNumber() > 0 );
897
898   Aspect_InteriorStyle aStyle;
899   Quantity_Color anIntColor, aBackColor, anEdgeColor; 
900   Aspect_TypeOfLine aType;
901   Standard_Real aWidth;
902
903   theFillAsp->Values( aStyle, anIntColor, aBackColor, anEdgeColor, aType, aWidth );
904
905   if ( IsPolygons && theFillAsp->FrontMaterial().Transparency()<0.01 )
906   {
907     Prs3d_Root::NewGroup ( Prs );
908     Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup ( Prs );
909
910     //if ( IsPolygonsEdgesOff )
911       theFillAsp->SetEdgeOff ();
912     //else
913     //  theFillAsp->SetEdgeOn ();
914
915     if( anIntColor!=aBackColor )
916       theFillAsp->SetDistinguishOn();
917     else
918       theFillAsp->SetDistinguishOff();
919
920     if( IsFacePolygons )
921     {
922       aGroup->SetPrimitivesAspect ( theFillAsp );
923       aGroup->AddPrimitiveArray ( thePolygons );
924     }
925
926     if( IsVolumePolygons )
927     {
928       Handle( Graphic3d_AspectFillArea3d ) aCullFillAsp = 
929           new Graphic3d_AspectFillArea3d( *( theFillAsp.operator->() ) );
930
931       Standard_Boolean isSupressBackFaces = Standard_False;
932       Handle( MeshVS_Drawer ) aDrawer = GetDrawer();
933       if (!aDrawer.IsNull())
934         aDrawer->GetBoolean  ( MeshVS_DA_SupressBackFaces, isSupressBackFaces );
935
936       if (isSupressBackFaces)
937         aCullFillAsp->SuppressBackFace();
938
939       aGroup->SetPrimitivesAspect ( aCullFillAsp );
940       aGroup->AddPrimitiveArray ( theVolumesInShad );
941     }
942   }
943
944   if ( IsPolylines && !IsPolygonsEdgesOff )
945   {
946     Prs3d_Root::NewGroup ( Prs );
947     Handle (Graphic3d_Group) aLGroup = Prs3d_Root::CurrentGroup ( Prs );
948
949     theFillAsp->SetEdgeOff();
950     if ( IsSelected )
951       aLGroup->SetPrimitivesAspect ( theLineAsp );
952     else
953     {
954       aLGroup->SetPrimitivesAspect ( theFillAsp );
955       aLGroup->SetPrimitivesAspect ( new Graphic3d_AspectLine3d
956         ( anEdgeColor, Aspect_TOL_SOLID, aWidth ) );
957     }
958     aLGroup->AddPrimitiveArray ( theLines );
959     theFillAsp->SetEdgeOn();
960   }
961
962   if ( IsLinkPolylines )
963   {
964     Prs3d_Root::NewGroup ( Prs );
965     Handle (Graphic3d_Group) aBeamGroup = Prs3d_Root::CurrentGroup ( Prs );
966
967     theFillAsp->SetEdgeOff();
968     if ( !IsSelected )
969       aBeamGroup->SetPrimitivesAspect ( theFillAsp );
970     aBeamGroup->SetPrimitivesAspect ( theLineAsp );
971     aBeamGroup->AddPrimitiveArray ( theLinkLines );
972     theFillAsp->SetEdgeOn();
973   }
974
975   if ( IsPolygons && theFillAsp->FrontMaterial().Transparency()>=0.01 )
976   {
977     Prs3d_Root::NewGroup ( Prs );
978     Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup ( Prs );
979
980     //if ( IsPolygonsEdgesOff )
981       theFillAsp->SetEdgeOff ();
982     //else
983     //  theFillAsp->SetEdgeOn ();
984
985     if( anIntColor!=aBackColor )
986       theFillAsp->SetDistinguishOn();
987     else
988       theFillAsp->SetDistinguishOff();
989
990     if( IsFacePolygons )
991     {
992       aGroup->SetPrimitivesAspect ( theFillAsp );
993       aGroup->AddPrimitiveArray ( thePolygons );
994     }
995
996     if( IsVolumePolygons )
997     {
998       Handle( Graphic3d_AspectFillArea3d ) aCullFillAsp = 
999           new Graphic3d_AspectFillArea3d( *( theFillAsp.operator->() ) );
1000
1001       Standard_Boolean isSupressBackFaces = Standard_False;
1002       Handle( MeshVS_Drawer ) aDrawer = GetDrawer();
1003       if (!aDrawer.IsNull())
1004         aDrawer->GetBoolean  ( MeshVS_DA_SupressBackFaces, isSupressBackFaces );
1005
1006       if (isSupressBackFaces)
1007         aCullFillAsp->SuppressBackFace();
1008
1009       aGroup->SetPrimitivesAspect ( aCullFillAsp );
1010       aGroup->AddPrimitiveArray ( theVolumesInShad );
1011     }
1012   }
1013 }
1014
1015 //================================================================
1016 // Function : CalculateCenter
1017 // Purpose  :
1018 //================================================================
1019 void MeshVS_MeshPrsBuilder::CalculateCenter (const TColStd_Array1OfReal& theCoords,
1020                                              const Standard_Integer NbNodes,
1021                                              Standard_Real &xG,
1022                                              Standard_Real &yG,
1023                                              Standard_Real &zG)
1024 {
1025   xG = yG = zG = 0;
1026   if ( NbNodes < 4 )
1027   {
1028     for ( Standard_Integer k=1; k<=NbNodes; k++)
1029     {
1030       xG += theCoords(3*k-2);
1031       yG += theCoords(3*k-1);
1032       zG += theCoords(3*k);
1033     }
1034     xG /= Standard_Real(NbNodes);
1035     yG /= Standard_Real(NbNodes);
1036     zG /= Standard_Real(NbNodes);
1037   }
1038   else
1039   {
1040     Standard_Integer a = 1, b = 3;
1041     xG = ( theCoords( 3*a-2 ) + theCoords( 3*b-2 ) ) / 2.0;
1042     yG = ( theCoords( 3*a-1 ) + theCoords( 3*b-1 ) ) / 2.0;
1043     zG = ( theCoords( 3*a )   + theCoords( 3*b   ) ) / 2.0;
1044   }
1045 }