Test for 0022778: Bug in BRepMesh
[occt.git] / src / MeshVS / MeshVS_VectorPrsBuilder.cxx
CommitLineData
b311480e 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
7fd59977 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//================================================================
58MeshVS_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 ),
67myIsSimplePrs( IsSimplePrs ),
68mySimpleWidthPrm( 2.5 ),
69mySimpleStartPrm( 0.85 ),
70mySimpleEndPrm( 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//================================================================
85const 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//================================================================
98void 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//================================================================
111Standard_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//================================================================
124Standard_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//================================================================
143void 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//================================================================
162void 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
196void 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
343 aVGroup->BeginPrimitives();
344 aVGroup->AddPrimitiveArray( aLineArray );
345 aVGroup->EndPrimitives();
346 if ( !myIsSimplePrs )
347 {
348 Graphic3d_MaterialAspect aMatAspect;
349 aMatAspect.SetAmbient( 1 );
350 aMatAspect.SetDiffuse( 0 );
351 aMatAspect.SetEmissive( 0 );
352 aMatAspect.SetShininess( 1 );
353 aMatAspect.SetSpecular( 0 );
354 Handle(Graphic3d_AspectFillArea3d) aFillAspect =
355 new Graphic3d_AspectFillArea3d (Aspect_IS_HOLLOW, aColor, aColor, Aspect_TOL_SOLID,
356 1., aMatAspect, aMatAspect );
357
358 aVGroup->SetPrimitivesAspect( aFillAspect );
359
360 aVGroup->BeginPrimitives();
361 aVGroup->AddPrimitiveArray( aTriangleArray );
362 aVGroup->EndPrimitives();
363 }
364 else
365 {
366 Handle(Graphic3d_AspectLine3d) anArrowLinAspect =
367 new Graphic3d_AspectLine3d ( aColor, Aspect_TOL_SOLID, mySimpleWidthPrm * 1.5 );
368
369 aVGroup->SetPrimitivesAspect( anArrowLinAspect );
370
371 aVGroup->BeginPrimitives();
372 aVGroup->AddPrimitiveArray( aArrowLineArray );
373 aVGroup->EndPrimitives();
374 }
375
376 if( !aCustomElements.IsEmpty() )
377 CustomBuild( Prs, aCustomElements, IDsToExclude, theDisplayMode );
378}
379
380//=======================================================================
381// name : DrawVector
382// Purpose : Fill arrays of primitives for drawing force
383//=======================================================================
384void MeshVS_VectorPrsBuilder::DrawVector ( const gp_Trsf& theTrsf,
385 const Standard_Real Length,
386 const Standard_Real MaxLength,
387 const TColgp_Array1OfPnt& ArrowPoints,
388 const Handle(Graphic3d_ArrayOfPrimitives)& Lines,
389 const Handle(Graphic3d_ArrayOfPrimitives)& ArrowLines,
390 const Handle(Graphic3d_ArrayOfPrimitives)& Triangles) const
391{
392 const int PntNum = 8;
393
394 const Standard_Real aMinLength = MaxLength * ( 1 - mySimpleStartPrm );
395 const Standard_Real aLocalLength = ( !myIsSimplePrs || Length > aMinLength ? Length : aMinLength );
396 // draw line
397 gp_Pnt aLinePnt[ 2 ] = { gp_Pnt( 0, 0, 0 ) , gp_Pnt( 0, 0, aLocalLength ) };
398 theTrsf.Transforms( aLinePnt[ 0 ].ChangeCoord() );
399 theTrsf.Transforms( aLinePnt[ 1 ].ChangeCoord() );
400
401 Lines->AddBound( 2 );
402 Lines->AddVertex( aLinePnt[ 0 ] );
403 Lines->AddVertex( aLinePnt[ 1 ] );
404
405 // draw arrow
406 if ( !myIsSimplePrs )
407 {
408 Standard_Integer l = ArrowPoints.Lower(),
409 u = ArrowPoints.Upper(),
410 i;
411 if ( u-l < PntNum-1 )
412 return;
413
414 TColgp_Array1OfPnt anArrowPnt( l, u );
415 for ( i = l; i < l+PntNum; i++ )
416 {
417 anArrowPnt( i ).ChangeCoord() = ArrowPoints ( i ).Coord() + gp_XYZ( 0, 0, aLocalLength );
418 theTrsf.Transforms( anArrowPnt( i ).ChangeCoord() );
419 }
420
421 Triangles->AddBound(8);
422 for ( i = 0; i < PntNum; i++ )
423 Triangles->AddVertex( anArrowPnt( l+i ) );
424 }
425 else
426 {
427 const Standard_Real aEndPos = aLocalLength - MaxLength * ( 1 - mySimpleEndPrm );
428 const Standard_Real aArrowLength = MaxLength * ( mySimpleEndPrm - mySimpleStartPrm );
429 gp_Pnt aArrowPnt[ 2 ] = { gp_Pnt( 0, 0, aEndPos - aArrowLength ),
430 gp_Pnt( 0, 0, aEndPos ) };
431 theTrsf.Transforms( aArrowPnt[ 0 ].ChangeCoord() );
432 theTrsf.Transforms( aArrowPnt[ 1 ].ChangeCoord() );
433
434 ArrowLines->AddBound( 2 );
435 ArrowLines->AddVertex( aArrowPnt[ 0 ] );
436 ArrowLines->AddVertex( aArrowPnt[ 1 ] );
437 }
438}
439
440//=======================================================================
441// name : calculateArrow
442// Purpose : Calculate points of arrow ( 8 pnts )
443//=======================================================================
444Standard_Real MeshVS_VectorPrsBuilder::calculateArrow ( TColgp_Array1OfPnt& Points,
445 const Standard_Real Length,
446 const Standard_Real ArrowPart )
447{
448 Standard_Real h = Length * ArrowPart;
449 Standard_Real w = h / 5.;
450
451 Standard_Integer f = Points.Lower();
452 Points( f ) = gp_Pnt( 0, 0, 0 );
453 Points( f+1 ) = gp_Pnt( 0, -w, -h );
454 Points( f+2 ) = gp_Pnt( w * 0.866, -w * 0.5, -h );
455 Points( f+3 ) = gp_Pnt( w * 0.866, w * 0.5, -h );
456 Points( f+4 ) = gp_Pnt( 0 , w, -h );
457 Points( f+5 ) = gp_Pnt( -w * 0.866, w * 0.5, -h );
458 Points( f+6 ) = gp_Pnt( -w * 0.866, -w * 0.5, -h );
459 Points( f+7 ) = gp_Pnt( 0, -w, -h );
460
461 return h;
462}
463
464//=======================================================================
465// name : SetSimplePrsMode
466// Purpose :
467//=======================================================================
468void MeshVS_VectorPrsBuilder::SetSimplePrsMode( const Standard_Boolean IsSimpleArrow )
469{
470 myIsSimplePrs = IsSimpleArrow;
471}
472
473//=======================================================================
474// name : SetSimplePrsParams
475// Purpose :
476//=======================================================================
477void MeshVS_VectorPrsBuilder::SetSimplePrsParams( const Standard_Real theLineWidthParam,
478 const Standard_Real theStartParam,
479 const Standard_Real theEndParam )
480{
481 mySimpleWidthPrm = theLineWidthParam;
482 mySimpleStartPrm = theStartParam;
483 mySimpleEndPrm = theEndParam;
484}