566f3f7899c661f421e2c8e0bb14f2ae869135b1
[occt.git] / src / MeshVS / MeshVS_NodalColorPrsBuilder.cxx
1 // Created on: 2003-11-12
2 // Created by: Alexander SOLOVYOV
3 // Copyright (c) 2003-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #define _POLYGONES_
22 // if define _POLYGONES_ ColorPrsBuilder use ArrayOfPolygons for drawing faces
23
24 #include <MeshVS_NodalColorPrsBuilder.ixx>
25
26 #include <Graphic3d_AspectFillArea3d.hxx>
27 #include <Graphic3d_AspectLine3d.hxx>
28 #include <Graphic3d_ArrayOfPolygons.hxx>
29 #include <Graphic3d_ArrayOfPolylines.hxx>
30 #include <Graphic3d_Vertex.hxx>
31 #include <Graphic3d_Group.hxx>
32 #include <Graphic3d_Array1OfVertex.hxx>
33 #include <Graphic3d_TextureParams.hxx>
34
35 #include <Prs3d_ShadingAspect.hxx>
36 #include <Prs3d_Root.hxx>
37 #include <Prs3d_LineAspect.hxx>
38
39 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
40 #include <TColStd_ListIteratorOfListOfInteger.hxx>
41 #include <TColStd_Array1OfReal.hxx>
42 #include <TColStd_HArray1OfReal.hxx>
43 #include <TColStd_Array1OfInteger.hxx>
44 #include <TColStd_SequenceOfInteger.hxx>
45 #include <TColStd_HPackedMapOfInteger.hxx>
46
47 #include <MeshVS_DisplayModeFlags.hxx>
48 #include <MeshVS_DrawerAttribute.hxx>
49 #include <MeshVS_DataSource.hxx>
50 #include <MeshVS_Drawer.hxx>
51 #include <MeshVS_Mesh.hxx>
52 #include <MeshVS_MeshPrsBuilder.hxx>
53 #include <MeshVS_HArray1OfSequenceOfInteger.hxx>
54 #include <MeshVS_Buffer.hxx>
55
56 #include <gp_Pnt.hxx>
57 #include <Image_PixMap.hxx>
58 #include <Graphic3d_Texture2D.hxx>
59 #include <Graphic3d_TypeOfTextureMode.hxx>
60 #include <Standard_DefineHandle.hxx>
61 #include <PrsMgr_PresentationManager3d.hxx>
62 #include <Graphic3d_Array1OfVertexNT.hxx>
63 #include <AIS_Drawer.hxx>
64 #include <Quantity_Array1OfColor.hxx>
65 #include <Aspect_SequenceOfColor.hxx>
66
67 /*
68   Class       : MeshVS_ImageTexture2D
69   Description : Texture for nodal presentation
70 */
71 class MeshVS_ImageTexture2D : public Graphic3d_Texture2D
72 {
73
74 public:
75
76   MeshVS_ImageTexture2D (const Handle(Image_PixMap)& theImg)
77   : Graphic3d_Texture2D ("", Graphic3d_TOT_2D),
78     myImage (theImg)
79   {
80     myParams->SetModulate (Standard_True);
81     myParams->SetFilter   (Graphic3d_TOTF_BILINEAR);
82   }
83
84   virtual ~MeshVS_ImageTexture2D()
85   {
86     //
87   }
88
89   virtual Standard_Boolean IsDone() const
90   {
91     return !myImage.IsNull() && !myImage->IsEmpty();
92   }
93
94   virtual Handle(Image_PixMap) GetImage() const
95   {
96     return myImage;
97   }
98
99 private:
100
101   Handle(Image_PixMap) myImage;
102
103 public:
104
105   DEFINE_STANDARD_RTTI(MeshVS_ImageTexture2D)
106
107 };
108
109 DEFINE_STANDARD_HANDLE    (MeshVS_ImageTexture2D, Graphic3d_Texture2D)
110 IMPLEMENT_STANDARD_HANDLE (MeshVS_ImageTexture2D, Graphic3d_Texture2D)
111 IMPLEMENT_STANDARD_RTTIEXT(MeshVS_ImageTexture2D, Graphic3d_Texture2D)
112
113 //================================================================
114 // Function : getNearestPow2
115 // Purpose  : Returns the nearest power of two greater than the
116 //            argument value
117 //================================================================
118 static inline Standard_Integer getNearestPow2( Standard_Integer theValue )
119 {
120   // Precaution against overflow
121   Standard_Integer aHalfMax = IntegerLast() >> 1, aRes = 1;
122   if ( theValue > aHalfMax ) theValue = aHalfMax;
123   while ( aRes < theValue ) aRes <<= 1;
124   return aRes;
125 }
126
127 /*
128   Class       : MeshVS_NodalColorPrsBuilder
129   Description : This class provides methods to create presentation of
130                 nodes with assigned color (See hxx for more description )
131 */
132
133 //================================================================
134 // Function : Constructor MeshVS_NodalColorPrsBuilder
135 // Purpose  :
136 //================================================================
137 MeshVS_NodalColorPrsBuilder::MeshVS_NodalColorPrsBuilder ( const Handle(MeshVS_Mesh)& Parent,
138                                                            const MeshVS_DisplayModeFlags& Flags,
139                                                            const Handle (MeshVS_DataSource)& DS,
140                                                            const Standard_Integer Id,
141                                                            const MeshVS_BuilderPriority& Priority )
142 : MeshVS_PrsBuilder ( Parent, Flags, DS, Id, Priority ),
143   myUseTexture( Standard_False ),
144   myInvalidColor( Quantity_NOC_GRAY )
145 {
146   SetExcluding ( Standard_True );
147 }
148
149 //================================================================
150 // Function : Build
151 // Purpose  :
152 //================================================================
153 void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
154                                           const TColStd_PackedMapOfInteger& IDs,
155                                           TColStd_PackedMapOfInteger& IDsToExclude,
156                                           const Standard_Boolean IsElement,
157                                           const Standard_Integer DisplayMode) const
158 {
159   Handle (MeshVS_DataSource) aSource = GetDataSource();
160   Handle (MeshVS_Drawer)     aDrawer = GetDrawer();
161   if ( aSource.IsNull() || aDrawer.IsNull() )
162     return;
163
164   Standard_Integer aMaxFaceNodes;
165   if ( !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, aMaxFaceNodes ) || aMaxFaceNodes <= 0 )
166     return;
167
168   MeshVS_Buffer aCoordsBuf (3*aMaxFaceNodes*sizeof(Standard_Real));
169   TColStd_Array1OfReal aCoords ( aCoordsBuf, 1, 3 * aMaxFaceNodes );
170   Standard_Integer NbNodes;
171   MeshVS_EntityType aType;
172
173   if ( !( DisplayMode & GetFlags() ) || !IsElement )
174     return;
175
176   if ( myUseTexture && ( !myTextureCoords.Extent() || !myTextureColorMap.Length() ) ||
177        !myUseTexture && !myNodeColorMap.Extent() )
178     return;
179
180   // subtract the hidden elements and ids to exclude (to minimise allocated memory)
181   TColStd_PackedMapOfInteger anIDs;
182   anIDs.Assign( IDs );
183   Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
184   if ( !aHiddenElems.IsNull() )
185     anIDs.Subtract( aHiddenElems->Map() );
186   anIDs.Subtract( IDsToExclude );
187
188   Standard_Boolean IsReflect = Standard_False, IsMeshSmoothShading = Standard_False;
189   aDrawer->GetBoolean( MeshVS_DA_ColorReflection, IsReflect );
190   aDrawer->GetBoolean( MeshVS_DA_SmoothShading,   IsMeshSmoothShading );
191
192   // Following parameter are used for texture presentation only
193   int nbColors = 0; // Number of colors from color map
194   int nbTextureColors = 0; // Number of colors in texture (it will be pow of 2)
195   if ( myUseTexture )
196   {
197     nbColors = myTextureColorMap.Length();
198     nbTextureColors = getNearestPow2( nbColors );
199   }
200
201   Standard_Integer aSize = anIDs.Extent();
202
203   // Calculate maximum possible number of vertices and bounds
204   Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
205   Standard_Integer PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0;
206   TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
207   for( ; it.More(); it.Next() )
208   {
209     Standard_Integer aKey = it.Key();
210     if ( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
211       MeshVS_MeshPrsBuilder::HowManyPrimitives
212       ( aTopo, Standard_True, Standard_False, NbNodes,
213       PolygonVerticesFor3D, PolygonBoundsFor3D );
214   }
215
216   // Draw faces with nodal color
217   // OCC20644 Use "plastic" material as it is "non-physic" and so it is easier
218   // to get the required colors (see TelUpdateMaterial() function in OpenGl_attri.c)
219   Graphic3d_MaterialAspect aMaterial[ 2 ];
220   aMaterial[ 0 ] = Graphic3d_MaterialAspect( Graphic3d_NOM_PLASTIC );
221   aMaterial[ 1 ] = Graphic3d_MaterialAspect( Graphic3d_NOM_PLASTIC );
222   Standard_Integer i;
223   for ( i = 0; i < 2; i++ )
224   {
225     if ( !IsReflect )
226     {
227       aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_SPECULAR );
228       aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_AMBIENT );
229       aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_DIFFUSE );
230       aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_EMISSION );
231     }
232     else{
233       // OCC20644 Using the material with reflection properties same as in
234       // ElementalColorPrsBuilder, to get the same colors.
235       // Additionally, ambient and diffuse coefficients are used below to scale incoming colors,
236       // to simulate TelUpdateMaterial() function from OpenGl_attri.c.
237       // This is mandatory, as these "scaled" colors are then passed directly to OpenGL
238       // as ambient and diffuse colors of the current material using glColorMaterial().
239       // In ElementalColorPrsBuilder we do not need to do scale the colors, as this
240       // is done by TelUpdateMaterial().
241       // 0.5 is used to have the colors in 3D maximally similar to those in the color scale.
242       // This is possible when the sum of all coefficient is equal to 1.
243       aMaterial[i].SetAmbient( .5 );
244       aMaterial[i].SetDiffuse( .5 );
245       aMaterial[i].SetSpecular( 0. );
246       aMaterial[i].SetEmissive( 0. );
247     }
248
249  }
250
251
252   // Create array of polygons for interior presentation of faces and volumes
253   Handle(Graphic3d_ArrayOfPolygons) aCPolyArr = new Graphic3d_ArrayOfPolygons
254     ( aMaxFaceNodes * aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D,
255     0, myUseTexture || IsReflect, !myUseTexture, Standard_False, myUseTexture );
256
257   // Create array of polylines for presentation of edges
258   // (used for optimization insted of SetEdgeOn method call)
259   Handle(Graphic3d_ArrayOfPolylines) aPolyL = new Graphic3d_ArrayOfPolylines
260     ( ( aMaxFaceNodes + 1 ) * aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D );
261
262   gp_Pnt P, Start;
263   Standard_Real aMin = gp::Resolution() * gp::Resolution();
264   gp_Dir aDefNorm( 0., 0., 1. );
265
266   // Prepare for scaling the incoming colors
267   Standard_Real anColorRatio = aMaterial[0].Ambient();
268
269   for( it.Reset(); it.More(); it.Next() )
270   {
271     Standard_Integer aKey = it.Key();
272     if ( aSource->GetGeom  ( aKey, Standard_True, aCoords, NbNodes, aType ) )
273     {
274       MeshVS_Buffer aNodesBuf (NbNodes*sizeof(Standard_Integer));
275       TColStd_Array1OfInteger aNodes(aNodesBuf, 1, NbNodes);
276       if ( !aSource->GetNodesByElement ( aKey, aNodes, NbNodes ) )
277         continue;
278
279       Quantity_Color aNColor;
280
281       Standard_Boolean isValid = Standard_True;
282       Standard_Integer i;
283       if ( myUseTexture )
284       {
285         for ( i = 1; i <= NbNodes && isValid; i++ )
286           isValid = myTextureCoords.IsBound( aNodes( i ) );
287       }
288       else
289       {
290         for ( i = 1; i <= NbNodes && isValid; i++ )
291           isValid = GetColor ( aNodes( i ), aNColor );
292       }
293
294       if ( !isValid )
295         continue;
296
297       // Preparing normal(s) to show reflections if requested
298       Handle(TColStd_HArray1OfReal) aNormals;
299       Standard_Boolean hasNormals =
300         ( IsReflect && aSource->GetNormalsByElement( aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals ) );
301
302       if ( aType == MeshVS_ET_Face )
303       {
304         aCPolyArr->AddBound ( NbNodes );
305         aPolyL->AddBound ( NbNodes + 1 );
306
307         for ( i = 1; i <= NbNodes; i++)
308         {
309           P = gp_Pnt( aCoords( 3 * i - 2 ), aCoords( 3 * i - 1 ), aCoords( 3 * i ) );
310           if ( myUseTexture )
311           {
312             int anId = aNodes( i );
313             double aTexCoord = myTextureCoords( anId );
314
315             // transform texture coordinate in accordance with number of colors specified
316             // by upper level and real size of Gl texture
317             // The Gl texture has border colors interpolated with the colors from the color map,
318             // thats why we need to shrink texture coordinates around the middle point to
319             // exclude areas where the map colors are interpolated with the borders color
320             double aWrapCoord = 1.0 / (2.0 * nbTextureColors) + aTexCoord * (nbColors - 1.0) / nbTextureColors;
321
322             if ( hasNormals )
323             {
324               gp_Vec aNorm(aNormals->Value( 3 * i - 2 ),
325                            aNormals->Value( 3 * i - 1 ),
326                            aNormals->Value( 3 * i     ));
327               // There are two "rows" of colors: user's invalid color at the top
328               // of texture and line of map colors at the bottom of the texture.
329               // Since the texture has borders, which are interpolated with the "rows" of colors
330               // we should specify the 0.25 offset to get the correct texture color
331               aNorm.SquareMagnitude() > aMin ?
332                 aCPolyArr->AddVertex(P, gp_Dir( aNorm ),
333                   gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ) :
334                 aCPolyArr->AddVertex(P, aDefNorm,
335                   gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
336             }
337             else
338               aCPolyArr->AddVertex( P, aDefNorm,
339                 gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
340           }
341           else
342           {
343             GetColor ( aNodes( i ), aNColor );
344
345             if ( IsReflect )
346             {
347               // Simulating TelUpdateMaterial() from OpenGl_attri.c
348               // to get the same colors in elemental and nodal color prs builders
349               aNColor.SetValues(anColorRatio * aNColor.Red(),
350                                 anColorRatio * aNColor.Green(),
351                                 anColorRatio * aNColor.Blue(),
352                                 Quantity_TOC_RGB);
353
354               if ( hasNormals )
355               {
356                 gp_Vec aNorm(aNormals->Value( 3 * i - 2 ),
357                   aNormals->Value( 3 * i - 1 ),
358                   aNormals->Value( 3 * i     ));
359                 aNorm.SquareMagnitude() > aMin ?
360                   aCPolyArr->AddVertex(P, gp_Dir( aNorm ), aNColor ) :
361                 aCPolyArr->AddVertex(P, aDefNorm       , aNColor );
362               }
363               else
364                 aCPolyArr->AddVertex(P, aDefNorm, aNColor );
365             }
366             else
367               aCPolyArr->AddVertex( P, aNColor );
368           }
369           aPolyL->AddVertex ( P );
370           if ( i == 1 )
371             Start = P;
372         }
373         aPolyL->AddVertex ( Start );
374
375         // if IsExcludingOn then presentation must not be built by other builders
376         if ( IsExcludingOn() )
377           IDsToExclude.Add( aKey );
378       }
379       else if ( aType == MeshVS_ET_Volume )
380       {
381         if ( !aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
382           continue;
383
384         // iterate through faces of volume
385         for ( Standard_Integer k = aTopo->Lower(), last = aTopo->Upper(), normIndex = 1; k <= last; k++, normIndex++ )
386         {
387           const TColStd_SequenceOfInteger& aSeq = aTopo->Value( k );
388           Standard_Integer m = aSeq.Length(), ind;
389
390           // build polygon & polylines for current face
391           aCPolyArr->AddBound( m );
392           aPolyL->AddBound( m + 1 );
393           for ( Standard_Integer j = 1; j <= m; j++ )
394           {
395             ind = aSeq.Value( j );
396             P = gp_Pnt( aCoords( 3 * ind + 1 ),
397                         aCoords( 3 * ind + 2 ),
398                         aCoords( 3 * ind + 3 ) );
399             if ( myUseTexture )
400             {
401               Standard_Integer anId = aNodes( ind + 1 );
402               Standard_Real aTexCoord = myTextureCoords( anId );
403
404               // transform texture coordinate in accordance with number of colors specified
405               // by upper level and real size of Gl texture
406               // The Gl texture has border colors interpolated with the colors from the color map,
407               // thats why we need to shrink texture coordinates around the middle point to
408               // exclude areas where the map colors are interpolated with the borders color
409               double aWrapCoord = 1.0 / (2.0 * nbTextureColors) + aTexCoord * (nbColors - 1.0) / nbTextureColors;
410
411               if ( hasNormals )
412               {
413                 gp_Vec aNorm(aNormals->Value( 3 * i - 2 ),
414                              aNormals->Value( 3 * i - 1 ),
415                              aNormals->Value( 3 * i     ));
416                 // There are two "rows" of colors: user's invalid color at the top
417                 // of texture and line of map colors at the bottom of the texture.
418                 // Since the texture has borders, which are interpolated with the "rows" of colors
419                 // we should specify the 0.25 offset to get the correct texture color
420                 aNorm.SquareMagnitude() > aMin ?
421                   aCPolyArr->AddVertex(P, gp_Dir( aNorm ),
422                     gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ) :
423                   aCPolyArr->AddVertex(P, aDefNorm,
424                     gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
425               }
426               else
427                 aCPolyArr->AddVertex( P, aDefNorm,
428                   gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
429             }
430             else
431             {
432               GetColor( aNodes( ind + 1 ), aNColor );
433               if  ( IsReflect )
434               {
435                 // Simulating TelUpdateMaterial() from OpenGl_attri.c
436                 // to get the same colors in elemental and nodal color prs builders
437                 aNColor.SetValues(anColorRatio * aNColor.Red(),
438                                   anColorRatio * aNColor.Green(),
439                                   anColorRatio * aNColor.Blue(),
440                                   Quantity_TOC_RGB);
441
442                 if ( hasNormals )
443                 {
444                   gp_Vec aNorm(aNormals->Value( 3 * normIndex - 2 ),
445                     aNormals->Value( 3 * normIndex - 1 ),
446                     aNormals->Value( 3 * normIndex ));
447                   aNorm.SquareMagnitude() > aMin ?
448                     aCPolyArr->AddVertex( P, gp_Dir( aNorm ), aNColor ) :
449                   aCPolyArr->AddVertex( P, aDefNorm       , aNColor );
450                 }
451                 else
452                   aCPolyArr->AddVertex( P, aDefNorm, aNColor );
453               }
454               else
455                 aCPolyArr->AddVertex( P, aNColor );
456             }
457             aPolyL->AddVertex ( P );
458             if ( j == 1 )
459               Start = P;
460           }
461           aPolyL->AddVertex ( Start );
462         }
463
464         // if IsExcludingOn then presentation must not be built by other builders
465         if ( IsExcludingOn() )
466           IDsToExclude.Add( aKey );
467       }
468     }
469   } // for ( ...
470
471   Handle(Graphic3d_AspectFillArea3d) anAsp;
472
473 //  Aspect_InteriorStyle  aStyle;
474 //  Standard_Integer      aStyleInt;
475   Aspect_TypeOfLine     anEdgeType = Aspect_TOL_SOLID;
476   Standard_Integer      anEdgeInt;
477   Standard_Real         anEdgeWidth;
478   Quantity_Color        anInteriorColor;
479   Quantity_Color        anEdgeColor, aLineColor;
480   Standard_Boolean      aShowEdges = Standard_True;
481
482   aDrawer->GetColor  ( MeshVS_DA_InteriorColor, anInteriorColor );
483   aDrawer->GetColor  ( MeshVS_DA_EdgeColor, anEdgeColor );
484   aDrawer->GetColor  ( MeshVS_DA_BeamColor, aLineColor );
485   aDrawer->GetDouble ( MeshVS_DA_EdgeWidth, anEdgeWidth );
486   aDrawer->GetBoolean( MeshVS_DA_ShowEdges, aShowEdges );
487
488   if ( aDrawer->GetInteger ( MeshVS_DA_EdgeType, anEdgeInt ) )
489     anEdgeType = (Aspect_TypeOfLine) anEdgeInt;
490
491   if ( myUseTexture )
492   {
493     Handle(AIS_Drawer) anAISDrawer =  myParentMesh->Attributes();
494     if ( anAISDrawer.IsNull() )
495       return;
496
497     anAISDrawer->SetShadingAspect( new Prs3d_ShadingAspect() );
498     anAsp = anAISDrawer->ShadingAspect()->Aspect();
499     if ( anAsp.IsNull() )
500       return;
501
502     anAsp->SetFrontMaterial( aMaterial[ 0 ] );
503     anAsp->SetBackMaterial( aMaterial[ 1 ] );
504
505
506     Handle(Graphic3d_Texture2D) aTexture = CreateTexture();
507     if ( aTexture.IsNull() )
508       return;
509
510     anAsp->SetTextureMapOn();
511     anAsp->SetTextureMap( aTexture );
512     anAsp->SetInteriorColor( Quantity_NOC_WHITE );
513   }
514   else
515   {
516 //    if ( aDrawer->GetInteger ( MeshVS_DA_InteriorStyle, aStyleInt ) )
517 //      aStyle = (Aspect_InteriorStyle)aStyleInt;
518
519     anAsp = new Graphic3d_AspectFillArea3d (
520       Aspect_IS_SOLID, Quantity_NOC_GRAY, anEdgeColor,
521       anEdgeType, anEdgeWidth, aMaterial[ 0 ], aMaterial[ 1 ] );
522   }
523
524   anAsp->SetDistinguishOff();
525   anAsp->SetEdgeOff();
526
527   Handle(Graphic3d_AspectLine3d) anLAsp =
528     new Graphic3d_AspectLine3d( anEdgeColor, anEdgeType, anEdgeWidth );
529
530   Prs3d_Root::NewGroup ( Prs );
531   Handle(Graphic3d_Group) aGroup1 = Prs3d_Root::CurrentGroup ( Prs );
532
533   aGroup1->SetPrimitivesAspect( anAsp );
534   aGroup1->BeginPrimitives();
535   aGroup1->AddPrimitiveArray( aCPolyArr );
536   aGroup1->EndPrimitives();
537
538   if (aShowEdges)
539   {
540     Prs3d_Root::NewGroup ( Prs );
541     Handle(Graphic3d_Group) aGroup2 = Prs3d_Root::CurrentGroup ( Prs );
542
543     anAsp->SetEdgeOff();
544     anAsp->SetTextureMapOff();
545     aGroup2->SetPrimitivesAspect( anAsp );
546     aGroup2->SetPrimitivesAspect( anLAsp );
547     aGroup2->BeginPrimitives();
548     aGroup2->AddPrimitiveArray( aPolyL );
549     aGroup2->EndPrimitives();
550     anAsp->SetEdgeOn();
551   }
552 }
553
554 //================================================================
555 // Function : SetColors
556 // Purpose  :
557 //================================================================
558 void MeshVS_NodalColorPrsBuilder::SetColors (
559   const MeshVS_DataMapOfIntegerColor& theColorMap )
560 {
561   myNodeColorMap = theColorMap;
562 }
563
564 //================================================================
565 // Function : GetColors
566 // Purpose  :
567 //================================================================
568 const MeshVS_DataMapOfIntegerColor& MeshVS_NodalColorPrsBuilder::GetColors() const
569 {
570   return myNodeColorMap;
571 }
572
573 //================================================================
574 // Function : HasColors
575 // Purpose  :
576 //================================================================
577 Standard_Boolean MeshVS_NodalColorPrsBuilder::HasColors () const
578 {
579   return ( myNodeColorMap.Extent() >0 );
580 }
581
582 //================================================================
583 // Function : GetColor
584 // Purpose  :
585 //================================================================
586 Standard_Boolean MeshVS_NodalColorPrsBuilder::GetColor ( const Standard_Integer ID,
587                                                          Quantity_Color& theColor ) const
588 {
589   Standard_Boolean aRes = myNodeColorMap.IsBound ( ID );
590   if ( aRes )
591     theColor = myNodeColorMap.Find ( ID );
592   return aRes;
593 }
594
595 //================================================================
596 // Function : SetColor
597 // Purpose  :
598 //================================================================
599 void MeshVS_NodalColorPrsBuilder::SetColor ( const Standard_Integer theID,
600                                              const Quantity_Color& theCol )
601 {
602   Standard_Boolean aRes = myNodeColorMap.IsBound ( theID );
603   if ( aRes )
604     myNodeColorMap.ChangeFind ( theID ) = theCol;
605   else
606     myNodeColorMap.Bind ( theID, theCol );
607 }
608
609 //================================================================
610 // Function : UseTexture
611 // Purpose  : Specify whether texture must be used to build presentation
612 //================================================================
613 void MeshVS_NodalColorPrsBuilder::UseTexture( const Standard_Boolean theToUse )
614 {
615   myUseTexture = theToUse;
616   if ( myUseTexture )
617     myNodeColorMap.Clear();
618   else
619     myTextureColorMap.Clear();
620 }
621
622 //================================================================
623 // Function : IsUseTexture
624 // Purpose  : Verify whether texture is used to build presentation
625 //================================================================
626 Standard_Boolean MeshVS_NodalColorPrsBuilder::IsUseTexture() const
627 {
628   return myUseTexture;
629 }
630
631 //================================================================
632 // Function : SetColorMap
633 // Purpose  : Set colors to be used for texrture presentation.
634 //            Generate texture in accordance with given parameters
635 //================================================================
636 void MeshVS_NodalColorPrsBuilder::SetColorMap( const Aspect_SequenceOfColor& theColors )
637 {
638   myTextureColorMap = theColors;
639 }
640
641 //================================================================
642 // Function : GetColorMap
643 // Purpose  : Return colors used for texrture presentation
644 //================================================================
645 const Aspect_SequenceOfColor& MeshVS_NodalColorPrsBuilder::GetColorMap() const
646 {
647   return myTextureColorMap;
648 }
649
650 //================================================================
651 // Function : SetInvalidColor
652 // Purpose  : Set color representing invalid texture coordinate
653 //            (laying outside range [0, 1])
654 //================================================================
655 void MeshVS_NodalColorPrsBuilder::SetInvalidColor(
656   const Quantity_Color& theInvalidColor )
657 {
658   myInvalidColor = theInvalidColor;
659 }
660
661 //================================================================
662 // Function : GetInvalidColor
663 // Purpose  : Return color representing invalid texture coordinate
664 //            (laying outside range [0, 1])
665 //================================================================
666 Quantity_Color MeshVS_NodalColorPrsBuilder::GetInvalidColor() const
667 {
668   return myInvalidColor;
669 }
670
671 //================================================================
672 // Function : SetTextureCoords
673 // Purpose  : Specify correspondence between node IDs and texture
674 //            coordinates (range [0, 1])
675 //================================================================
676 void MeshVS_NodalColorPrsBuilder::SetTextureCoords (
677   const TColStd_DataMapOfIntegerReal& theMap )
678 {
679   myTextureCoords = theMap;
680 }
681
682 //================================================================
683 // Function : GetTextureCoords
684 // Purpose  : Get correspondence between node IDs and texture
685 //            coordinates (range [0, 1])
686 //================================================================
687 const TColStd_DataMapOfIntegerReal& MeshVS_NodalColorPrsBuilder::GetTextureCoords() const
688 {
689   return myTextureCoords;
690 }
691
692 //================================================================
693 // Function : SetTextureCoord
694 // Purpose  : Specify correspondence between node ID and texture
695 //            coordinate (range [0, 1])
696 //================================================================
697 void MeshVS_NodalColorPrsBuilder::SetTextureCoord( const Standard_Integer theID,
698                                                    const Standard_Real theCoord )
699 {
700   myTextureCoords.Bind( theID, theCoord );
701 }
702
703 //================================================================
704 // Function : GetTextureCoord
705 // Purpose  : Return correspondence between node IDs and texture
706 //            coordinate (range [0, 1])
707 //================================================================
708 Standard_Real MeshVS_NodalColorPrsBuilder::GetTextureCoord( const Standard_Integer theID )
709 {
710   return myTextureCoords.IsBound( theID ) ? myTextureCoords( theID ) : -1;
711 }
712
713 //================================================================
714 // Function : CreateTexture
715 // Purpose  : Create texture in accordance with myTextureColorMap
716 //================================================================
717 Handle(Graphic3d_Texture2D) MeshVS_NodalColorPrsBuilder::CreateTexture() const
718 {
719   const Standard_Integer aColorsNb = myTextureColorMap.Length();
720   if (aColorsNb == 0)
721   {
722     return NULL;
723   }
724
725   // create and fill image with colors
726   Handle(Image_PixMap) anImage = new Image_PixMap();
727   if (!anImage->InitTrash (Image_PixMap::ImgRGBA, Standard_Size(getNearestPow2 (aColorsNb)), 2))
728   {
729     return NULL;
730   }
731
732   anImage->SetTopDown (false);
733   Image_PixMapData<Image_ColorRGBA>& aData = anImage->EditData<Image_ColorRGBA>();
734   for (Standard_Size aCol = 0; aCol < Standard_Size(aColorsNb); ++aCol)
735   {
736     const Quantity_Color& aSrcColor = myTextureColorMap.Value (Standard_Integer(aCol) + 1);
737     Image_ColorRGBA& aColor = aData.ChangeValue (0, aCol);
738     aColor.r() = int(255.0 * aSrcColor.Red());
739     aColor.g() = int(255.0 * aSrcColor.Green());
740     aColor.b() = int(255.0 * aSrcColor.Blue());
741     aColor.a() = 0xFF;
742   }
743
744   // fill padding bytes
745   const Quantity_Color& aLastColorSrc = myTextureColorMap.Last();
746   const Image_ColorRGBA aLastColor =
747   {{
748     int(255.0 * aLastColorSrc.Red()),
749     int(255.0 * aLastColorSrc.Green()),
750     int(255.0 * aLastColorSrc.Blue()),
751     0xFF
752   }};
753
754   // fill second row
755   for (Standard_Size aCol = (Standard_Size )aColorsNb; aCol < anImage->SizeX(); ++aCol)
756   {
757     aData.ChangeValue (0, aCol) = aLastColor;
758   }
759
760   const Image_ColorRGBA anInvalidColor =
761   {{
762     int(255.0 * myInvalidColor.Red()),
763     int(255.0 * myInvalidColor.Green()),
764     int(255.0 * myInvalidColor.Blue()),
765     0xFF
766   }};
767   for (Standard_Size aCol = 0; aCol < anImage->SizeX(); ++aCol)
768   {
769     aData.ChangeValue (1, aCol) = anInvalidColor;
770   }
771
772   // create texture
773   return new MeshVS_ImageTexture2D (anImage);
774 }