0022627: Change OCCT memory management defaults
[occt.git] / src / MeshVS / MeshVS_VectorPrsBuilder.cxx
1 // File:        MeshVS_VectorPrsBuilder.cxx
2 // Created:     Fri Sep 19 2003
3 // Author:      Alexander SOLOVYOV
4 // Copyright:    Open CASCADE 2003
5
6 #include <MeshVS_VectorPrsBuilder.ixx>
7
8 #include <MeshVS_DisplayModeFlags.hxx>
9
10 #include <Graphic3d_ArrayOfPolylines.hxx>
11 #include <Graphic3d_ArrayOfPolygons.hxx>
12 #include <Graphic3d_ArrayOfTriangleFans.hxx>
13 #include <Graphic3d_MaterialAspect.hxx>
14 #include <Graphic3d_AspectLine3d.hxx>
15 #include <Graphic3d_AspectFillArea3d.hxx>
16 #include <Graphic3d_Group.hxx>
17
18 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
19 #include <TColStd_Array1OfReal.hxx>
20 #include <TColgp_Array1OfPnt.hxx>
21 #include <TColStd_HPackedMapOfInteger.hxx>
22
23 #include <Precision.hxx>
24
25 #include <gp_Ax3.hxx>
26
27 #include <Prs3d_Root.hxx>
28
29 #include <Aspect_TypeOfLine.hxx>
30
31 #include <MeshVS_DataSource.hxx>
32 #include <MeshVS_Drawer.hxx>
33 #include <MeshVS_DrawerAttribute.hxx>
34 #include <MeshVS_Mesh.hxx>
35 #include <MeshVS_EntityType.hxx>
36 #include <MeshVS_DataMapIteratorOfDataMapOfIntegerVector.hxx>
37 #include <MeshVS_Buffer.hxx>
38
39 //================================================================
40 // Function : Constructor MeshVS_VectorPrsBuilder
41 // Purpose  :
42 //================================================================
43 MeshVS_VectorPrsBuilder::MeshVS_VectorPrsBuilder ( const Handle(MeshVS_Mesh)& Parent,
44                                                    const Standard_Real MaxLength,
45                                                    const Quantity_Color& VectorColor,
46                                                    const MeshVS_DisplayModeFlags& Flags,
47                                                    const Handle (MeshVS_DataSource)& DS,
48                                                    const Standard_Integer Id,
49                                                    const MeshVS_BuilderPriority& Priority,
50                                                    const Standard_Boolean IsSimplePrs )
51 : MeshVS_PrsBuilder ( Parent, Flags, DS, Id, Priority ),
52 myIsSimplePrs( IsSimplePrs ),
53 mySimpleWidthPrm( 2.5 ),
54 mySimpleStartPrm( 0.85 ),
55 mySimpleEndPrm( 0.95 )
56 {
57   Handle ( MeshVS_Drawer ) aDrawer = GetDrawer();
58   if ( !aDrawer.IsNull() )
59   {
60     aDrawer->SetDouble ( MeshVS_DA_VectorMaxLength, MaxLength );
61     aDrawer->SetColor  ( MeshVS_DA_VectorColor, VectorColor );
62     aDrawer->SetDouble ( MeshVS_DA_VectorArrowPart, 0.1 );
63   }
64 }
65
66 //================================================================
67 // Function : GetVectors
68 // Purpose  :
69 //================================================================
70 const MeshVS_DataMapOfIntegerVector& MeshVS_VectorPrsBuilder::GetVectors
71   ( const Standard_Boolean IsElements ) const
72 {
73   if ( IsElements )
74     return myElemVectorMap;
75   else
76     return myNodeVectorMap;
77 }
78
79 //================================================================
80 // Function : SetVectors
81 // Purpose  :
82 //================================================================
83 void MeshVS_VectorPrsBuilder::SetVectors ( const Standard_Boolean IsElements,
84                                            const MeshVS_DataMapOfIntegerVector& theMap )
85 {
86   if ( IsElements )
87     myElemVectorMap = theMap;
88   else
89     myNodeVectorMap = theMap;
90 }
91
92 //================================================================
93 // Function : HasVectors
94 // Purpose  :
95 //================================================================
96 Standard_Boolean MeshVS_VectorPrsBuilder::HasVectors ( const Standard_Boolean IsElement ) const
97 {
98   Standard_Boolean aRes = (myNodeVectorMap.Extent()>0);
99   if ( IsElement )
100     aRes = (myElemVectorMap.Extent()>0);
101   return aRes;
102
103 }
104
105 //================================================================
106 // Function : GetVector
107 // Purpose  :
108 //================================================================
109 Standard_Boolean MeshVS_VectorPrsBuilder::GetVector ( const Standard_Boolean IsElement,
110                                                       const Standard_Integer ID,
111                                                       gp_Vec& Vect ) const
112 {
113   const MeshVS_DataMapOfIntegerVector* aMap = &myNodeVectorMap;
114   if ( IsElement )
115     aMap = &myElemVectorMap;
116
117   Standard_Boolean aRes = aMap->IsBound ( ID );
118   if ( aRes )
119     Vect = aMap->Find ( ID );
120
121   return aRes;
122 }
123
124 //================================================================
125 // Function : SetVector
126 // Purpose  :
127 //================================================================
128 void MeshVS_VectorPrsBuilder::SetVector ( const Standard_Boolean IsElement,
129                                           const Standard_Integer ID,
130                                           const gp_Vec& Vect )
131 {
132   MeshVS_DataMapOfIntegerVector* aMap = &myNodeVectorMap;
133   if ( IsElement )
134     aMap = &myElemVectorMap;
135
136   Standard_Boolean aRes = aMap->IsBound ( ID );
137   if ( aRes )
138     aMap->ChangeFind ( ID ) = Vect;
139   else
140     aMap->Bind ( ID, Vect );
141 }
142
143 //================================================================
144 // Function : GetMaxVectorValue
145 // Purpose  :
146 //================================================================
147 void MeshVS_VectorPrsBuilder::GetMinMaxVectorValue ( const Standard_Boolean IsElement,
148                                                      Standard_Real& MinValue,
149                                                      Standard_Real& MaxValue ) const
150 {
151   const MeshVS_DataMapOfIntegerVector* aMap = &myNodeVectorMap;
152   if ( IsElement )
153     aMap = &myElemVectorMap;
154
155   MeshVS_DataMapIteratorOfDataMapOfIntegerVector anIt ( *aMap );
156   if ( anIt.More() )
157     MinValue = MaxValue = anIt.Value().Magnitude();
158
159   Standard_Real aCurValue;
160
161   for ( ; anIt.More(); anIt.Next() )
162   {
163     aCurValue = anIt.Value().Magnitude();
164     if ( MinValue > aCurValue )
165       MinValue = aCurValue;
166     if ( MaxValue < aCurValue )
167       MaxValue = aCurValue;
168   }
169 }
170
171 //================================================================
172 // Function : Build
173 // Purpose  :
174 //================================================================
175
176 #define NB_VERTICES 2
177 #define NB_BOUNDS 1
178 #define NB_TRIANGLES 6
179 #define NB_FANS 1
180
181 void MeshVS_VectorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
182                                       const TColStd_PackedMapOfInteger& IDs,
183                                       TColStd_PackedMapOfInteger& IDsToExclude,
184                                       const Standard_Boolean IsElement,
185                                       const Standard_Integer theDisplayMode ) const
186 {
187   Handle ( MeshVS_Drawer ) aDrawer = GetDrawer();
188   Handle (MeshVS_DataSource) aSource = GetDataSource();
189   if ( aSource.IsNull() || aDrawer.IsNull() || !HasVectors( IsElement ) ||
190        ( theDisplayMode & GetFlags() )==0 )
191     return;
192
193   Standard_Integer aMaxFaceNodes;
194   Standard_Real aMaxLen, anArrowPart = 0.1;
195
196   if ( !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, aMaxFaceNodes ) ||
197        aMaxFaceNodes <= 0 ||
198        !aDrawer->GetDouble  ( MeshVS_DA_VectorMaxLength, aMaxLen )    ||
199        aMaxLen <= 0       ||
200        !aDrawer->GetDouble ( MeshVS_DA_VectorArrowPart, anArrowPart ) ||
201        anArrowPart <= 0
202      )
203     return;
204
205   MeshVS_Buffer aCoordsBuf (3*aMaxFaceNodes*sizeof(Standard_Real));
206   TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3*aMaxFaceNodes);
207   Standard_Integer NbNodes;
208   MeshVS_EntityType aType;
209
210   // DECLARE ARRAYS OF PRIMITIVES
211   const MeshVS_DataMapOfIntegerVector& aMap = GetVectors ( IsElement );
212   Standard_Integer aNbVectors = aMap.Extent();
213
214   if ( aNbVectors <= 0 )
215     return;
216
217   // polylines
218   Standard_Integer aNbVertices         = aNbVectors  * NB_VERTICES;
219   Standard_Integer aNbBounds           = aNbVectors  * NB_BOUNDS;
220
221   // fans
222   Standard_Integer aNbTriangleVertices = aNbVectors  * (NB_TRIANGLES + 2);
223   Standard_Integer aNbFans             = aNbVectors  * NB_TRIANGLES;
224
225   Handle(Graphic3d_ArrayOfPrimitives) aLineArray =
226     new Graphic3d_ArrayOfPolylines(aNbVertices, aNbBounds);
227   Handle(Graphic3d_ArrayOfPrimitives) aArrowLineArray =
228     new Graphic3d_ArrayOfPolylines(aNbVertices, aNbBounds);
229
230   Handle(Graphic3d_ArrayOfTriangleFans) aTriangleArray =
231     new Graphic3d_ArrayOfTriangleFans(aNbTriangleVertices, aNbFans);
232
233   TColgp_Array1OfPnt anArrowPnt(1,8);
234   Standard_Real k, b, aMaxValue, aMinValue, aValue, X, Y, Z;
235   
236   Standard_Real aMinLength = calculateArrow( anArrowPnt, aMaxLen, anArrowPart );
237   gp_Vec aVec; gp_Trsf aTrsf;
238
239   GetMinMaxVectorValue ( IsElement, aMinValue, aMaxValue );
240
241   if ( aMaxValue - aMinValue > Precision::Confusion() )
242   {
243     k = 0.8 * aMaxLen / ( aMaxValue - aMinValue );
244     b = aMaxLen - k * aMaxValue;
245   }
246   else
247   {
248     k = 0;
249     b = aMaxLen;
250   }
251
252   TColStd_PackedMapOfInteger aCustomElements;
253
254   // subtract the hidden elements and ids to exclude (to minimise allocated memory)
255   TColStd_PackedMapOfInteger anIDs;
256   anIDs.Assign( IDs );
257   if ( IsElement )
258   {
259     Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
260     if ( !aHiddenElems.IsNull() )
261       anIDs.Subtract( aHiddenElems->Map() );
262   }
263   anIDs.Subtract( IDsToExclude );
264
265   TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
266   for( ; it.More(); it.Next() )
267   {
268     Standard_Integer aKey = it.Key();
269       if( GetVector ( IsElement, aKey, aVec ) )
270       {
271         aValue = aVec.Magnitude();
272
273         if ( Abs( aValue ) < Precision::Confusion() )
274           continue;
275
276         if( aSource->GetGeom ( aKey, IsElement, aCoords, NbNodes, aType ) )
277         {
278           if( aType == MeshVS_ET_Node )
279           {
280             X = aCoords(1);
281             Y = aCoords(2);
282             Z = aCoords(3);
283           }
284           else if( aType == MeshVS_ET_Link || 
285                    aType == MeshVS_ET_Face || 
286                    aType == MeshVS_ET_Volume )
287           {
288             if( IsElement && IsExcludingOn() )
289               IDsToExclude.Add( aKey );
290             X = Y = Z = 0;
291             for ( Standard_Integer i=1; i<=NbNodes; i++ )
292             {
293               X += aCoords (3*i-2);
294               Y += aCoords (3*i-1);
295               Z += aCoords (3*i);
296             }
297             X /= Standard_Real ( NbNodes );
298             Y /= Standard_Real ( NbNodes );
299             Z /= Standard_Real ( NbNodes );
300           }
301           else
302           {
303             aCustomElements.Add( aKey );
304             continue;
305           }
306
307           aTrsf.SetDisplacement ( gp_Ax3 ( gp_Pnt ( 0, 0, 0 ), gp_Dir(0, 0, 1)),
308                                   gp_Ax3 ( gp_Pnt ( X, Y, Z ), aVec ) );
309
310           DrawVector ( aTrsf, Max( k * fabs( aValue ) + b, aMinLength), aMaxLen,
311                        anArrowPnt, aLineArray, aArrowLineArray, aTriangleArray );
312         }
313       }
314   }
315
316   Prs3d_Root::NewGroup ( Prs );
317   Handle (Graphic3d_Group) aVGroup = Prs3d_Root::CurrentGroup ( Prs );
318
319   Quantity_Color aColor;
320   aDrawer->GetColor ( MeshVS_DA_VectorColor, aColor );
321
322   // Add primitive arrays to group
323   Handle(Graphic3d_AspectLine3d) aLinAspect =
324     new Graphic3d_AspectLine3d ( aColor, Aspect_TOL_SOLID, 1.5 );
325
326   aVGroup->SetPrimitivesAspect( aLinAspect );
327
328   aVGroup->BeginPrimitives();
329   aVGroup->AddPrimitiveArray( aLineArray );
330   aVGroup->EndPrimitives();
331   if ( !myIsSimplePrs )
332   {
333     Graphic3d_MaterialAspect aMatAspect;
334     aMatAspect.SetAmbient( 1 );
335     aMatAspect.SetDiffuse( 0 );
336     aMatAspect.SetEmissive( 0 );
337     aMatAspect.SetShininess( 1 );
338     aMatAspect.SetSpecular( 0 );
339     Handle(Graphic3d_AspectFillArea3d) aFillAspect =
340       new Graphic3d_AspectFillArea3d (Aspect_IS_HOLLOW, aColor, aColor, Aspect_TOL_SOLID,
341                                       1., aMatAspect, aMatAspect );
342
343     aVGroup->SetPrimitivesAspect( aFillAspect );
344
345     aVGroup->BeginPrimitives();
346     aVGroup->AddPrimitiveArray( aTriangleArray );
347     aVGroup->EndPrimitives();
348   }
349   else
350   {
351     Handle(Graphic3d_AspectLine3d) anArrowLinAspect =
352       new Graphic3d_AspectLine3d ( aColor, Aspect_TOL_SOLID, mySimpleWidthPrm * 1.5 );
353
354     aVGroup->SetPrimitivesAspect( anArrowLinAspect );
355     
356     aVGroup->BeginPrimitives();
357     aVGroup->AddPrimitiveArray( aArrowLineArray );
358     aVGroup->EndPrimitives();
359   }
360
361   if( !aCustomElements.IsEmpty() )
362     CustomBuild( Prs, aCustomElements, IDsToExclude, theDisplayMode );
363 }
364
365 //=======================================================================
366 // name    : DrawVector
367 // Purpose : Fill arrays of primitives for drawing force
368 //=======================================================================
369 void MeshVS_VectorPrsBuilder::DrawVector ( const gp_Trsf& theTrsf,
370                                            const Standard_Real Length,
371                                            const Standard_Real MaxLength,
372                                            const TColgp_Array1OfPnt& ArrowPoints,
373                                            const Handle(Graphic3d_ArrayOfPrimitives)& Lines,
374                                            const Handle(Graphic3d_ArrayOfPrimitives)& ArrowLines,
375                                            const Handle(Graphic3d_ArrayOfPrimitives)& Triangles) const
376 {
377   const int PntNum = 8;
378
379   const Standard_Real aMinLength = MaxLength * ( 1 - mySimpleStartPrm );
380   const Standard_Real aLocalLength = ( !myIsSimplePrs || Length > aMinLength ? Length : aMinLength );
381   // draw line
382   gp_Pnt aLinePnt[ 2 ] = { gp_Pnt( 0, 0, 0 ) , gp_Pnt( 0, 0, aLocalLength ) };
383   theTrsf.Transforms( aLinePnt[ 0 ].ChangeCoord() );
384   theTrsf.Transforms( aLinePnt[ 1 ].ChangeCoord() );
385
386   Lines->AddBound( 2 );
387   Lines->AddVertex( aLinePnt[ 0 ] );
388   Lines->AddVertex( aLinePnt[ 1 ] );
389
390   // draw arrow
391   if ( !myIsSimplePrs )
392   {
393     Standard_Integer l = ArrowPoints.Lower(),
394                      u = ArrowPoints.Upper(),
395                      i;
396     if ( u-l < PntNum-1 )
397       return;
398
399     TColgp_Array1OfPnt anArrowPnt( l, u );
400     for ( i = l; i < l+PntNum; i++ )
401     {
402       anArrowPnt( i ).ChangeCoord() = ArrowPoints ( i ).Coord() + gp_XYZ( 0, 0, aLocalLength );
403       theTrsf.Transforms( anArrowPnt( i ).ChangeCoord() );
404     }
405
406     Triangles->AddBound(8);
407     for ( i = 0; i < PntNum; i++ )
408       Triangles->AddVertex( anArrowPnt( l+i ) );
409   }
410   else
411   {
412     const Standard_Real aEndPos = aLocalLength - MaxLength * ( 1 - mySimpleEndPrm );
413     const Standard_Real aArrowLength = MaxLength * ( mySimpleEndPrm - mySimpleStartPrm );
414     gp_Pnt aArrowPnt[ 2 ] = { gp_Pnt( 0, 0, aEndPos - aArrowLength ),
415                               gp_Pnt( 0, 0, aEndPos ) };
416     theTrsf.Transforms( aArrowPnt[ 0 ].ChangeCoord() );
417     theTrsf.Transforms( aArrowPnt[ 1 ].ChangeCoord() );
418
419     ArrowLines->AddBound( 2 );
420     ArrowLines->AddVertex( aArrowPnt[ 0 ] );
421     ArrowLines->AddVertex( aArrowPnt[ 1 ] );
422   }
423 }
424
425 //=======================================================================
426 // name    : calculateArrow
427 // Purpose : Calculate points of arrow ( 8 pnts )
428 //=======================================================================
429 Standard_Real MeshVS_VectorPrsBuilder::calculateArrow ( TColgp_Array1OfPnt& Points,
430                                                         const Standard_Real Length,
431                                                         const Standard_Real ArrowPart )
432 {
433   Standard_Real h = Length * ArrowPart;
434   Standard_Real w = h / 5.;
435
436   Standard_Integer f = Points.Lower();
437   Points( f   ) = gp_Pnt( 0,  0, 0 );
438   Points( f+1 ) = gp_Pnt( 0, -w, -h );
439   Points( f+2 ) = gp_Pnt( w * 0.866, -w * 0.5, -h );
440   Points( f+3 ) = gp_Pnt( w * 0.866,  w * 0.5, -h );
441   Points( f+4 ) = gp_Pnt( 0 , w, -h );
442   Points( f+5 ) = gp_Pnt( -w * 0.866,  w * 0.5, -h );
443   Points( f+6 ) = gp_Pnt( -w * 0.866, -w * 0.5, -h );
444   Points( f+7 ) = gp_Pnt( 0, -w, -h );
445
446   return h;
447 }
448
449 //=======================================================================
450 // name    : SetSimplePrsMode
451 // Purpose : 
452 //=======================================================================
453 void MeshVS_VectorPrsBuilder::SetSimplePrsMode( const Standard_Boolean IsSimpleArrow )
454 {
455   myIsSimplePrs = IsSimpleArrow;
456 }
457
458 //=======================================================================
459 // name    : SetSimplePrsParams
460 // Purpose : 
461 //=======================================================================
462 void MeshVS_VectorPrsBuilder::SetSimplePrsParams( const Standard_Real theLineWidthParam,
463                                                   const Standard_Real theStartParam,
464                                                   const Standard_Real theEndParam )
465 {
466   mySimpleWidthPrm = theLineWidthParam;
467   mySimpleStartPrm = theStartParam;
468   mySimpleEndPrm   = theEndParam;
469 }