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