0024428: Implementation of LGPL license
[occt.git] / src / MeshVS / MeshVS_ElementalColorPrsBuilder.cxx
1 // Created on: 2003-11-12
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_ElementalColorPrsBuilder.ixx>
17
18 #include <Graphic3d_AspectFillArea3d.hxx>
19 #include <Graphic3d_AspectLine3d.hxx>
20 #include <Graphic3d_ArrayOfPolygons.hxx>
21 #include <Graphic3d_ArrayOfPolylines.hxx>
22 #include <Graphic3d_Group.hxx>
23
24 #include <Prs3d_ShadingAspect.hxx>
25 #include <Prs3d_Root.hxx>
26 #include <Prs3d_LineAspect.hxx>
27
28 #include <TColStd_MapOfInteger.hxx>
29 #include <TColStd_PackedMapOfInteger.hxx>
30 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
31 #include <TColStd_ListIteratorOfListOfInteger.hxx>
32 #include <TColStd_Array1OfReal.hxx>
33 #include <TColStd_SequenceOfInteger.hxx>
34 #include <TColStd_HArray1OfReal.hxx>
35 #include <TColStd_HPackedMapOfInteger.hxx>
36
37 #include <MeshVS_DisplayModeFlags.hxx>
38 #include <MeshVS_DataSource.hxx>
39 #include <MeshVS_Mesh.hxx>
40 #include <MeshVS_DataMapOfColorMapOfInteger.hxx>
41 #include <MeshVS_DataMapOfTwoColorsMapOfInteger.hxx>
42 #include <MeshVS_Drawer.hxx>
43 #include <MeshVS_DrawerAttribute.hxx>
44 #include <MeshVS_DataMapIteratorOfDataMapOfIntegerTwoColors.hxx>
45 #include <MeshVS_DataMapIteratorOfDataMapOfIntegerColor.hxx>
46 #include <MeshVS_DataMapIteratorOfDataMapOfTwoColorsMapOfInteger.hxx>
47 #include <MeshVS_DataMapIteratorOfDataMapOfColorMapOfInteger.hxx>
48 #include <MeshVS_MeshPrsBuilder.hxx>
49 #include <MeshVS_Buffer.hxx>
50
51
52 //================================================================
53 // Function : Constructor MeshVS_ElementalColorPrsBuilder
54 // Purpose  :
55 //================================================================
56 MeshVS_ElementalColorPrsBuilder::MeshVS_ElementalColorPrsBuilder
57   ( const Handle(MeshVS_Mesh)& Parent,
58     const MeshVS_DisplayModeFlags& Flags,
59     const Handle (MeshVS_DataSource)& DS,
60     const Standard_Integer Id,
61     const MeshVS_BuilderPriority& Priority )
62 : MeshVS_PrsBuilder ( Parent, Flags, DS, Id, Priority )
63 {
64   SetExcluding ( Standard_True );
65 }
66
67 //================================================================
68 // Function : Build
69 // Purpose  :
70 //================================================================
71 void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
72                                               const TColStd_PackedMapOfInteger& IDs,
73                                               TColStd_PackedMapOfInteger& IDsToExclude,
74                                               const Standard_Boolean IsElement,
75                                               const Standard_Integer DisplayMode) const
76 {
77   Handle (MeshVS_DataSource) aSource = GetDataSource();
78   Handle (MeshVS_Drawer)     aDrawer = GetDrawer();
79
80   if ( aSource.IsNull() || aDrawer.IsNull() )
81     return;
82
83   Standard_Integer aMaxFaceNodes;
84   if ( !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, aMaxFaceNodes ) && aMaxFaceNodes<=0 )
85     return;
86
87   MeshVS_DataMapOfIntegerColor* anElemColorMap = (MeshVS_DataMapOfIntegerColor*) &myElemColorMap1;
88   MeshVS_DataMapOfIntegerTwoColors* anElemTwoColorsMap = (MeshVS_DataMapOfIntegerTwoColors*)&myElemColorMap2;
89
90   MeshVS_DataMapOfColorMapOfInteger     aColorsOfElements;
91   MeshVS_DataMapOfTwoColorsMapOfInteger aTwoColorsOfElements;
92
93   MeshVS_Buffer aCoordsBuf (3*aMaxFaceNodes*sizeof(Standard_Real));
94   TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3*aMaxFaceNodes);
95   Standard_Integer NbNodes;
96   MeshVS_EntityType aType;
97
98   if ( !( DisplayMode & GetFlags() ) || !IsElement ||
99        ( myElemColorMap1.IsEmpty() && myElemColorMap2.IsEmpty() ) )
100     return;
101
102   // subtract the hidden elements and ids to exclude (to minimise allocated memory)
103   TColStd_PackedMapOfInteger anIDs;
104   anIDs.Assign( IDs );
105   Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
106   if ( !aHiddenElems.IsNull() )
107     anIDs.Subtract( aHiddenElems->Map() );
108   anIDs.Subtract( IDsToExclude );
109
110   // STEP 0: We looking for two colored elements, who has equal two colors and move it
111   // to map of elements with one assigned color
112   TColStd_ListOfInteger aColorOne;
113   for ( MeshVS_DataMapIteratorOfDataMapOfIntegerTwoColors anIter ( *anElemTwoColorsMap ); anIter.More(); anIter.Next () )
114   {
115     Standard_Integer aKey   = anIter.Key ();
116     MeshVS_TwoColors aValue = anIter.Value ();
117     Quantity_Color   aCol1, aCol2;
118     ExtractColors ( aValue, aCol1, aCol2 );
119     if ( aCol1 == aCol2 )
120     {
121       aColorOne.Append ( aKey );
122       anElemColorMap->Bind ( aKey, aCol1 );
123     }
124   }
125
126   for ( TColStd_ListIteratorOfListOfInteger aLIter ( aColorOne ); aLIter.More(); aLIter.Next() )
127     anElemTwoColorsMap->UnBind ( aLIter.Value() );
128
129   // The map is to resort itself by colors.
130   // STEP 1: We start sorting elements with one assigned color
131   for ( MeshVS_DataMapIteratorOfDataMapOfIntegerColor anIterM ( *anElemColorMap ); anIterM.More(); anIterM.Next () )
132   {
133     Standard_Integer aMKey = anIterM.Key ();
134     // The ID of current element
135     Standard_Boolean IsExist = Standard_False;
136     for ( MeshVS_DataMapIteratorOfDataMapOfColorMapOfInteger anIterC ( aColorsOfElements );
137           anIterC.More() && !IsExist; anIterC.Next () )
138       if ( anIterC.Key()==anIterM.Value() )
139       {
140         TColStd_MapOfInteger& aChangeValue = (TColStd_MapOfInteger&) anIterC.Value();
141         aChangeValue.Add ( aMKey );
142         IsExist = Standard_True;
143       }
144
145     if ( !IsExist )
146     {
147       TColStd_MapOfInteger aNewMap; aNewMap.Add ( aMKey );
148       aColorsOfElements.Bind ( anIterM.Value(), aNewMap );
149     }
150   }
151
152   // STEP 2: We start sorting elements with two assigned colors
153   for ( MeshVS_DataMapIteratorOfDataMapOfIntegerTwoColors anIterM2 ( *anElemTwoColorsMap ); anIterM2.More();
154         anIterM2.Next () )
155   {
156     Standard_Integer aMKey = anIterM2.Key ();
157     // The ID of current element
158     Standard_Boolean IsExist = Standard_False;
159     for ( MeshVS_DataMapIteratorOfDataMapOfTwoColorsMapOfInteger anIterC2 ( aTwoColorsOfElements );
160           anIterC2.More() && !IsExist; anIterC2.Next () )
161       if ( IsEqual ( anIterC2.Key(), anIterM2.Value() ) )
162       {
163         TColStd_MapOfInteger& aChangeValue = (TColStd_MapOfInteger&) anIterC2.Value();
164         aChangeValue.Add ( aMKey );
165         IsExist = Standard_True;
166       }
167
168     if ( !IsExist )
169     {
170       TColStd_MapOfInteger aNewMap; aNewMap.Add ( aMKey );
171       aTwoColorsOfElements.Bind ( anIterM2.Value(), aNewMap );
172     }
173   }
174
175   //Now we are ready to draw faces with equal colors
176   Aspect_InteriorStyle aStyle;
177   Standard_Integer     aStyleInt;
178   Aspect_TypeOfLine    anEdgeType = Aspect_TOL_SOLID;
179   Aspect_TypeOfLine    aLineType = Aspect_TOL_SOLID;
180   Standard_Integer     anEdgeInt, aLineInt;
181   Standard_Real        anEdgeWidth, aLineWidth;
182   Quantity_Color       anInteriorColor;
183   Quantity_Color       anEdgeColor, aLineColor;
184   Standard_Boolean     anEdgeOn = Standard_True, IsReflect = Standard_False,
185                        IsMeshSmoothShading = Standard_False;
186
187   aDrawer->GetColor  ( MeshVS_DA_InteriorColor, anInteriorColor );
188   aDrawer->GetColor  ( MeshVS_DA_EdgeColor, anEdgeColor );
189   aDrawer->GetColor  ( MeshVS_DA_BeamColor, aLineColor );
190   aDrawer->GetDouble ( MeshVS_DA_EdgeWidth, anEdgeWidth );
191   aDrawer->GetDouble ( MeshVS_DA_BeamWidth, aLineWidth );
192   aDrawer->GetBoolean( MeshVS_DA_ShowEdges, anEdgeOn );
193   aDrawer->GetBoolean( MeshVS_DA_ColorReflection, IsReflect );
194   aDrawer->GetBoolean( MeshVS_DA_SmoothShading, IsMeshSmoothShading );
195
196   if ( aDrawer->GetInteger ( MeshVS_DA_InteriorStyle, aStyleInt) )
197     aStyle = (Aspect_InteriorStyle) aStyleInt;
198
199   if ( aDrawer->GetInteger ( MeshVS_DA_EdgeType, anEdgeInt) )
200     anEdgeType = (Aspect_TypeOfLine) anEdgeInt;
201
202   if ( aDrawer->GetInteger ( MeshVS_DA_BeamType, aLineInt) )
203     aLineType = (Aspect_TypeOfLine) aLineInt;
204
205   Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
206   Standard_Integer PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0;
207   TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
208   for( ; it.More(); it.Next() )
209   {
210     Standard_Integer aKey = it.Key();
211     if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
212         MeshVS_MeshPrsBuilder::HowManyPrimitives
213           ( aTopo, Standard_True, Standard_False, NbNodes,
214             PolygonVerticesFor3D, PolygonBoundsFor3D );
215   }
216
217   Graphic3d_MaterialAspect aMaterial[2];
218   Standard_Integer i;
219   for ( i=0; i<2; i++ )
220   {
221     // OCC20644 "plastic" is most suitable here, as it is "non-physic"
222     // so TelUpdateMaterial() from OpenGl_attri.c uses the interior
223     // color from AspectFillArea3d to calculate all material colors
224     aMaterial[i] = Graphic3d_MaterialAspect ( Graphic3d_NOM_PLASTIC );
225
226     // OCC21720 For single-colored elements turning all material components off is a good idea,
227     // as anyhow the normals are not computed and the lighting will be off,
228     // the element color will be taken from Graphic3d_AspectFillArea3d's interior color,
229     // and there is no need to spend time on updating material properties 
230     if ( !IsReflect )
231     {
232       aMaterial[i].SetReflectionModeOff(Graphic3d_TOR_AMBIENT);
233       aMaterial[i].SetReflectionModeOff(Graphic3d_TOR_DIFFUSE);
234       aMaterial[i].SetReflectionModeOff(Graphic3d_TOR_SPECULAR);
235       aMaterial[i].SetReflectionModeOff(Graphic3d_TOR_EMISSION);
236     }
237     else
238     {
239       // OCC20644 This stuff is important in order for elemental and nodal colors
240       // to produce similar visual impression and also to make colors match
241       // those in the color scale most exactly (the sum of all reflection 
242       // coefficients is equal to 1). See also MeshVS_NodalColorPrsBuilder
243       // class for more explanations.
244       aMaterial[i].SetAmbient( .5 );
245       aMaterial[i].SetDiffuse( .5 );
246       aMaterial[i].SetSpecular( 0. );
247       aMaterial[i].SetEmissive( 0. );
248     }
249   }
250
251   // Draw elements with one color
252   for ( MeshVS_DataMapIteratorOfDataMapOfColorMapOfInteger aColIter ( aColorsOfElements ); aColIter.More();
253         aColIter.Next() )
254   {
255     Standard_Integer aSize = aColIter.Value().Extent();
256     if ( aSize<=0 )
257       continue;
258
259     TColStd_PackedMapOfInteger aCustomElements;
260
261     Prs3d_Root::NewGroup ( Prs );
262     Handle ( Graphic3d_Group ) aGGroup = Prs3d_Root::CurrentGroup ( Prs );
263     Prs3d_Root::NewGroup ( Prs );
264     Handle ( Graphic3d_Group ) aLGroup = Prs3d_Root::CurrentGroup ( Prs );
265
266     Handle (Graphic3d_ArrayOfPolygons) aPolyGArr = new Graphic3d_ArrayOfPolygons
267       ( aMaxFaceNodes*aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D, 0, IsReflect );
268     Standard_Boolean IsPolyG = Standard_False;
269
270     Handle (Graphic3d_ArrayOfPolylines) aPolyLArr = new Graphic3d_ArrayOfPolylines
271       ( 2*aSize, aSize );
272     Standard_Boolean IsPolyL = Standard_False;
273
274     // OCC20644 NOTE: aColIter.Key() color is then scaled by TelUpdateMaterial() in OpenGl_attri.c
275     // using the material reflection coefficients. This affects the visual result.
276     Handle(Graphic3d_AspectFillArea3d) anAsp =
277       new Graphic3d_AspectFillArea3d ( Aspect_IS_SOLID, aColIter.Key(), anEdgeColor,
278                                        anEdgeType, anEdgeWidth, aMaterial[0], aMaterial[1] );
279
280     Handle(Graphic3d_AspectLine3d) anLAsp =
281       new Graphic3d_AspectLine3d ( aColIter.Key(), aLineType, aLineWidth );
282
283     anAsp->SetDistinguishOff ();
284     anAsp->SetInteriorColor ( aColIter.Key() );
285     if (anEdgeOn)
286       anAsp->SetEdgeOn();
287     else
288       anAsp->SetEdgeOff();
289
290     for( it.Reset(); it.More(); it.Next() )
291     {
292       Standard_Integer aKey = it.Key();
293       if( aColIter.Value().Contains( aKey ) )
294       {
295         if ( !aSource->GetGeom  ( aKey, Standard_True, aCoords, NbNodes, aType ) )
296           continue;
297
298         if( aType == MeshVS_ET_Face )
299         {
300           aPolyGArr->AddBound ( NbNodes );
301           if( IsExcludingOn() )
302             IDsToExclude.Add( aKey );
303         }
304         else if( aType == MeshVS_ET_Link )
305         {
306           aPolyLArr->AddBound ( NbNodes );
307           if( IsExcludingOn() )
308             IDsToExclude.Add( aKey );
309         }
310         else if( aType == MeshVS_ET_Volume )
311         {
312           if( IsExcludingOn() )
313             IDsToExclude.Add( aKey );
314           if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
315           {
316             MeshVS_MeshPrsBuilder::AddVolumePrs( aTopo, aCoords, NbNodes, aPolyGArr, IsReflect, Standard_False, Standard_False, 1.0 );
317             IsPolyG = Standard_True;
318           }
319           else
320             continue;
321         }
322         else
323         {
324           aCustomElements.Add( aKey );
325           continue;
326         }
327
328         // Preparing normal(s) to show reflections if requested
329         Handle(TColStd_HArray1OfReal) aNormals;
330         Standard_Boolean hasNormals = IsReflect && aSource->GetNormalsByElement( aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals );
331
332         // Adding vertices (with normals if necessary)
333         for ( i=1; i<=NbNodes; i++ )
334           if ( aType == MeshVS_ET_Face )
335           {
336             if ( IsReflect )
337             {
338               hasNormals ? aPolyGArr->AddVertex ( aCoords(3 * i - 2), 
339                                                   aCoords(3 * i - 1), 
340                                                   aCoords(3 * i    ),
341                                                   aNormals->Value(3 * i - 2), 
342                                                   aNormals->Value(3 * i - 1), 
343                                                   aNormals->Value(3 * i    ) ) :
344                            aPolyGArr->AddVertex ( aCoords(3 * i - 2), 
345                                                   aCoords(3 * i - 1), 
346                                                   aCoords(3 * i    ),
347                                                   0., 
348                                                   0., 
349                                                   1. );
350             }
351             else
352               aPolyGArr->AddVertex ( aCoords(3 * i - 2), 
353                                      aCoords(3 * i - 1), 
354                                      aCoords(3 * i    ) );
355             IsPolyG = Standard_True;
356           }
357           else if ( aType == MeshVS_ET_Link )
358           {
359             aPolyLArr->AddVertex ( aCoords(3*i-2), aCoords(3*i-1), aCoords(3*i) );
360             IsPolyL = Standard_True;
361           }
362       }
363     }
364
365     if ( IsPolyG )
366     {
367       aGGroup->SetPrimitivesAspect ( anAsp );
368       aGGroup->AddPrimitiveArray ( aPolyGArr );
369     }
370     if ( IsPolyL )
371     {
372       anAsp->SetEdgeOff();
373       aLGroup->SetPrimitivesAspect ( anAsp );
374       aLGroup->SetPrimitivesAspect ( anLAsp );
375       aLGroup->AddPrimitiveArray ( aPolyLArr );
376       if (anEdgeOn)
377         anAsp->SetEdgeOn();
378       else
379         anAsp->SetEdgeOff();
380     }
381
382     if( !aCustomElements.IsEmpty() )
383       CustomBuild( Prs, aCustomElements, IDsToExclude, DisplayMode );
384   }
385
386   Graphic3d_MaterialAspect aMaterial2[2];
387   for ( i=0; i<2; i++ )
388   {
389     // OCC20644 "plastic" is most suitable here, as it is "non-physic"
390     // so TelUpdateMaterial() from OpenGl_attri.c uses the interior
391     // color from AspectFillArea3d to calculate all material colors
392     aMaterial2[i] = Graphic3d_MaterialAspect ( Graphic3d_NOM_PLASTIC );
393
394     if ( !IsReflect )
395     {
396       // OCC21720 Cannot turn ALL material components off, as such a material
397       // would be ignored by TelUpdateMaterial(), but we need it in order
398       // to have different materials for front and back sides!
399       // Instead, trying to make material color "nondirectional" with 
400       // only ambient component on.
401       aMaterial2[i].SetReflectionModeOn ( Graphic3d_TOR_AMBIENT );
402       aMaterial2[i].SetReflectionModeOff( Graphic3d_TOR_DIFFUSE );
403       aMaterial2[i].SetReflectionModeOff( Graphic3d_TOR_SPECULAR );
404       aMaterial2[i].SetReflectionModeOff( Graphic3d_TOR_EMISSION );
405       aMaterial2[i].SetAmbient ( 1. );
406       aMaterial2[i].SetDiffuse ( 0. );
407       aMaterial2[i].SetSpecular( 0. );
408       aMaterial2[i].SetEmissive( 0. );
409     }
410     else
411     {
412       // OCC20644 This stuff is important in order for elemental and nodal colors
413       // to produce similar visual impression and also to make colors match
414       // those in the color scale most exactly (the sum of all reflection 
415       // coefficients is equal to 1). See also MeshVS_NodalColorPrsBuilder
416       // class for more explanations.
417       aMaterial2[i].SetAmbient( .5 );
418       aMaterial2[i].SetDiffuse( .5 );
419       aMaterial2[i].SetSpecular( 0. );
420       aMaterial2[i].SetEmissive( 0. );
421     }
422   }
423
424   // Draw faces with two color
425   for ( MeshVS_DataMapIteratorOfDataMapOfTwoColorsMapOfInteger aColIter2 ( aTwoColorsOfElements );
426         aColIter2.More(); aColIter2.Next() )
427   {
428     Prs3d_Root::NewGroup ( Prs );
429     Handle ( Graphic3d_Group ) aGroup2 = Prs3d_Root::CurrentGroup ( Prs );
430
431     Standard_Integer aSize = aColIter2.Value().Extent();
432     if ( aSize<=0 )
433       continue;
434
435     Handle (Graphic3d_ArrayOfPolygons) aPolyArr = new Graphic3d_ArrayOfPolygons
436       ( aMaxFaceNodes*aSize, aSize, 0, IsReflect );
437
438     MeshVS_TwoColors aTC = aColIter2.Key();
439     Quantity_Color aMyIntColor, aMyBackColor;
440     ExtractColors ( aTC, aMyIntColor, aMyBackColor );
441
442     // OCC20644 NOTE: aMyIntColor color is then scaled by TelUpdateMaterial() in OpenGl_attri.c
443     // using the material reflection coefficients. This affects the visual result.
444     Handle(Graphic3d_AspectFillArea3d) anAsp =
445       new Graphic3d_AspectFillArea3d ( Aspect_IS_SOLID, aMyIntColor, anEdgeColor,
446                                          anEdgeType, anEdgeWidth, aMaterial2[0], aMaterial2[1] );
447     anAsp->SetDistinguishOn ();
448     anAsp->SetInteriorColor ( aMyIntColor );
449     anAsp->SetBackInteriorColor ( aMyBackColor );
450     if (anEdgeOn)
451       anAsp->SetEdgeOn();
452     else
453       anAsp->SetEdgeOff();
454
455     aGroup2->SetPrimitivesAspect ( anAsp );
456
457     for( it.Reset(); it.More(); it.Next() )
458     {
459       Standard_Integer aKey = it.Key();
460       if( aColIter2.Value().Contains( aKey ) )
461       {
462         if ( !aSource->GetGeom ( aKey, Standard_True, aCoords, NbNodes, aType ) )
463           continue;
464
465         if( IsExcludingOn() )
466           IDsToExclude.Add( aKey );
467
468         if ( aType == MeshVS_ET_Face && NbNodes > 0 )
469         {
470           // Preparing normal(s) to show reflections if requested
471           Handle(TColStd_HArray1OfReal) aNormals;
472           // OCC21720 Always passing normals to OpenGL to make materials work
473           // For OpenGL: "No normals" -> "No lighting" -> "no materials taken into account"
474           Standard_Boolean hasNormals = /*IsReflect &&*/
475             aSource->GetNormalsByElement( aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals );
476
477           aPolyArr->AddBound ( NbNodes );
478
479           for ( i=1; i<=NbNodes; i++ )
480           {
481             if ( IsReflect )
482             {
483               hasNormals ? aPolyArr->AddVertex ( aCoords(3 * i - 2), 
484                                                  aCoords(3 * i - 1), 
485                                                  aCoords(3 * i    ),
486                                                  aNormals->Value(3 * i - 2), 
487                                                  aNormals->Value(3 * i - 1), 
488                                                  aNormals->Value(3 * i    ) ) :
489                            aPolyArr->AddVertex ( aCoords(3 * i - 2), 
490                                                  aCoords(3 * i - 1), 
491                                                  aCoords(3 * i    ),
492                                                  0., 
493                                                  0., 
494                                                  1. );
495             }
496             else
497               aPolyArr->AddVertex ( aCoords(3*i-2), 
498                                     aCoords(3*i-1), 
499                                     aCoords(3*i  ) );
500           }
501         }
502       }
503     }
504     aGroup2->AddPrimitiveArray ( aPolyArr );
505   }
506 }
507
508 //================================================================
509 // Function : SetColors
510 // Purpose  :
511 //================================================================
512 void MeshVS_ElementalColorPrsBuilder::SetColors1 ( const MeshVS_DataMapOfIntegerColor& theColorMap )
513 {
514   myElemColorMap1 = theColorMap;
515 }
516
517 //================================================================
518 // Function : GetColors
519 // Purpose  :
520 //================================================================
521 const MeshVS_DataMapOfIntegerColor& MeshVS_ElementalColorPrsBuilder::GetColors1 () const
522 {
523   return myElemColorMap1;
524 }
525
526 //================================================================
527 // Function : HasColors1
528 // Purpose  :
529 //================================================================
530 Standard_Boolean MeshVS_ElementalColorPrsBuilder::HasColors1 () const
531 {
532   return ( myElemColorMap1.Extent() >0 );
533 }
534
535 //================================================================
536 // Function : GetColor1
537 // Purpose  :
538 //================================================================
539 Standard_Boolean MeshVS_ElementalColorPrsBuilder::GetColor1 ( const Standard_Integer ID,
540                                                               Quantity_Color& theColor ) const
541 {
542   Standard_Boolean aRes = myElemColorMap1.IsBound ( ID );
543   if ( aRes )
544     theColor = myElemColorMap1.Find ( ID );
545
546   return aRes;
547 }
548
549 //================================================================
550 // Function : SetColor1
551 // Purpose  :
552 //================================================================
553 void MeshVS_ElementalColorPrsBuilder::SetColor1 ( const Standard_Integer theID,
554                                                   const Quantity_Color& theCol )
555 {
556   Standard_Boolean aRes = myElemColorMap1.IsBound ( theID );
557   if ( aRes )
558     myElemColorMap1.ChangeFind ( theID ) = theCol;
559   else
560     myElemColorMap1.Bind ( theID, theCol );
561 }
562
563 //================================================================
564 // Function : SetColors2
565 // Purpose  :
566 //================================================================
567 void MeshVS_ElementalColorPrsBuilder::SetColors2 ( const MeshVS_DataMapOfIntegerTwoColors& theColorMap )
568 {
569   myElemColorMap2 = theColorMap;
570 }
571
572 //================================================================
573 // Function : GetColors2
574 // Purpose  :
575 //================================================================
576 const MeshVS_DataMapOfIntegerTwoColors& MeshVS_ElementalColorPrsBuilder::GetColors2 () const
577 {
578   return myElemColorMap2;
579 }
580
581 //================================================================
582 // Function : HasColors2
583 // Purpose  :
584 //================================================================
585 Standard_Boolean MeshVS_ElementalColorPrsBuilder::HasColors2 () const
586 {
587   return (myElemColorMap2.Extent()>0);
588 }
589
590 //================================================================
591 // Function : GetColor2
592 // Purpose  :
593 //================================================================
594 Standard_Boolean MeshVS_ElementalColorPrsBuilder::GetColor2 ( const Standard_Integer ID,
595                                                               MeshVS_TwoColors& theColor ) const
596 {
597   Standard_Boolean aRes = myElemColorMap2.IsBound ( ID );
598   if ( aRes )
599     theColor = myElemColorMap2.Find ( ID );
600
601   return aRes;
602 }
603
604 //================================================================
605 // Function : GetColor2
606 // Purpose  :
607 //================================================================
608 Standard_Boolean MeshVS_ElementalColorPrsBuilder::GetColor2 ( const Standard_Integer ID,
609                                                               Quantity_Color& theColor1,
610                                                               Quantity_Color& theColor2 ) const
611 {
612   MeshVS_TwoColors aTC;
613   Standard_Boolean aRes = GetColor2 ( ID, aTC );
614   if ( aRes)
615     ExtractColors ( aTC, theColor1, theColor2 );
616   return aRes;
617 }
618
619 //================================================================
620 // Function : SetColor2
621 // Purpose  :
622 //================================================================
623 void MeshVS_ElementalColorPrsBuilder::SetColor2 ( const Standard_Integer theID,
624                                                   const Quantity_Color& theCol1,
625                                                   const Quantity_Color& theCol2 )
626 {
627   SetColor2 ( theID, BindTwoColors ( theCol1, theCol2 ) );
628 }
629
630 //================================================================
631 // Function : SetColor2
632 // Purpose  :
633 //================================================================
634 void MeshVS_ElementalColorPrsBuilder::SetColor2 ( const Standard_Integer theID,
635                                                   const MeshVS_TwoColors& theCol )
636 {
637   Standard_Boolean aRes = myElemColorMap2.IsBound ( theID );
638   if ( aRes )
639     myElemColorMap2.ChangeFind ( theID ) = theCol;
640   else
641     myElemColorMap2.Bind ( theID, theCol );
642 }