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