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