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