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 under
7 // the terms of the GNU Lesser General Public License 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 #include <Graphic3d_ArrayOfPrimitives.hxx>
16 
17 #include <Graphic3d_ArrayOfPoints.hxx>
18 #include <Graphic3d_ArrayOfSegments.hxx>
19 #include <Graphic3d_ArrayOfPolylines.hxx>
20 #include <Graphic3d_ArrayOfTriangles.hxx>
21 #include <Graphic3d_ArrayOfTriangleStrips.hxx>
22 #include <Graphic3d_ArrayOfTriangleFans.hxx>
23 #include <Graphic3d_ArrayOfQuadrangles.hxx>
24 #include <Graphic3d_ArrayOfQuadrangleStrips.hxx>
25 #include <Graphic3d_ArrayOfPolygons.hxx>
26 #include <Graphic3d_AttribBuffer.hxx>
27 #include <Graphic3d_MutableIndexBuffer.hxx>
28 
29 #include <TCollection_AsciiString.hxx>
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPrimitives,Standard_Transient)34 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPrimitives, Standard_Transient)
35 
36 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPoints,           Graphic3d_ArrayOfPrimitives)
37 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfSegments,         Graphic3d_ArrayOfPrimitives)
38 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolylines,        Graphic3d_ArrayOfPrimitives)
39 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangles,        Graphic3d_ArrayOfPrimitives)
40 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangleStrips,   Graphic3d_ArrayOfPrimitives)
41 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangleFans,     Graphic3d_ArrayOfPrimitives)
42 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangles,      Graphic3d_ArrayOfPrimitives)
43 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangleStrips, Graphic3d_ArrayOfPrimitives)
44 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolygons,         Graphic3d_ArrayOfPrimitives)
45 
46 // =======================================================================
47 // function : CreateArray
48 // purpose  :
49 // =======================================================================
50 Handle(Graphic3d_ArrayOfPrimitives) Graphic3d_ArrayOfPrimitives::CreateArray (Graphic3d_TypeOfPrimitiveArray theType,
51                                                                               Standard_Integer theMaxVertexs,
52                                                                               Standard_Integer theMaxBounds,
53                                                                               Standard_Integer theMaxEdges,
54                                                                               Graphic3d_ArrayFlags theArrayFlags)
55 {
56   switch (theType)
57   {
58     case Graphic3d_TOPA_UNDEFINED:
59       return Handle(Graphic3d_ArrayOfPrimitives)();
60     case Graphic3d_TOPA_POINTS:
61       return new Graphic3d_ArrayOfPoints (theMaxVertexs, theArrayFlags);
62     case Graphic3d_TOPA_SEGMENTS:
63       return new Graphic3d_ArrayOfSegments (theMaxVertexs, theMaxEdges, theArrayFlags);
64     case Graphic3d_TOPA_POLYLINES:
65       return new Graphic3d_ArrayOfPolylines (theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
66     case Graphic3d_TOPA_TRIANGLES:
67       return new Graphic3d_ArrayOfTriangles (theMaxVertexs, theMaxEdges, theArrayFlags);
68     case Graphic3d_TOPA_TRIANGLESTRIPS:
69       return new Graphic3d_ArrayOfTriangleStrips (theMaxVertexs, theMaxBounds, theArrayFlags);
70     case Graphic3d_TOPA_TRIANGLEFANS:
71       return new Graphic3d_ArrayOfTriangleFans (theMaxVertexs, theMaxBounds, theArrayFlags);
72     case Graphic3d_TOPA_LINES_ADJACENCY:
73     case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
74     case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
75     case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
76       return new Graphic3d_ArrayOfPrimitives (theType, theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
77     case Graphic3d_TOPA_QUADRANGLES:
78       return new Graphic3d_ArrayOfQuadrangles (theMaxVertexs, theMaxEdges, theArrayFlags);
79     case Graphic3d_TOPA_QUADRANGLESTRIPS:
80       return new Graphic3d_ArrayOfQuadrangleStrips (theMaxVertexs, theMaxBounds, theArrayFlags);
81     case Graphic3d_TOPA_POLYGONS:
82       return new Graphic3d_ArrayOfPolygons (theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
83   }
84   return Handle(Graphic3d_ArrayOfPrimitives)();
85 }
86 
87 // =======================================================================
88 // function : init
89 // purpose  :
90 // =======================================================================
init(Graphic3d_TypeOfPrimitiveArray theType,Standard_Integer theMaxVertexs,Standard_Integer theMaxBounds,Standard_Integer theMaxEdges,Graphic3d_ArrayFlags theArrayOptions)91 void Graphic3d_ArrayOfPrimitives::init (Graphic3d_TypeOfPrimitiveArray theType,
92                                         Standard_Integer theMaxVertexs,
93                                         Standard_Integer theMaxBounds,
94                                         Standard_Integer theMaxEdges,
95                                         Graphic3d_ArrayFlags theArrayOptions)
96 {
97   myType = theType;
98   myNormData = NULL;
99   myTexData  = NULL;
100   myColData  = NULL;
101   myAttribs.Nullify();
102   myIndices.Nullify();
103   myBounds.Nullify();
104 
105   const Handle(NCollection_BaseAllocator)& anAlloc = Graphic3d_Buffer::DefaultAllocator();
106   if ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) != 0
107    || (theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) != 0)
108   {
109     Graphic3d_AttribBuffer* anAttribs = new Graphic3d_AttribBuffer (anAlloc);
110     anAttribs->SetMutable     ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) != 0);
111     anAttribs->SetInterleaved ((theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) == 0);
112     myAttribs = anAttribs;
113   }
114   else
115   {
116     myAttribs = new Graphic3d_Buffer (anAlloc);
117   }
118   if (theMaxVertexs < 1)
119   {
120     return;
121   }
122 
123   if (theMaxEdges > 0)
124   {
125     if ((theArrayOptions & Graphic3d_ArrayFlags_IndexesMutable) != 0)
126     {
127       myIndices = new Graphic3d_MutableIndexBuffer (anAlloc);
128     }
129     else
130     {
131       myIndices = new Graphic3d_IndexBuffer (anAlloc);
132     }
133     if (theMaxVertexs < Standard_Integer(USHRT_MAX))
134     {
135       if (!myIndices->Init<unsigned short> (theMaxEdges))
136       {
137         myIndices.Nullify();
138         return;
139       }
140     }
141     else
142     {
143       if (!myIndices->Init<unsigned int> (theMaxEdges))
144       {
145         myIndices.Nullify();
146         return;
147       }
148     }
149     myIndices->NbElements = 0;
150   }
151 
152   Graphic3d_Attribute anAttribs[4];
153   Standard_Integer    aNbAttribs = 0;
154   anAttribs[aNbAttribs].Id       = Graphic3d_TOA_POS;
155   anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
156   ++aNbAttribs;
157   if ((theArrayOptions & Graphic3d_ArrayFlags_VertexNormal) != 0)
158   {
159     anAttribs[aNbAttribs].Id       = Graphic3d_TOA_NORM;
160     anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
161     ++aNbAttribs;
162   }
163   if ((theArrayOptions & Graphic3d_ArrayFlags_VertexTexel) != 0)
164   {
165     anAttribs[aNbAttribs].Id       = Graphic3d_TOA_UV;
166     anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC2;
167     ++aNbAttribs;
168   }
169   if ((theArrayOptions & Graphic3d_ArrayFlags_VertexColor) != 0)
170   {
171     anAttribs[aNbAttribs].Id       = Graphic3d_TOA_COLOR;
172     anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC4UB;
173     ++aNbAttribs;
174   }
175 
176   if (!myAttribs->Init (theMaxVertexs, anAttribs, aNbAttribs))
177   {
178     myAttribs.Nullify();
179     myIndices.Nullify();
180     return;
181   }
182 
183   Standard_Integer anAttribDummy = 0;
184   myAttribs->ChangeAttributeData (Graphic3d_TOA_POS, anAttribDummy, myPosStride);
185   myNormData = myAttribs->ChangeAttributeData (Graphic3d_TOA_NORM,  anAttribDummy, myNormStride);
186   myTexData  = myAttribs->ChangeAttributeData (Graphic3d_TOA_UV,    anAttribDummy, myTexStride);
187   myColData  = myAttribs->ChangeAttributeData (Graphic3d_TOA_COLOR, anAttribDummy, myColStride);
188 
189   memset (myAttribs->ChangeData(), 0, size_t(myAttribs->Stride) * size_t(myAttribs->NbMaxElements()));
190   if ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) == 0
191    && (theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) == 0)
192   {
193     myAttribs->NbElements = 0;
194   }
195 
196   if (theMaxBounds > 0)
197   {
198     myBounds = new Graphic3d_BoundBuffer (anAlloc);
199     if (!myBounds->Init (theMaxBounds, (theArrayOptions & Graphic3d_ArrayFlags_BoundColor) != 0))
200     {
201       myAttribs.Nullify();
202       myIndices.Nullify();
203       myBounds .Nullify();
204       return;
205     }
206     myBounds->NbBounds = 0;
207   }
208 }
209 
210 // =======================================================================
211 // function : ~Graphic3d_ArrayOfPrimitives
212 // purpose  :
213 // =======================================================================
~Graphic3d_ArrayOfPrimitives()214 Graphic3d_ArrayOfPrimitives::~Graphic3d_ArrayOfPrimitives()
215 {
216   myIndices.Nullify();
217   myAttribs.Nullify();
218   myBounds .Nullify();
219 }
220 
221 // =======================================================================
222 // function : AddBound
223 // purpose  :
224 // =======================================================================
AddBound(const Standard_Integer theEdgeNumber)225 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber)
226 {
227   Standard_OutOfRange_Raise_if (myBounds.IsNull() || myBounds->NbBounds >= myBounds->NbMaxBounds, "TOO many BOUND");
228   myBounds->Bounds[myBounds->NbBounds] = theEdgeNumber;
229   return ++myBounds->NbBounds;
230 }
231 
232 // =======================================================================
233 // function : AddBound
234 // purpose  :
235 // =======================================================================
AddBound(const Standard_Integer theEdgeNumber,const Standard_Real theR,const Standard_Real theG,const Standard_Real theB)236 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber,
237                                                         const Standard_Real    theR,
238                                                         const Standard_Real    theG,
239                                                         const Standard_Real    theB)
240 {
241   Standard_OutOfRange_Raise_if (myBounds.IsNull() || myBounds->NbBounds >= myBounds->NbMaxBounds, "TOO many BOUND");
242   myBounds->Bounds[myBounds->NbBounds] = theEdgeNumber;
243   ++myBounds->NbBounds;
244   SetBoundColor (myBounds->NbBounds, theR, theG, theB);
245   return myBounds->NbBounds;
246 }
247 
248 // =======================================================================
249 // function : AddEdge
250 // purpose  :
251 // =======================================================================
AddEdge(const Standard_Integer theVertexIndex)252 Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge (const Standard_Integer theVertexIndex)
253 {
254   Standard_OutOfRange_Raise_if (myIndices.IsNull() || myIndices->NbElements >= myIndices->NbMaxElements(), "TOO many EDGE");
255   Standard_OutOfRange_Raise_if (theVertexIndex < 1 || theVertexIndex > myAttribs->NbElements, "BAD VERTEX index");
256   const Standard_Integer aVertIndex = theVertexIndex - 1;
257   myIndices->SetIndex (myIndices->NbElements, aVertIndex);
258   return ++myIndices->NbElements;
259 }
260 
261 // =======================================================================
262 // function : AddTriangleStripEdges
263 // purpose  :
264 // =======================================================================
AddTriangleStripEdges(Standard_Integer theVertexLower,Standard_Integer theVertexUpper)265 void Graphic3d_ArrayOfPrimitives::AddTriangleStripEdges (Standard_Integer theVertexLower,
266                                                          Standard_Integer theVertexUpper)
267 {
268   if (myType != Graphic3d_TOPA_TRIANGLES)
269   {
270     throw Standard_TypeMismatch ("Not array of triangles");
271   }
272 
273   Standard_Boolean isOdd = Standard_True;
274   for (Standard_Integer aNodeIter = theVertexLower + 2; aNodeIter <= theVertexUpper; ++aNodeIter)
275   {
276     if (isOdd)
277     {
278       AddTriangleEdges (aNodeIter - 2, aNodeIter - 1, aNodeIter);
279     }
280     else
281     {
282       AddTriangleEdges (aNodeIter - 1, aNodeIter - 2, aNodeIter);
283     }
284     isOdd = !isOdd;
285   }
286 }
287 
288 // =======================================================================
289 // function : AddTriangleFanEdges
290 // purpose  :
291 // =======================================================================
AddTriangleFanEdges(Standard_Integer theVertexLower,Standard_Integer theVertexUpper,Standard_Boolean theToClose)292 void Graphic3d_ArrayOfPrimitives::AddTriangleFanEdges (Standard_Integer theVertexLower,
293                                                        Standard_Integer theVertexUpper,
294                                                        Standard_Boolean theToClose)
295 {
296   if (myType != Graphic3d_TOPA_TRIANGLES)
297   {
298     throw Standard_TypeMismatch ("Not array of triangles");
299   }
300 
301   for (Standard_Integer aNodeIter = theVertexLower + 1; aNodeIter <= theVertexUpper; ++aNodeIter)
302   {
303     AddTriangleEdges (theVertexLower, aNodeIter - 1, aNodeIter);
304   }
305   if (theToClose)
306   {
307     AddTriangleEdges (theVertexLower, theVertexUpper, theVertexLower + 1);
308   }
309 }
310 
311 // =======================================================================
312 // function : AddPolylineEdges
313 // purpose  :
314 // =======================================================================
AddPolylineEdges(Standard_Integer theVertexLower,Standard_Integer theVertexUpper,Standard_Boolean theToClose)315 void Graphic3d_ArrayOfPrimitives::AddPolylineEdges (Standard_Integer theVertexLower,
316                                                     Standard_Integer theVertexUpper,
317                                                     Standard_Boolean theToClose)
318 {
319   if (myType != Graphic3d_TOPA_SEGMENTS)
320   {
321     throw Standard_TypeMismatch ("Not array of segments");
322   }
323 
324   for (Standard_Integer aNodeIter = theVertexLower; aNodeIter < theVertexUpper; ++aNodeIter)
325   {
326     AddSegmentEdges (aNodeIter, aNodeIter + 1);
327   }
328   if (theToClose)
329   {
330     AddSegmentEdges (theVertexUpper, theVertexLower);
331   }
332 }
333 
334 // =======================================================================
335 // function : StringType
336 // purpose  :
337 // =======================================================================
StringType() const338 Standard_CString Graphic3d_ArrayOfPrimitives::StringType() const
339 {
340   switch (myType)
341   {
342     case Graphic3d_TOPA_POINTS:           return "ArrayOfPoints";
343     case Graphic3d_TOPA_SEGMENTS:         return "ArrayOfSegments";
344     case Graphic3d_TOPA_POLYLINES:        return "ArrayOfPolylines";
345     case Graphic3d_TOPA_TRIANGLES:        return "ArrayOfTriangles";
346     case Graphic3d_TOPA_TRIANGLESTRIPS:   return "ArrayOfTriangleStrips";
347     case Graphic3d_TOPA_TRIANGLEFANS:     return "ArrayOfTriangleFans";
348     case Graphic3d_TOPA_LINES_ADJACENCY:          return "ArrayOfLinesAdjacency";
349     case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:     return "ArrayOfLineStripAdjacency";
350     case Graphic3d_TOPA_TRIANGLES_ADJACENCY:      return "ArrayOfTrianglesAdjacency";
351     case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY: return "ArrayOfTriangleStripAdjacency";
352     case Graphic3d_TOPA_QUADRANGLES:      return "ArrayOfQuadrangles";
353     case Graphic3d_TOPA_QUADRANGLESTRIPS: return "ArrayOfQuadrangleStrips";
354     case Graphic3d_TOPA_POLYGONS:         return "ArrayOfPolygons";
355     case Graphic3d_TOPA_UNDEFINED:        return "UndefinedArray";
356   }
357   return "UndefinedArray";
358 }
359 
360 // =======================================================================
361 // function : ItemNumber
362 // purpose  :
363 // =======================================================================
ItemNumber() const364 Standard_Integer Graphic3d_ArrayOfPrimitives::ItemNumber() const
365 {
366   if (myAttribs.IsNull())
367   {
368     return -1;
369   }
370 
371   switch (myType)
372   {
373     case Graphic3d_TOPA_POINTS:           return myAttribs->NbElements;
374     case Graphic3d_TOPA_POLYLINES:
375     case Graphic3d_TOPA_POLYGONS:         return !myBounds.IsNull() ? myBounds->NbBounds : 1;
376     case Graphic3d_TOPA_SEGMENTS:         return myIndices.IsNull() || myIndices->NbElements < 1
377                                                ? myAttribs->NbElements / 2
378                                                : myIndices->NbElements / 2;
379     case Graphic3d_TOPA_TRIANGLES:        return myIndices.IsNull() || myIndices->NbElements < 1
380                                                ? myAttribs->NbElements / 3
381                                                : myIndices->NbElements / 3;
382     case Graphic3d_TOPA_QUADRANGLES:      return myIndices.IsNull() || myIndices->NbElements < 1
383                                                ? myAttribs->NbElements / 4
384                                                : myIndices->NbElements / 4;
385     case Graphic3d_TOPA_TRIANGLESTRIPS:   return !myBounds.IsNull()
386                                                ? myAttribs->NbElements - 2 * myBounds->NbBounds
387                                                : myAttribs->NbElements - 2;
388     case Graphic3d_TOPA_QUADRANGLESTRIPS: return !myBounds.IsNull()
389                                                ? myAttribs->NbElements / 2 - myBounds->NbBounds
390                                                : myAttribs->NbElements / 2 - 1;
391     case Graphic3d_TOPA_TRIANGLEFANS:     return !myBounds.IsNull()
392                                                ? myAttribs->NbElements - 2 * myBounds->NbBounds
393                                                : myAttribs->NbElements - 2;
394     case Graphic3d_TOPA_LINES_ADJACENCY:  return myIndices.IsNull() || myIndices->NbElements < 1
395                                                ? myAttribs->NbElements / 4
396                                                : myIndices->NbElements / 4;
397     case Graphic3d_TOPA_LINE_STRIP_ADJACENCY: return !myBounds.IsNull()
398                                                     ? myAttribs->NbElements - 4 * myBounds->NbBounds
399                                                     : myAttribs->NbElements - 4;
400     case Graphic3d_TOPA_TRIANGLES_ADJACENCY: return myIndices.IsNull() || myIndices->NbElements < 1
401                                                   ? myAttribs->NbElements / 6
402                                                   : myIndices->NbElements / 6;
403     case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY: return !myBounds.IsNull()
404                                                 ? myAttribs->NbElements - 4 * myBounds->NbBounds
405                                                 : myAttribs->NbElements - 4;
406     case Graphic3d_TOPA_UNDEFINED:        return -1;
407   }
408   return -1;
409 }
410 
411 // =======================================================================
412 // function : IsValid
413 // purpose  :
414 // =======================================================================
IsValid()415 Standard_Boolean Graphic3d_ArrayOfPrimitives::IsValid()
416 {
417   if (myAttribs.IsNull())
418   {
419     return Standard_False;
420   }
421 
422   Standard_Integer nvertexs = myAttribs->NbElements;
423   Standard_Integer nbounds  = myBounds.IsNull()  ? 0 : myBounds->NbBounds;
424   Standard_Integer nedges   = myIndices.IsNull() ? 0 : myIndices->NbElements;
425   switch (myType)
426   {
427     case Graphic3d_TOPA_POINTS:
428       if (nvertexs < 1)
429       {
430         return Standard_False;
431       }
432       break;
433     case Graphic3d_TOPA_POLYLINES:
434       if (nedges > 0
435        && nedges < 2)
436       {
437         return Standard_False;
438       }
439       if (nvertexs < 2)
440       {
441         return Standard_False;
442       }
443       break;
444     case Graphic3d_TOPA_SEGMENTS:
445       if (nvertexs < 2)
446       {
447         return Standard_False;
448       }
449       break;
450     case Graphic3d_TOPA_POLYGONS:
451       if (nedges > 0
452        && nedges < 3)
453       {
454         return Standard_False;
455       }
456       if (nvertexs < 3)
457       {
458         return Standard_False;
459       }
460       break;
461     case Graphic3d_TOPA_TRIANGLES:
462       if (nedges > 0)
463       {
464         if (nedges < 3
465          || nedges % 3 != 0)
466         {
467           if (nedges <= 3)
468           {
469             return Standard_False;
470           }
471           myIndices->NbElements = 3 * (nedges / 3);
472         }
473       }
474       else if (nvertexs < 3
475             || nvertexs % 3 != 0 )
476       {
477         if (nvertexs <= 3)
478         {
479           return Standard_False;
480         }
481         myAttribs->NbElements = 3 * (nvertexs / 3);
482       }
483       break;
484     case Graphic3d_TOPA_QUADRANGLES:
485       if (nedges > 0)
486       {
487         if (nedges < 4
488          || nedges % 4 != 0)
489         {
490           if (nedges <= 4)
491           {
492             return Standard_False;
493           }
494           myIndices->NbElements = 4 * (nedges / 4);
495         }
496       }
497       else if (nvertexs < 4
498             || nvertexs % 4 != 0)
499       {
500         if (nvertexs <= 4)
501         {
502           return Standard_False;
503         }
504         myAttribs->NbElements = 4 * (nvertexs / 4);
505       }
506       break;
507     case Graphic3d_TOPA_TRIANGLEFANS:
508     case Graphic3d_TOPA_TRIANGLESTRIPS:
509       if (nvertexs < 3)
510       {
511         return Standard_False;
512       }
513       break;
514     case Graphic3d_TOPA_QUADRANGLESTRIPS:
515       if (nvertexs < 4)
516       {
517         return Standard_False;
518       }
519       break;
520     case Graphic3d_TOPA_LINES_ADJACENCY:
521     case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
522       if (nvertexs < 4)
523       {
524         return Standard_False;
525       }
526       break;
527     case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
528     case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
529       if (nvertexs < 6)
530       {
531         return Standard_False;
532       }
533       break;
534     case Graphic3d_TOPA_UNDEFINED:
535     default:
536       return Standard_False;
537   }
538 
539   // total number of edges(vertices) in bounds should be the same as variable
540   // of total number of defined edges(vertices); if no edges - only vertices
541   // could be in bounds.
542   if (nbounds > 0)
543   {
544     Standard_Integer n = 0;
545     for (Standard_Integer aBoundIter = 0; aBoundIter < nbounds; ++aBoundIter)
546     {
547       n += myBounds->Bounds[aBoundIter];
548     }
549     if (nedges > 0
550      && n != nedges)
551     {
552       if (nedges <= n)
553       {
554         return Standard_False;
555       }
556       myIndices->NbElements = n;
557     }
558     else if (nedges == 0
559           && n != nvertexs)
560     {
561       if (nvertexs <= n)
562       {
563         return Standard_False;
564       }
565       myAttribs->NbElements = n;
566     }
567   }
568 
569   // check that edges (indexes to an array of vertices) are in range.
570   if (nedges > 0)
571   {
572     for (Standard_Integer anEdgeIter = 0; anEdgeIter < nedges; ++anEdgeIter)
573     {
574       if (myIndices->Index (anEdgeIter) >= myAttribs->NbElements)
575       {
576         return Standard_False;
577       }
578     }
579   }
580   return Standard_True;
581 }
582