c25c62082d7ac6927009dc0323b36a1a0820b988
[occt.git] / src / Graphic3d / Graphic3d_ArrayOfPrimitives.cxx
1 // Created on: 2000-06-16
2 // Copyright (c) 2000-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and / or modify it
7 // under the terms of the GNU Lesser General Public version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #define TRACE 0
16
17 #include <Graphic3d_ArrayOfPrimitives.ixx>
18 #include <Standard.hxx>
19 #include <TCollection_AsciiString.hxx>
20 #include <OSD_Environment.hxx>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 Graphic3d_ArrayOfPrimitives :: Graphic3d_ArrayOfPrimitives (
26                         const Graphic3d_TypeOfPrimitiveArray aType,
27                         const Standard_Integer maxVertexs,
28                         const Standard_Integer maxBounds,
29                         const Standard_Integer maxEdges,
30                         const Standard_Boolean hasVNormals,
31                         const Standard_Boolean hasVColors,
32                         const Standard_Boolean hasFColors,
33                         const Standard_Boolean hasVTexels,
34                         const Standard_Boolean hasEdgeInfos )
35 : myMaxBounds(0),myMaxVertexs(0),myMaxEdges(0)
36 {
37   const Standard_Integer size = sizeof(CALL_DEF_PARRAY);
38   Standard_Integer format = MVERTICE;
39   if( hasVNormals ) format |= MVNORMAL;
40   if( hasVColors ) format |= MVCOLOR;
41   if( hasVTexels ) format |= MVTEXEL;
42     
43   myPrimitiveArray = (Graphic3d_PrimitiveArray) Standard::Allocate(size); 
44   memset ( myPrimitiveArray, 0, size );
45
46   if( maxVertexs > 0){
47     myPrimitiveArray->vertices = (TEL_POINT*) Standard::Allocate(maxVertexs *sizeof(TEL_POINT));
48     memset ( myPrimitiveArray->vertices, 0, maxVertexs *sizeof(TEL_POINT));
49   }
50
51   if( hasVNormals ){
52     myPrimitiveArray->vnormals = (TEL_POINT*) Standard::Allocate(sizeof(TEL_POINT) * maxVertexs);
53     memset ( myPrimitiveArray->vnormals, 0, sizeof(TEL_POINT) * maxVertexs);
54   }
55
56   if( hasVColors ){
57     myPrimitiveArray->vcolours = (Tint*) Standard::Allocate(maxVertexs *sizeof(Tint));
58     memset ( myPrimitiveArray->vcolours, 0, sizeof(Tint) * maxVertexs);
59   }
60
61   if( hasVTexels ){
62     myPrimitiveArray->vtexels = (TEL_TEXTURE_COORD*) Standard::Allocate(maxVertexs *sizeof(TEL_TEXTURE_COORD));
63     memset ( myPrimitiveArray->vtexels, 0, sizeof(TEL_TEXTURE_COORD) * maxVertexs);
64   }
65
66   if( hasFColors && (maxBounds > 0) ){
67     myPrimitiveArray->fcolours = (TEL_COLOUR*) Standard::Allocate(maxBounds *sizeof(TEL_COLOUR));
68     memset ( myPrimitiveArray->fcolours, 0, sizeof(TEL_COLOUR) * maxBounds);
69   } 
70
71   if( maxBounds > 0 ){
72     myPrimitiveArray->bounds = (Tint*) Standard::Allocate(maxBounds *sizeof(Tint));
73     memset ( myPrimitiveArray->bounds, 0, maxBounds *sizeof(Tint));
74   }
75
76   if( maxEdges > 0 ){
77     myPrimitiveArray->edges = (Tint*) Standard::Allocate(maxEdges *sizeof(Tint));
78     memset ( myPrimitiveArray->edges, 0,  maxEdges *sizeof(Tint));
79   }
80
81   if( hasEdgeInfos && (maxEdges > 0) ){
82     myPrimitiveArray->edge_vis = (Tchar*)Standard::Allocate(maxEdges *sizeof(Tchar));
83     memset ( myPrimitiveArray->edge_vis, 0, maxEdges *sizeof(Tchar));
84   }
85
86   myPrimitiveArray->keys = NULL;
87   myMaxVertexs = maxVertexs;
88   myMaxBounds = maxBounds;
89   myMaxEdges = maxEdges;
90   myPrimitiveArray->type          = (TelPrimitivesArrayType) aType;
91   myPrimitiveArray->format        = format;
92   myPrimitiveArray->num_bounds    = 0;
93   myPrimitiveArray->num_vertexs   = 0;
94   myPrimitiveArray->num_edges     = 0;
95 }
96
97 void Graphic3d_ArrayOfPrimitives::Destroy ()
98 {
99   if( myPrimitiveArray ) {
100     if( myPrimitiveArray->vertices ){
101       Standard::Free( (Standard_Address&)myPrimitiveArray->vertices );
102       myPrimitiveArray->vertices = 0;
103     }
104
105     if( myPrimitiveArray->vnormals ){
106       Standard::Free( (Standard_Address&)myPrimitiveArray->vnormals );
107       myPrimitiveArray->vnormals = 0;
108     }
109
110     if( myPrimitiveArray->vcolours ){
111       Standard::Free( (Standard_Address&)myPrimitiveArray->vcolours );
112       myPrimitiveArray->vcolours = 0;
113     }
114
115     if( myPrimitiveArray->vtexels ){
116       Standard::Free( (Standard_Address&)myPrimitiveArray->vtexels );
117       myPrimitiveArray->vtexels = 0;
118     }
119
120     if( myPrimitiveArray->fcolours ){
121       Standard::Free( (Standard_Address&)myPrimitiveArray->fcolours );
122       myPrimitiveArray->fcolours = 0;
123     } 
124
125     if( myPrimitiveArray->bounds ){
126       Standard::Free( (Standard_Address&)myPrimitiveArray->bounds );
127       myPrimitiveArray->bounds = 0;
128     }
129
130     if( myPrimitiveArray->edges ){
131       Standard::Free( (Standard_Address&)myPrimitiveArray->edges );
132       myPrimitiveArray->edges = 0;
133     }
134
135     if( myPrimitiveArray->edge_vis ){
136       Standard::Free( (Standard_Address&)myPrimitiveArray->edge_vis );
137       myPrimitiveArray->edge_vis = 0;
138     }
139
140     Standard::Free( (Standard_Address&)myPrimitiveArray );
141 #if TRACE > 0
142     cout << " Graphic3d_ArrayOfPrimitives::Destroy()" << endl;
143 #endif
144   }
145 }
146
147 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Z)
148 {
149   if( !myPrimitiveArray ) return 0;
150   const Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
151   SetVertice(index,X,Y,Z);
152   return index;
153 }
154
155 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const gp_Pnt& aVertice, const Quantity_Color& aColor)
156 {
157   const Standard_Integer index = AddVertex(aVertice);
158   Standard_Real r,g,b;
159   aColor.Values(r,g,b,Quantity_TOC_RGB);
160   SetVertexColor(index,r,g,b);
161   return index;
162 }
163
164 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const gp_Pnt& aVertice, const Standard_Integer aColor)
165 {
166   const Standard_Integer index = AddVertex(aVertice);
167   SetVertexColor(index,aColor);
168   return index;
169 }
170
171 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Z,
172                                                         const Standard_ShortReal NX, const Standard_ShortReal NY, const Standard_ShortReal NZ)
173 {
174   if( !myPrimitiveArray ) return 0;
175   const Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
176   SetVertice(index,X,Y,Z);
177   SetVertexNormal(index,NX,NY,NZ);
178   return index;
179 }
180
181 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const gp_Pnt& aVertice,
182                                                         const gp_Dir& aNormal,
183                                                         const Quantity_Color& aColor)
184 {
185   const Standard_Integer index = AddVertex(aVertice,aNormal);
186   Standard_Real r,g,b;
187   aColor.Values(r,g,b,Quantity_TOC_RGB);
188   SetVertexColor(index,r,g,b);
189   return index;
190 }
191
192 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const gp_Pnt& aVertice,
193                                                         const gp_Dir& aNormal,
194                                                         const Standard_Integer aColor)
195 {
196   const Standard_Integer index = AddVertex(aVertice,aNormal);
197   SetVertexColor(index,aColor);
198   return index;
199 }
200
201 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
202         const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Z,
203         const Standard_ShortReal TX, const Standard_ShortReal TY)
204 {
205   if( !myPrimitiveArray ) return 0;
206   const Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
207   SetVertice(index,X,Y,Z);
208   SetVertexTexel(index,TX,TY);
209   return index;
210 }
211
212 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
213         const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Z,
214         const Standard_ShortReal NX, const Standard_ShortReal NY, const Standard_ShortReal NZ,
215         const Standard_ShortReal TX, const Standard_ShortReal TY)
216 {
217   if( !myPrimitiveArray ) return 0;
218   const Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
219   SetVertice(index,X,Y,Z);
220   SetVertexNormal(index,NX,NY,NZ);
221   SetVertexTexel(index,TX,TY);
222   return index;
223 }
224
225 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound( const Standard_Integer edgeNumber)
226 {
227   Standard_Integer index = 0;
228   if( myPrimitiveArray && myPrimitiveArray->bounds ) {
229     index = myPrimitiveArray->num_bounds;
230     if( index < myMaxBounds ) {
231       myPrimitiveArray->bounds[index] = edgeNumber;
232       myPrimitiveArray->num_bounds = ++index;
233     } else {
234       Standard_OutOfRange::Raise(" TOO many BOUNDS");
235     }
236   }
237
238   return index;
239 }
240
241 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound( const Standard_Integer edgeNumber,
242                                                         const Quantity_Color& aFColor)
243 {
244   Standard_Real r,g,b;
245   aFColor.Values(r,g,b,Quantity_TOC_RGB);
246   return AddBound(edgeNumber,r,g,b);
247 }
248
249 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound( const Standard_Integer edgeNumber,
250                                                         const Standard_Real R, 
251                                                         const Standard_Real G,
252                                                         const Standard_Real B)
253 {
254   if( !myPrimitiveArray ) return 0;
255   Standard_Integer index = myPrimitiveArray->num_bounds;
256   if( index >= myMaxBounds ) {
257     Standard_OutOfRange::Raise(" TOO many BOUND");
258   }
259   myPrimitiveArray->bounds[index] = edgeNumber;
260   myPrimitiveArray->num_bounds = ++index;
261   SetBoundColor(index,R,G,B);
262   return index;
263 }
264
265 Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge(const Standard_Integer vertexIndex,
266                                                       const Standard_Boolean isVisible)
267 {
268   if( !myPrimitiveArray ) return 0;
269
270   Standard_Integer index = myPrimitiveArray->num_edges;
271   if( index >= myMaxEdges ) {
272     Standard_OutOfRange::Raise(" TOO many EDGE");
273   }
274   Standard_Integer vindex = vertexIndex-1;
275   if( vertexIndex > 0 && vindex < myMaxVertexs ) {
276     myPrimitiveArray->edges[index] = vindex;
277     if( myPrimitiveArray->edge_vis ) {
278       myPrimitiveArray->edge_vis[index] = (Tchar) (isVisible ? 1 : 0);
279     }
280     myPrimitiveArray->num_edges = ++index;
281   } else {
282     Standard_OutOfRange::Raise(" BAD EDGE vertex index");
283   }
284
285   return index;
286 }
287
288 Standard_Boolean Graphic3d_ArrayOfPrimitives::Orientate(const gp_Dir& aNormal)
289 {
290   return Orientate(1,Max(VertexNumber(),EdgeNumber()),aNormal);
291 }
292
293 Standard_Boolean Graphic3d_ArrayOfPrimitives::Orientate(const Standard_Integer aVertexIndex,
294                                                         const Standard_Integer aVertexNumber,
295                                                         const gp_Dir& aNormal)
296 {
297   Standard_Boolean somethingHasChange = Standard_False;
298   if( myPrimitiveArray && (myPrimitiveArray->num_vertexs > 2) ) {
299     Standard_Integer i,j,k=aVertexNumber,n=aVertexIndex-1;
300     Standard_ShortReal x,y,z;
301     if( myPrimitiveArray->edges ) {
302       if( n >= 0 && (n+k) <= myPrimitiveArray->num_edges ) {
303         Standard_Integer i1 = myPrimitiveArray->edges[n];
304         Standard_Integer i2 = myPrimitiveArray->edges[n+1];
305         Standard_Integer i3 = myPrimitiveArray->edges[n+2];
306         gp_Pnt p1(myPrimitiveArray->vertices[i1].xyz[0],
307                   myPrimitiveArray->vertices[i1].xyz[1],
308                   myPrimitiveArray->vertices[i1].xyz[2]);
309         gp_Pnt p2(myPrimitiveArray->vertices[i2].xyz[0],
310                   myPrimitiveArray->vertices[i2].xyz[1],
311                   myPrimitiveArray->vertices[i2].xyz[2]);
312         gp_Pnt p3(myPrimitiveArray->vertices[i3].xyz[0],
313                   myPrimitiveArray->vertices[i3].xyz[1],
314                   myPrimitiveArray->vertices[i3].xyz[2]);
315         gp_Vec v21(p1,p2),v31(p1,p3),fn = v21.Crossed(v31);
316         if( aNormal.IsOpposite(fn, M_PI / 4.) ) {
317           Standard_Integer e; char v;
318           for( i=0,j=k-1 ; i<k/2 ; i++,j-- ) {
319             e = myPrimitiveArray->edges[n+i];
320             myPrimitiveArray->edges[n+i] = myPrimitiveArray->edges[n+j];
321             myPrimitiveArray->edges[n+j] = e;
322             if( myPrimitiveArray->edge_vis ) {
323               v = myPrimitiveArray->edge_vis[n+i];
324               myPrimitiveArray->edge_vis[n+i] = myPrimitiveArray->edge_vis[n+j];
325               myPrimitiveArray->edge_vis[n+j] = v;
326             }
327             if( myPrimitiveArray->vnormals ) {
328               e = myPrimitiveArray->edges[n+i];
329               x = myPrimitiveArray->vnormals[e].xyz[0];
330               y = myPrimitiveArray->vnormals[e].xyz[1];
331               z = myPrimitiveArray->vnormals[e].xyz[2];
332               gp_Vec vn(x,y,z);
333               if( aNormal.IsOpposite(vn, M_PI / 4.) ) {
334                 myPrimitiveArray->vnormals[e].xyz[0] = -x;
335                 myPrimitiveArray->vnormals[e].xyz[1] = -y;
336                 myPrimitiveArray->vnormals[e].xyz[2] = -z;
337               }
338             }
339           }
340           somethingHasChange = Standard_True;
341         }
342       } else {
343         Standard_OutOfRange::Raise(" BAD EDGE index or number");
344       }
345       return somethingHasChange;
346     } 
347
348     if( n >= 0 && (n+k) <= myPrimitiveArray->num_vertexs ) {
349       gp_Pnt p1(myPrimitiveArray->vertices[n].xyz[0],
350                   myPrimitiveArray->vertices[n].xyz[1],
351                   myPrimitiveArray->vertices[n].xyz[2]);
352       gp_Pnt p2(myPrimitiveArray->vertices[n+1].xyz[0],
353                   myPrimitiveArray->vertices[n+1].xyz[1],
354                   myPrimitiveArray->vertices[n+1].xyz[2]);
355       gp_Pnt p3(myPrimitiveArray->vertices[n+2].xyz[0],
356                   myPrimitiveArray->vertices[n+2].xyz[1],
357                   myPrimitiveArray->vertices[n+2].xyz[2]);
358       gp_Vec v21(p1,p2),v31(p1,p3),fn = v21.Crossed(v31);
359       if( aNormal.IsOpposite(fn, M_PI / 4.) ) {
360         for( i=0,j=k-1 ; i<k/2 ; i++,j-- ) {
361           x = myPrimitiveArray->vertices[n+i].xyz[0];
362           y = myPrimitiveArray->vertices[n+i].xyz[1];
363           z = myPrimitiveArray->vertices[n+i].xyz[2];
364           myPrimitiveArray->vertices[n+i].xyz[0] = myPrimitiveArray->vertices[n+j].xyz[0];
365           myPrimitiveArray->vertices[n+i].xyz[1] = myPrimitiveArray->vertices[n+j].xyz[1];
366           myPrimitiveArray->vertices[n+i].xyz[2] = myPrimitiveArray->vertices[n+j].xyz[2];
367           myPrimitiveArray->vertices[n+j].xyz[0] = x;
368           myPrimitiveArray->vertices[n+j].xyz[1] = y;
369           myPrimitiveArray->vertices[n+j].xyz[2] = z;
370           if( myPrimitiveArray->vnormals ) {
371             x = myPrimitiveArray->vnormals[n+i].xyz[0];
372             y = myPrimitiveArray->vnormals[n+i].xyz[1];
373             z = myPrimitiveArray->vnormals[n+i].xyz[2];
374             myPrimitiveArray->vnormals[n+i].xyz[0] = myPrimitiveArray->vnormals[n+j].xyz[0];
375             myPrimitiveArray->vnormals[n+i].xyz[1] = myPrimitiveArray->vnormals[n+j].xyz[1];
376             myPrimitiveArray->vnormals[n+i].xyz[2] = myPrimitiveArray->vnormals[n+j].xyz[2];
377             myPrimitiveArray->vnormals[n+j].xyz[0] = x;
378             myPrimitiveArray->vnormals[n+j].xyz[1] = y;
379             myPrimitiveArray->vnormals[n+j].xyz[2] = z;
380
381             x = myPrimitiveArray->vnormals[n+i].xyz[0];
382             y = myPrimitiveArray->vnormals[n+i].xyz[1];
383             z = myPrimitiveArray->vnormals[n+i].xyz[2];
384             gp_Vec vn(x,y,z);
385             if( aNormal.IsOpposite(vn, M_PI / 4.) ) {
386               myPrimitiveArray->vnormals[n+i].xyz[0] = -x;
387               myPrimitiveArray->vnormals[n+i].xyz[1] = -y;
388               myPrimitiveArray->vnormals[n+i].xyz[2] = -z;
389             }
390           }
391           if( myPrimitiveArray->vcolours ) {
392             x = (Standard_ShortReal)myPrimitiveArray->vcolours[n+i];
393             myPrimitiveArray->vcolours[n+i] = myPrimitiveArray->vcolours[n+j];
394             myPrimitiveArray->vcolours[n+j] = (Tint)x;
395           }
396           if( myPrimitiveArray->vtexels ) {
397             x = myPrimitiveArray->vtexels[n+i].xy[0];
398             y = myPrimitiveArray->vtexels[n+i].xy[1];
399             myPrimitiveArray->vtexels[n+i].xy[0] = myPrimitiveArray->vtexels[n+j].xy[0];
400             myPrimitiveArray->vtexels[n+i].xy[1] = myPrimitiveArray->vtexels[n+j].xy[1];
401             myPrimitiveArray->vtexels[n+j].xy[0] = x;
402             myPrimitiveArray->vtexels[n+j].xy[1] = y;
403           }
404         }
405         somethingHasChange = Standard_True;
406       }
407     }
408   }
409   return somethingHasChange;
410 }
411
412 Standard_Boolean Graphic3d_ArrayOfPrimitives::Orientate(const Standard_Integer aBoundIndex,
413                                                         const gp_Dir& aNormal)
414 {
415   Standard_Boolean somethingHasChange = Standard_False;
416   if( myPrimitiveArray && myPrimitiveArray->vertices ) {
417     if( myPrimitiveArray->bounds && 
418         (aBoundIndex > 0) && (aBoundIndex <= myPrimitiveArray->num_bounds) ) {
419       Standard_Integer k,n;
420       for( k=n=1 ; k<aBoundIndex ; k++ )
421         n += myPrimitiveArray->bounds[k];
422       k = myPrimitiveArray->bounds[aBoundIndex-1];
423       somethingHasChange = Orientate(n,k,aNormal);
424     } else if( myPrimitiveArray->bounds ) {
425       Standard_OutOfRange::Raise(" BAD BOUND index");
426     } else if( (aBoundIndex > 0) && (aBoundIndex <= ItemNumber()) ) {
427       switch( myPrimitiveArray->type ) {
428         case TelPointsArrayType:
429         case TelPolylinesArrayType:
430         case TelSegmentsArrayType:
431           break;
432         case TelPolygonsArrayType:
433         case TelTriangleStripsArrayType:
434         case TelTriangleFansArrayType:
435         case TelQuadrangleStripsArrayType:
436           somethingHasChange = Orientate(1,VertexNumber(),aNormal);
437           break;
438         case TelTrianglesArrayType:
439           somethingHasChange = Orientate(aBoundIndex*3-2,3,aNormal);
440           break;
441         case TelQuadranglesArrayType:
442           somethingHasChange = Orientate(aBoundIndex*4-3,4,aNormal);
443           break;
444         default:
445           break;
446       }
447     } else {
448       Standard_OutOfRange::Raise(" BAD ITEM index");
449     }
450   }
451   return somethingHasChange;
452 }
453
454 void Graphic3d_ArrayOfPrimitives::SetVertice( const Standard_Integer anIndex,
455                                               const gp_Pnt& aVertice)
456 {
457   Standard_Real x,y,z;
458   aVertice.Coord(x,y,z);
459   SetVertice(anIndex,Standard_ShortReal(x),Standard_ShortReal(y),Standard_ShortReal(z));
460 }
461
462 void Graphic3d_ArrayOfPrimitives::SetVertexColor( const Standard_Integer anIndex,
463                                                   const Quantity_Color& aColor)
464 {
465   Standard_Real r,g,b;
466   aColor.Values(r,g,b,Quantity_TOC_RGB);
467   SetVertexColor(anIndex,r,g,b);
468 }
469
470 void Graphic3d_ArrayOfPrimitives::SetVertexColor( const Standard_Integer anIndex,
471                                                   const Standard_Integer aColor)
472 {
473   if( !myPrimitiveArray ) return;
474   if( anIndex < 1 || anIndex > myMaxVertexs ) {
475     Standard_OutOfRange::Raise(" BAD VERTEX index");
476   }
477   Standard_Integer index = anIndex - 1;
478   if( myPrimitiveArray->vcolours ) {
479 #if defined (sparc) || defined (__sparc__) || defined (__sparc)
480     /* 
481       Well known processor(x86) architectures that use the little-endian format. 
482       Processors use big-endian format is SPARC. In this case use platform with 
483       SPARC architecture(SUNOS). Byte order could have little-endian format.
484     */
485     const char* p_ch = (const char*)&aColor;
486     myPrimitiveArray->vcolours[index] += p_ch[0];
487     myPrimitiveArray->vcolours[index] += p_ch[1] << 8 ;
488     myPrimitiveArray->vcolours[index] += p_ch[2] << 16;
489     myPrimitiveArray->vcolours[index] += p_ch[3] << 24;
490 #else
491     myPrimitiveArray->vcolours[index] = aColor;
492 #endif
493
494   }
495 }
496
497 void Graphic3d_ArrayOfPrimitives::SetVertexNormal(const Standard_Integer anIndex,
498                                                   const gp_Dir& aNormal)
499 {
500   Standard_Real x,y,z;
501   aNormal.Coord(x,y,z);
502   SetVertexNormal(anIndex,x,y,z);
503 }
504
505 void Graphic3d_ArrayOfPrimitives::SetVertexTexel( const Standard_Integer anIndex,
506                                                   const gp_Pnt2d& aTexel)
507 {
508   Standard_Real x,y;
509   aTexel.Coord(x,y);
510   SetVertexTexel(anIndex,x,y);
511 }
512
513 void Graphic3d_ArrayOfPrimitives::SetBoundColor(const Standard_Integer anIndex,
514                                                 const Quantity_Color& aColor)
515 {
516   Standard_Real r,g,b;
517   aColor.Values(r,g,b,Quantity_TOC_RGB);
518   SetBoundColor(anIndex,r,g,b);
519 }
520
521 Standard_CString Graphic3d_ArrayOfPrimitives::StringType() const
522 {
523   TCollection_AsciiString name("UndefinedArray");
524   switch( myPrimitiveArray->type ) {
525     case TelPointsArrayType:
526       name = "ArrayOfPoints";
527       break;
528     case TelPolylinesArrayType:
529       name = "ArrayOfPolylines";
530       break;
531     case TelSegmentsArrayType:
532       name = "ArrayOfSegments";
533       break;
534     case TelPolygonsArrayType:
535       name = "ArrayOfPolygons";
536       break;
537     case TelTrianglesArrayType:
538       name = "ArrayOfTriangles";
539       break;
540     case TelQuadranglesArrayType:
541       name = "ArrayOfQuadrangles";
542       break;
543     case TelTriangleStripsArrayType:
544       name = "ArrayOfTriangleStrips";
545       break;
546     case TelQuadrangleStripsArrayType:
547       name = "ArrayOfQuadrangleStrips";
548       break;
549     case TelTriangleFansArrayType:
550       name = "ArrayOfTriangleFans";
551       break;
552     default:
553       break;
554   }
555
556   return name.ToCString();
557 }
558
559 gp_Pnt Graphic3d_ArrayOfPrimitives::Vertice(const Standard_Integer aRank) const
560 {
561   Standard_Real x,y,z;
562   Vertice(aRank,x,y,z);
563   return gp_Pnt(x,y,z);
564 }
565
566 Quantity_Color Graphic3d_ArrayOfPrimitives::VertexColor(const Standard_Integer aRank) const
567 {
568   Standard_Real r,g,b;
569   VertexColor(aRank,r,g,b);
570   return Quantity_Color(r,g,b,Quantity_TOC_RGB);
571 }
572
573 gp_Dir Graphic3d_ArrayOfPrimitives::VertexNormal(const Standard_Integer aRank) const
574 {
575   Standard_Real x,y,z;
576   VertexNormal(aRank,x,y,z);
577   return gp_Dir(x,y,z);
578 }
579
580 gp_Pnt2d Graphic3d_ArrayOfPrimitives::VertexTexel(const Standard_Integer aRank) const
581 {
582   Standard_Real x,y;
583   VertexTexel(aRank,x,y);
584   return gp_Pnt2d(x,y);
585 }
586
587 Quantity_Color Graphic3d_ArrayOfPrimitives::BoundColor(const Standard_Integer aRank) const
588 {
589   Standard_Real r = 0.0, g = 0.0, b = 0.0;
590   BoundColor(aRank,r,g,b);
591   return Quantity_Color(r,g,b,Quantity_TOC_RGB);
592 }
593
594 Standard_Integer Graphic3d_ArrayOfPrimitives::ItemNumber() const
595 {
596   Standard_Integer number=-1;
597   if( myPrimitiveArray ) switch( myPrimitiveArray->type ) {
598     case TelPointsArrayType:
599       number = myPrimitiveArray->num_vertexs;
600       break;
601     case TelPolylinesArrayType:
602     case TelPolygonsArrayType:
603       if( myPrimitiveArray->num_bounds > 0 ) 
604         number = myPrimitiveArray->num_bounds;
605       else number = 1;
606       break;
607     case TelSegmentsArrayType:
608       if( myPrimitiveArray->num_edges > 0 ) 
609         number = myPrimitiveArray->num_edges/2;
610       else number = myPrimitiveArray->num_vertexs/2;
611       break;
612     case TelTrianglesArrayType:
613       if( myPrimitiveArray->num_edges > 0 ) 
614         number = myPrimitiveArray->num_edges/3;
615       else number = myPrimitiveArray->num_vertexs/3;
616       break;
617     case TelQuadranglesArrayType:
618       if( myPrimitiveArray->num_edges > 0 ) 
619         number = myPrimitiveArray->num_edges/4;
620       else number = myPrimitiveArray->num_vertexs/4;
621       break;
622     case TelTriangleStripsArrayType:
623       if( myPrimitiveArray->num_bounds > 0 ) 
624         number = myPrimitiveArray->num_vertexs-2*myPrimitiveArray->num_bounds;
625       else number = myPrimitiveArray->num_vertexs-2;
626       break;
627     case TelQuadrangleStripsArrayType:
628       if( myPrimitiveArray->num_bounds > 0 ) 
629         number = myPrimitiveArray->num_vertexs/2-myPrimitiveArray->num_bounds;
630       else number = myPrimitiveArray->num_vertexs/2-1;
631       break;
632     case TelTriangleFansArrayType:
633       if( myPrimitiveArray->num_bounds > 0 ) 
634         number = myPrimitiveArray->num_vertexs-2*myPrimitiveArray->num_bounds;
635       else number = myPrimitiveArray->num_vertexs-2;
636       break;
637     default:
638       break;
639   }
640
641   return number;
642 }
643
644 void Graphic3d_ArrayOfPrimitives::ComputeVNormals(const Standard_Integer from,
645                                                   const Standard_Integer to)
646 {
647   Standard_Integer next = from+1;
648   Standard_Integer last = to+1;
649   gp_Pnt p1,p2,p3;
650
651   if( myMaxEdges > 0 ) {
652     p1 = Vertice(Edge(next++));
653     p2 = Vertice(Edge(next++));
654   } else {
655     p1 = Vertice(next++);
656     p2 = Vertice(next++);
657   }
658
659   gp_Vec vn;
660   
661   while ( next <= last ) {
662     if( myMaxEdges > 0 ) {
663       p3 = Vertice(Edge(next));
664     } else {
665       p3 = Vertice(next);
666     }
667     gp_Vec v21(p2,p1);
668     gp_Vec v31(p3,p1);
669     vn = v21 ^ v31;
670     if( vn.SquareMagnitude() > 0. ) break;
671     next++;
672   }
673
674   if( next > last ) {
675 #if TRACE > 0
676     cout << " An item has a NULL computed facet normal" << endl;
677 #endif
678     return;
679   }
680
681   vn.Normalize();
682   if( myMaxEdges > 0 ) {
683     for( int i=from+1 ; i<=to+1 ; i++ ) {
684       SetVertexNormal(Edge(i),vn);
685     }
686   } else {
687     for( int i=from+1 ; i<=to+1 ; i++ ) {
688       SetVertexNormal(i,vn);
689     }
690   }
691 }
692
693 Standard_Boolean Graphic3d_ArrayOfPrimitives::IsValid()
694 {
695   if( !myPrimitiveArray ) return Standard_False;
696
697   Standard_Integer nvertexs = myPrimitiveArray->num_vertexs;
698   Standard_Integer nbounds = myPrimitiveArray->num_bounds;
699   Standard_Integer nedges = myPrimitiveArray->num_edges;
700   Standard_Integer i,n;
701
702 #if TRACE > 0
703   Standard_CString name = StringType();
704   cout << " !!! An " << name << " has " << ItemNumber() << " items" << endl;
705 #endif
706
707   switch( myPrimitiveArray->type ) {
708     case TelPointsArrayType:
709       if( nvertexs < 1 ) {
710 #if TRACE > 0
711         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
712 #endif
713         return Standard_False;
714       }
715       break;
716     case TelPolylinesArrayType:
717       if( nedges > 0 && nedges < 2 ) {
718 #if TRACE > 0
719         cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
720 #endif
721         return Standard_False;
722       }
723       if( nvertexs < 2 ) {
724 #if TRACE > 0
725         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
726 #endif
727         return Standard_False;
728       }
729       break;
730     case TelSegmentsArrayType:
731       if( nvertexs < 2 ) {
732 #if TRACE > 0
733         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
734 #endif
735         return Standard_False;
736       }
737       break;
738     case TelPolygonsArrayType:
739       if( nedges > 0 && nedges < 3 ) {
740 #if TRACE > 0
741         cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
742 #endif
743         return Standard_False;
744       }
745       if( nvertexs < 3 ) {
746 #if TRACE > 0
747         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
748 #endif
749         return Standard_False;
750       }
751       break;
752     case TelTrianglesArrayType:
753       if( nedges > 0 ) {
754         if( nedges < 3 || nedges % 3 != 0 ) {
755 #if TRACE > 0
756           cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
757 #endif
758           if( nedges > 3 ) myPrimitiveArray->num_edges = 3 * (nedges / 3);
759           else return Standard_False;
760         }
761       } else if( nvertexs < 3 || nvertexs % 3 != 0 ) {
762 #if TRACE > 0
763         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
764 #endif
765         if( nvertexs > 3 ) myPrimitiveArray->num_vertexs = 3 * (nvertexs / 3);
766         else return Standard_False;
767       }
768       break;
769     case TelQuadranglesArrayType:
770       if( nedges > 0 ) {
771         if( nedges < 4 || nedges % 4 != 0 ) {
772 #if TRACE > 0
773           cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
774 #endif
775           if( nedges > 4 ) myPrimitiveArray->num_edges = 4 * (nedges / 4);
776           else return Standard_False;
777         }
778       } else if( nvertexs < 4 || nvertexs % 4 != 0 ) {
779 #if TRACE > 0
780         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
781 #endif
782         if( nvertexs > 4 ) myPrimitiveArray->num_vertexs = 4 * (nvertexs / 4);
783         else return Standard_False;
784       }
785       break;
786     case TelTriangleFansArrayType:
787     case TelTriangleStripsArrayType:
788       if( nvertexs < 3 ) {
789 #if TRACE > 0
790         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
791 #endif
792         return Standard_False;
793       }
794       break;
795     case TelQuadrangleStripsArrayType:
796       if( nvertexs < 4 ) {
797 #if TRACE > 0
798         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
799 #endif
800         return Standard_False;
801       }
802       break;
803     default:
804 #if TRACE > 0
805       cout << " *** UNKNOWN Array of primitives type found" << endl;
806 #endif
807       return Standard_False;
808   }
809
810   // total number of edges(verticies) in bounds should be the same as variable
811   // of total number of defined edges(verticies); if no edges - only verticies 
812   // could be in bounds.
813   if( nbounds > 0 ) {
814     for( i=n=0 ; i<nbounds ; i++ ) {
815       n += myPrimitiveArray->bounds[i];
816     }
817     if( nedges > 0 && n != nedges ) {
818 #if TRACE > 0
819       cout << " *** An " << name << " has an incoherent number of edges " << nedges << endl;
820 #endif
821       if( nedges > n ) myPrimitiveArray->num_edges = n;
822       else return Standard_False;
823     } else if ( nedges == 0 && n != nvertexs ) {
824 #if TRACE > 0
825       cout << " *** An " << name << " has an incoherent number of vertexs " << nvertexs << endl;
826 #endif
827       if( nvertexs > n ) myPrimitiveArray->num_vertexs = n;
828       else return Standard_False;
829     }
830   }
831
832   // check that edges (indexes to an array of verticies) are in range.
833   if( nedges > 0 ) {
834     for( i=0 ; i<nedges ; i++ ) {
835       if( myPrimitiveArray->edges[i] >= myPrimitiveArray->num_vertexs ) {
836 #if TRACE > 0
837         cout << " *** An " << name << " has a vertex index " << myPrimitiveArray->edges[i] << " greater than the number of defined vertexs " << myPrimitiveArray->num_vertexs << endl;
838 #endif
839         myPrimitiveArray->edges[i] = myPrimitiveArray->num_vertexs-1;
840       }
841     }
842   }
843
844   return Standard_True;
845 }