0028276: Visualization, Graphic3d_ArrayOfPrimitives - fix usage of 16-bit indices
[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 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 <gp_Dir.hxx>
18 #include <gp_Pnt.hxx>
19 #include <gp_Pnt2d.hxx>
20 #include <Graphic3d_Group.hxx>
21 #include <NCollection_AlignedAllocator.hxx>
22 #include <OSD_Environment.hxx>
23 #include <Quantity_Color.hxx>
24 #include <Standard.hxx>
25 #include <Standard_OutOfRange.hxx>
26 #include <Standard_Type.hxx>
27 #include <TCollection_AsciiString.hxx>
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPrimitives,MMgt_TShared)
32
33 Graphic3d_ArrayOfPrimitives::Graphic3d_ArrayOfPrimitives (const Graphic3d_TypeOfPrimitiveArray theType,
34                                                           const Standard_Integer               theMaxVertexs,
35                                                           const Standard_Integer               theMaxBounds,
36                                                           const Standard_Integer               theMaxEdges,
37                                                           const Standard_Boolean               theHasVNormals,
38                                                           const Standard_Boolean               theHasVColors,
39                                                           const Standard_Boolean               theHasFColors,
40                                                           const Standard_Boolean               theHasVTexels)
41 : myType       (theType),
42   myMaxBounds  (0),
43   myMaxVertexs (0),
44   myMaxEdges   (0),
45   myVNor       (0),
46   myVTex       (0),
47   myVCol       (0)
48 {
49   Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
50   myAttribs = new Graphic3d_Buffer (anAlloc);
51   if (theMaxVertexs < 1)
52   {
53     return;
54   }
55
56   if (theMaxEdges > 0)
57   {
58     myIndices = new Graphic3d_IndexBuffer (anAlloc);
59     if (theMaxVertexs < Standard_Integer(USHRT_MAX))
60     {
61       if (!myIndices->Init<unsigned short> (theMaxEdges))
62       {
63         myIndices.Nullify();
64         return;
65       }
66     }
67     else
68     {
69       if (!myIndices->Init<unsigned int> (theMaxEdges))
70       {
71         myIndices.Nullify();
72         return;
73       }
74     }
75     myIndices->NbElements = 0;
76   }
77
78   Graphic3d_Attribute anAttribs[4];
79   Standard_Integer    aNbAttribs = 0;
80   anAttribs[aNbAttribs].Id       = Graphic3d_TOA_POS;
81   anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
82   ++aNbAttribs;
83   if (theHasVNormals)
84   {
85     anAttribs[aNbAttribs].Id       = Graphic3d_TOA_NORM;
86     anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
87     ++aNbAttribs;
88   }
89   if (theHasVTexels)
90   {
91     anAttribs[aNbAttribs].Id       = Graphic3d_TOA_UV;
92     anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC2;
93     ++aNbAttribs;
94   }
95   if (theHasVColors)
96   {
97     anAttribs[aNbAttribs].Id       = Graphic3d_TOA_COLOR;
98     anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC4UB;
99     ++aNbAttribs;
100   }
101
102   if (!myAttribs->Init (theMaxVertexs, anAttribs, aNbAttribs))
103   {
104     myAttribs.Nullify();
105     myIndices.Nullify();
106     return;
107   }
108   memset (myAttribs->ChangeData (0), 0, size_t(myAttribs->Stride) * size_t(myAttribs->NbElements));
109
110   if (theMaxBounds > 0)
111   {
112     myBounds = new Graphic3d_BoundBuffer (anAlloc);
113     if (!myBounds->Init (theMaxBounds, theHasFColors))
114     {
115       myAttribs.Nullify();
116       myIndices.Nullify();
117       myBounds .Nullify();
118       return;
119     }
120     myBounds->NbBounds = 0;
121   }
122
123   for (Standard_Integer anAttribIter = 0; anAttribIter < aNbAttribs; ++anAttribIter)
124   {
125     const Graphic3d_Attribute& anAttrib = anAttribs[anAttribIter];
126     switch (anAttrib.Id)
127     {
128       case Graphic3d_TOA_POS:
129       case Graphic3d_TOA_CUSTOM:
130         break;
131       case Graphic3d_TOA_NORM:
132       {
133         myVNor = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
134         break;
135       }
136       case Graphic3d_TOA_UV:
137       {
138         myVTex = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
139         break;
140       }
141       case Graphic3d_TOA_COLOR:
142       {
143         myVCol = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
144         break;
145       }
146     }
147   }
148
149   myAttribs->NbElements = 0;
150   myMaxVertexs = theMaxVertexs;
151   myMaxBounds  = theMaxBounds;
152   myMaxEdges   = theMaxEdges;
153 }
154
155 void Graphic3d_ArrayOfPrimitives::Destroy()
156 {
157   myVNor = 0;
158   myVTex = 0;
159   myVCol = 0;
160   myIndices.Nullify();
161   myAttribs.Nullify();
162   myBounds .Nullify();
163 }
164
165 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const Standard_ShortReal theX,
166                                                          const Standard_ShortReal theY,
167                                                          const Standard_ShortReal theZ)
168 {
169   if (myAttribs.IsNull())
170   {
171     return 0;
172   }
173
174   const Standard_Integer anIndex = myAttribs->NbElements + 1;
175   SetVertice (anIndex, theX, theY, theZ);
176   return anIndex;
177 }
178
179 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const gp_Pnt&         theVertex,
180                                                          const Quantity_Color& theColor)
181 {
182   const Standard_Integer anIndex = AddVertex (theVertex);
183   SetVertexColor (anIndex, theColor.Red(), theColor.Green(), theColor.Blue());
184   return anIndex;
185 }
186
187 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const gp_Pnt&          theVertex,
188                                                          const Standard_Integer theColor32)
189 {
190   const Standard_Integer anIndex = AddVertex (theVertex);
191   SetVertexColor (anIndex, theColor32);
192   return anIndex;
193 }
194
195 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const Standard_ShortReal theX,  const Standard_ShortReal theY,  const Standard_ShortReal theZ,
196                                                          const Standard_ShortReal theNX, const Standard_ShortReal theNY, const Standard_ShortReal theNZ)
197 {
198   if (myAttribs.IsNull())
199   {
200     return 0;
201   }
202
203   const Standard_Integer anIndex = myAttribs->NbElements + 1;
204   SetVertice      (anIndex, theX,  theY,  theZ);
205   SetVertexNormal (anIndex, theNX, theNY, theNZ);
206   return anIndex;
207 }
208
209 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const gp_Pnt&         theVertex,
210                                                          const gp_Dir&         theNormal,
211                                                          const Quantity_Color& theColor)
212 {
213   const Standard_Integer anIndex = AddVertex (theVertex, theNormal);
214   SetVertexColor (anIndex, theColor.Red(), theColor.Green(), theColor.Blue());
215   return anIndex;
216 }
217
218 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const gp_Pnt&          theVertex,
219                                                          const gp_Dir&          theNormal,
220                                                          const Standard_Integer theColor32)
221 {
222   const Standard_Integer anIndex = AddVertex (theVertex, theNormal);
223   SetVertexColor (anIndex, theColor32);
224   return anIndex;
225 }
226
227 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const Standard_ShortReal theX,  const Standard_ShortReal theY, const Standard_ShortReal theZ,
228                                                          const Standard_ShortReal theTX, const Standard_ShortReal theTY)
229 {
230   if (myAttribs.IsNull())
231   {
232     return 0;
233   }
234
235   const Standard_Integer anIndex = myAttribs->NbElements + 1;
236   SetVertice     (anIndex, theX, theY, theZ);
237   SetVertexTexel (anIndex, theTX, theTY);
238   return anIndex;
239 }
240
241 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const Standard_ShortReal theX,  const Standard_ShortReal theY,  const Standard_ShortReal theZ,
242                                                          const Standard_ShortReal theNX, const Standard_ShortReal theNY, const Standard_ShortReal theNZ,
243                                                          const Standard_ShortReal theTX, const Standard_ShortReal theTY)
244 {
245   if (myAttribs.IsNull())
246   {
247     return 0;
248   }
249
250   const Standard_Integer anIndex = myAttribs->NbElements + 1;
251   SetVertice      (anIndex, theX,  theY,  theZ);
252   SetVertexNormal (anIndex, theNX, theNY, theNZ);
253   SetVertexTexel  (anIndex, theTX, theTY);
254   return anIndex;
255 }
256
257 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber)
258 {
259   if (myBounds.IsNull())
260   {
261     return 0;
262   }
263   Standard_Integer anIndex = myBounds->NbBounds;
264   if (anIndex >= myMaxBounds)
265   {
266     Standard_OutOfRange::Raise ("TOO many BOUNDS");
267   }
268
269   myBounds->Bounds[anIndex] = theEdgeNumber;
270   myBounds->NbBounds        = ++anIndex;
271   return anIndex;
272 }
273
274 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber,
275                                                         const Quantity_Color&  theColor)
276 {
277   return AddBound (theEdgeNumber, theColor.Red(), theColor.Green(), theColor.Blue());
278 }
279
280 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber,
281                                                         const Standard_Real    theR,
282                                                         const Standard_Real    theG,
283                                                         const Standard_Real    theB)
284 {
285   if (myBounds.IsNull())
286   {
287     return 0;
288   }
289   Standard_Integer anIndex = myBounds->NbBounds;
290   if (anIndex >= myMaxBounds)
291   {
292     Standard_OutOfRange::Raise ("TOO many BOUND");
293   }
294
295   myBounds->Bounds[anIndex] = theEdgeNumber;
296   myBounds->NbBounds        = ++anIndex;
297   SetBoundColor (anIndex, theR, theG, theB);
298   return anIndex;
299 }
300
301 Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge (const Standard_Integer theVertexIndex)
302 {
303   if (myIndices.IsNull())
304   {
305     return 0;
306   }
307
308   Standard_Integer anIndex = myIndices->NbElements;
309   if (anIndex >= myMaxEdges)
310   {
311     Standard_OutOfRange::Raise ("TOO many EDGE");
312   }
313
314   Standard_Integer aVertIndex = theVertexIndex - 1;
315   if (theVertexIndex <= 0
316    || aVertIndex >= myMaxVertexs)
317   {
318     Standard_OutOfRange::Raise ("BAD EDGE vertex index");
319   }
320
321   myIndices->SetIndex (anIndex, aVertIndex);
322   myIndices->NbElements = ++anIndex;
323   return anIndex;
324 }
325
326 void Graphic3d_ArrayOfPrimitives::SetVertice (const Standard_Integer theIndex,
327                                               const gp_Pnt&          theVertex)
328 {
329   SetVertice (theIndex,
330               Standard_ShortReal (theVertex.X()),
331               Standard_ShortReal (theVertex.Y()),
332               Standard_ShortReal (theVertex.Z()));
333 }
334
335 void Graphic3d_ArrayOfPrimitives::SetVertexColor (const Standard_Integer theIndex,
336                                                   const Quantity_Color&  theColor)
337 {
338   SetVertexColor (theIndex, theColor.Red(), theColor.Green(), theColor.Blue());
339 }
340
341 void Graphic3d_ArrayOfPrimitives::SetVertexColor (const Standard_Integer theIndex,
342                                                   const Standard_Integer theColor)
343 {
344   if (myAttribs.IsNull())
345   {
346     return;
347   }
348
349   if (theIndex < 1
350    || theIndex > myMaxVertexs)
351   {
352     Standard_OutOfRange::Raise ("BAD VERTEX index");
353   }
354
355   if (myVCol != 0)
356   {
357     *reinterpret_cast<Standard_Integer* >(myAttribs->changeValue (theIndex - 1) + size_t(myVCol)) = theColor;
358   }
359 }
360
361 void Graphic3d_ArrayOfPrimitives::SetVertexNormal (const Standard_Integer theIndex,
362                                                    const gp_Dir&          theNormal)
363 {
364   SetVertexNormal (theIndex, theNormal.X(), theNormal.Y(), theNormal.Z());
365 }
366
367 void Graphic3d_ArrayOfPrimitives::SetVertexTexel (const Standard_Integer theIndex,
368                                                   const gp_Pnt2d&        theTexel)
369 {
370   SetVertexTexel (theIndex, theTexel.X(), theTexel.Y());
371 }
372
373 void Graphic3d_ArrayOfPrimitives::SetBoundColor (const Standard_Integer theIndex,
374                                                  const Quantity_Color&  theColor)
375 {
376   SetBoundColor (theIndex, theColor.Red(), theColor.Green(), theColor.Blue());
377 }
378
379 Standard_CString Graphic3d_ArrayOfPrimitives::StringType() const
380 {
381   switch (myType)
382   {
383     case Graphic3d_TOPA_POINTS:           return "ArrayOfPoints";
384     case Graphic3d_TOPA_POLYLINES:        return "ArrayOfPolylines";
385     case Graphic3d_TOPA_SEGMENTS:         return "ArrayOfSegments";
386     case Graphic3d_TOPA_POLYGONS:         return "ArrayOfPolygons";
387     case Graphic3d_TOPA_TRIANGLES:        return "ArrayOfTriangles";
388     case Graphic3d_TOPA_QUADRANGLES:      return "ArrayOfQuadrangles";
389     case Graphic3d_TOPA_TRIANGLESTRIPS:   return "ArrayOfTriangleStrips";
390     case Graphic3d_TOPA_QUADRANGLESTRIPS: return "ArrayOfQuadrangleStrips";
391     case Graphic3d_TOPA_TRIANGLEFANS:     return "ArrayOfTriangleFans";
392     case Graphic3d_TOPA_UNDEFINED:        return "UndefinedArray";
393   }
394   return "UndefinedArray";
395 }
396
397 gp_Pnt Graphic3d_ArrayOfPrimitives::Vertice (const Standard_Integer theRank) const
398 {
399   Standard_Real anXYZ[3];
400   Vertice (theRank, anXYZ[0], anXYZ[1], anXYZ[2]);
401   return gp_Pnt (anXYZ[0], anXYZ[1], anXYZ[2]);
402 }
403
404 Quantity_Color Graphic3d_ArrayOfPrimitives::VertexColor (const Standard_Integer theRank) const
405 {
406   Standard_Real anRGB[3];
407   VertexColor (theRank, anRGB[0], anRGB[1], anRGB[2]);
408   return Quantity_Color (anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB);
409 }
410
411 gp_Dir Graphic3d_ArrayOfPrimitives::VertexNormal (const Standard_Integer theRank) const
412 {
413   Standard_Real anXYZ[3];
414   VertexNormal (theRank, anXYZ[0], anXYZ[1], anXYZ[2]);
415   return gp_Dir (anXYZ[0], anXYZ[1], anXYZ[2]);
416 }
417
418 gp_Pnt2d Graphic3d_ArrayOfPrimitives::VertexTexel (const Standard_Integer theRank) const
419 {
420   Standard_Real anXY[2];
421   VertexTexel (theRank, anXY[0], anXY[1]);
422   return gp_Pnt2d (anXY[0], anXY[1]);
423 }
424
425 Quantity_Color Graphic3d_ArrayOfPrimitives::BoundColor (const Standard_Integer theRank) const
426 {
427   Standard_Real anRGB[3] = {0.0, 0.0, 0.0};
428   BoundColor (theRank, anRGB[0], anRGB[1], anRGB[2]);
429   return Quantity_Color (anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB);
430 }
431
432 Standard_Integer Graphic3d_ArrayOfPrimitives::ItemNumber() const
433 {
434   if (myAttribs.IsNull())
435   {
436     return -1;
437   }
438
439   switch (myType)
440   {
441     case Graphic3d_TOPA_POINTS:           return myAttribs->NbElements;
442     case Graphic3d_TOPA_POLYLINES:
443     case Graphic3d_TOPA_POLYGONS:         return !myBounds.IsNull() ? myBounds->NbBounds : 1;
444     case Graphic3d_TOPA_SEGMENTS:         return myIndices.IsNull() || myIndices->NbElements < 1
445                                                ? myAttribs->NbElements / 2
446                                                : myIndices->NbElements / 2;
447     case Graphic3d_TOPA_TRIANGLES:        return myIndices.IsNull() || myIndices->NbElements < 1
448                                                ? myAttribs->NbElements / 3
449                                                : myIndices->NbElements / 3;
450     case Graphic3d_TOPA_QUADRANGLES:      return myIndices.IsNull() || myIndices->NbElements < 1
451                                                ? myAttribs->NbElements / 4
452                                                : myIndices->NbElements / 4;
453     case Graphic3d_TOPA_TRIANGLESTRIPS:   return !myBounds.IsNull()
454                                                ? myAttribs->NbElements - 2 * myBounds->NbBounds
455                                                : myAttribs->NbElements - 2;
456     case Graphic3d_TOPA_QUADRANGLESTRIPS: return !myBounds.IsNull()
457                                                ? myAttribs->NbElements / 2 - myBounds->NbBounds
458                                                : myAttribs->NbElements / 2 - 1;
459     case Graphic3d_TOPA_TRIANGLEFANS:     return !myBounds.IsNull()
460                                                ? myAttribs->NbElements - 2 * myBounds->NbBounds
461                                                : myAttribs->NbElements - 2;
462     case Graphic3d_TOPA_UNDEFINED:        return -1;
463   }
464   return -1;
465 }
466
467 void Graphic3d_ArrayOfPrimitives::ComputeVNormals (const Standard_Integer theFrom,
468                                                    const Standard_Integer theTo)
469 {
470   Standard_Integer aNext = theFrom + 1;
471   Standard_Integer aLast = theTo   + 1;
472   gp_Pnt aTri[3];
473   if (myMaxEdges > 0)
474   {
475     aTri[0] = Vertice (Edge (aNext++));
476     aTri[1] = Vertice (Edge (aNext++));
477   }
478   else
479   {
480     aTri[0] = Vertice (aNext++);
481     aTri[1] = Vertice (aNext++);
482   }
483
484   gp_Vec vn;
485   while (aNext <= aLast)
486   {
487     if (myMaxEdges > 0)
488     {
489       aTri[2] = Vertice (Edge (aNext));
490     }
491     else
492     {
493       aTri[2] = Vertice (aNext);
494     }
495     gp_Vec v21 (aTri[1], aTri[0]);
496     gp_Vec v31 (aTri[2], aTri[0]);
497     vn = v21 ^ v31;
498     if (vn.SquareMagnitude() > 0.0)
499     {
500       break;
501     }
502     aNext++;
503   }
504
505   if (aNext > aLast)
506   {
507     return;
508   }
509
510   vn.Normalize();
511   if (myMaxEdges > 0)
512   {
513     for (int i = theFrom + 1; i <= theTo + 1; i++)
514     {
515       SetVertexNormal (Edge (i), vn);
516     }
517   }
518   else
519   {
520     for (int i = theFrom + 1; i <= theTo + 1; i++)
521     {
522       SetVertexNormal (i, vn);
523     }
524   }
525 }
526
527 Standard_Boolean Graphic3d_ArrayOfPrimitives::IsValid()
528 {
529   if (myAttribs.IsNull())
530   {
531     return Standard_False;
532   }
533
534   Standard_Integer nvertexs = myAttribs->NbElements;
535   Standard_Integer nbounds  = myBounds.IsNull()  ? 0 : myBounds->NbBounds;
536   Standard_Integer nedges   = myIndices.IsNull() ? 0 : myIndices->NbElements;
537   switch (myType)
538   {
539     case Graphic3d_TOPA_POINTS:
540       if (nvertexs < 1)
541       {
542         return Standard_False;
543       }
544       break;
545     case Graphic3d_TOPA_POLYLINES:
546       if (nedges > 0
547        && nedges < 2)
548       {
549         return Standard_False;
550       }
551       if (nvertexs < 2)
552       {
553         return Standard_False;
554       }
555       break;
556     case Graphic3d_TOPA_SEGMENTS:
557       if (nvertexs < 2)
558       {
559         return Standard_False;
560       }
561       break;
562     case Graphic3d_TOPA_POLYGONS:
563       if (nedges > 0
564        && nedges < 3)
565       {
566         return Standard_False;
567       }
568       if (nvertexs < 3)
569       {
570         return Standard_False;
571       }
572       break;
573     case Graphic3d_TOPA_TRIANGLES:
574       if (nedges > 0)
575       {
576         if (nedges < 3
577          || nedges % 3 != 0)
578         {
579           if (nedges <= 3)
580           {
581             return Standard_False;
582           }
583           myIndices->NbElements = 3 * (nedges / 3);
584         }
585       }
586       else if (nvertexs < 3
587             || nvertexs % 3 != 0 )
588       {
589         if (nvertexs <= 3)
590         {
591           return Standard_False;
592         }
593         myAttribs->NbElements = 3 * (nvertexs / 3);
594       }
595       break;
596     case Graphic3d_TOPA_QUADRANGLES:
597       if (nedges > 0)
598       {
599         if (nedges < 4
600          || nedges % 4 != 0)
601         {
602           if (nedges <= 4)
603           {
604             return Standard_False;
605           }
606           myIndices->NbElements = 4 * (nedges / 4);
607         }
608       }
609       else if (nvertexs < 4
610             || nvertexs % 4 != 0)
611       {
612         if (nvertexs <= 4)
613         {
614           return Standard_False;
615         }
616         myAttribs->NbElements = 4 * (nvertexs / 4);
617       }
618       break;
619     case Graphic3d_TOPA_TRIANGLEFANS:
620     case Graphic3d_TOPA_TRIANGLESTRIPS:
621       if (nvertexs < 3)
622       {
623         return Standard_False;
624       }
625       break;
626     case Graphic3d_TOPA_QUADRANGLESTRIPS:
627       if (nvertexs < 4)
628       {
629         return Standard_False;
630       }
631       break;
632     case Graphic3d_TOPA_UNDEFINED:
633     default:
634       return Standard_False;
635   }
636
637   // total number of edges(vertices) in bounds should be the same as variable
638   // of total number of defined edges(vertices); if no edges - only vertices
639   // could be in bounds.
640   if (nbounds > 0)
641   {
642     Standard_Integer n = 0;
643     for (Standard_Integer aBoundIter = 0; aBoundIter < nbounds; ++aBoundIter)
644     {
645       n += myBounds->Bounds[aBoundIter];
646     }
647     if (nedges > 0
648      && n != nedges)
649     {
650       if (nedges <= n)
651       {
652         return Standard_False;
653       }
654       myIndices->NbElements = n;
655     }
656     else if (nedges == 0
657           && n != nvertexs)
658     {
659       if (nvertexs <= n)
660       {
661         return Standard_False;
662       }
663       myAttribs->NbElements = n;
664     }
665   }
666
667   // check that edges (indexes to an array of vertices) are in range.
668   if (nedges > 0)
669   {
670     for (Standard_Integer anEdgeIter = 0; anEdgeIter < nedges; ++anEdgeIter)
671     {
672       if (myIndices->Index (anEdgeIter) >= myAttribs->NbElements)
673       {
674         return Standard_False;
675       }
676     }
677   }
678   return Standard_True;
679 }