1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
18 
19 bool
IsValidVertexTopology(int vertex_index,ON_TextLog * text_log) const20 ON_Brep::IsValidVertexTopology( int vertex_index, ON_TextLog* text_log ) const
21 {
22   if ( vertex_index < 0 || vertex_index >= m_V.Count() )
23   {
24     if ( text_log )
25       text_log->Print("brep vertex_index = %d (should be >=0 and <%d=brep.m_V.Count() ).\n",
26                       vertex_index, m_V.Count());
27     return false;
28   }
29   const ON_BrepVertex& vertex = m_V[vertex_index];
30   if ( vertex.m_vertex_index != vertex_index )
31   {
32     if ( text_log )
33     {
34       text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
35       text_log->PushIndent();
36       text_log->Print("vertex.m_vertex_index = %d (should be %d).\n",
37                        vertex.m_vertex_index, vertex_index );
38       text_log->PopIndent();
39     }
40     return false;
41   }
42 
43   const int vertex_edge_count = vertex.m_ei.Count();
44   int i, j, vei, ei;
45   for ( vei = 0; vei < vertex_edge_count; vei++ )
46   {
47     ei = vertex.m_ei[vei];
48 
49     if ( ei < 0 || ei >= m_E.Count() )
50     {
51       if ( text_log )
52       {
53         text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
54         text_log->PushIndent();
55         text_log->Print("vertex.m_ei[%d] = %d (should be >=0 and <%d).\n", vei, ei, m_E.Count());
56         text_log->PopIndent();
57       }
58       return false;
59     }
60 
61     const ON_BrepEdge& edge = m_E[ei];
62 
63     if ( ei != edge.m_edge_index )
64     {
65       if ( text_log )
66       {
67         text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
68         text_log->PushIndent();
69         text_log->Print("vertex.m_ei[%d] = %d is a deleted edge.\n", vei, ei);
70         text_log->PopIndent();
71       }
72       return false;
73     }
74 
75     if ( edge.m_vi[0] != vertex_index && edge.m_vi[1] != vertex_index )
76     {
77       if ( text_log )
78       {
79         text_log->Print("brep.m_V[%d] vertex or brep.m_E[%d] edge is not valid.\n",vertex_index,ei);
80         text_log->PushIndent();
81         text_log->Print("vertex.m_ei[%d] = %d but brep.m_E[%d].m_vi[] = [%d,%d]. "
82                         "At least one edge m_vi[] value should be %d.\n",
83                         vei,ei,ei,edge.m_vi[0],edge.m_vi[1],vertex_index);
84         text_log->PopIndent();
85       }
86       return false;
87     }
88 
89     for ( i = 0; i < vei; i++ )
90     {
91       if ( vertex.m_ei[i] == ei )
92       {
93         // edge should be closed
94         if ( edge.m_vi[0] != vertex_index || edge.m_vi[1] != vertex_index )
95         {
96           if ( text_log )
97           {
98             text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
99             text_log->PushIndent();
100             text_log->Print("vertex.m_ei[%d] and vertex.m_ei[%d] = %d but brep.m_E[%d].m_vi[0] = %d",
101                              i,vei,ei,ei,edge.m_vi[0]);
102             text_log->Print("and ON_Brep.m_E[%d].m_vi[1] = %d (both m_vi[] values should be %d).\n",
103                             ei,edge.m_vi[1],vertex_index);
104             text_log->PopIndent();
105           }
106           return false;
107         }
108         for (j = i+1; j < vei; j++ )
109         {
110           if ( vertex.m_ei[j] == ei )
111           {
112             if ( text_log )
113             {
114               text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
115               text_log->PushIndent();
116               text_log->Print("vertex.m_ei[%d,%d,%d] = %d. An open edge index should appear once\n",i,vei,j,ei);
117               text_log->Print("in vertex.m_ei[] and a closed edge index should appear twice.\n");
118               text_log->PopIndent();
119             }
120             return false;
121           }
122         }
123         break;
124       }
125     }
126 
127   }
128 
129   return true;
130 }
131 
132 bool
IsValidFaceTopology(int face_index,ON_TextLog * text_log) const133 ON_Brep::IsValidFaceTopology( int face_index, ON_TextLog* text_log  ) const
134 {
135   if ( face_index < 0 || face_index >= m_F.Count() )
136   {
137     if ( text_log )
138     {
139       text_log->Print("brep face_index = %d (should be >=0 and <%d=brep.m_F.Count()).\n",
140                       face_index, m_F.Count());
141     }
142     return false;
143   }
144   const ON_BrepFace& face = m_F[face_index];
145   if ( face.m_face_index != face_index )
146   {
147     if ( text_log )
148     {
149       text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
150       text_log->PushIndent();
151       text_log->Print("face.m_face_index = %d (should be %d).\n",
152                        face.m_face_index, face_index );
153       text_log->PopIndent();
154     }
155     return false;
156   }
157   if ( face.m_brep != this )
158   {
159     if ( text_log )
160     {
161       text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
162       text_log->PushIndent();
163       text_log->Print("face.m_brep does not point to parent brep.\n");
164       text_log->PopIndent();
165     }
166     return false;
167   }
168 
169   const int face_loop_count = face.m_li.Count();
170   if ( face_loop_count <= 0 )
171   {
172     if ( text_log )
173     {
174       text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
175       text_log->PushIndent();
176       text_log->Print("face.m_li.Count() <= 0 (should be >= 1)\n");
177       text_log->PopIndent();
178     }
179     return false;
180   }
181 
182   int i, fli, li;
183   for ( fli = 0; fli < face_loop_count; fli++ )
184   {
185     li = face.m_li[fli];
186     for ( i = 0; i < fli; i++ )
187     {
188       if ( face.m_li[i] == li )
189       {
190         if ( text_log )
191         {
192           text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
193           text_log->PushIndent();
194           text_log->Print("face.m_li[%d]=face.m_li[%d]=%d (a loop index should appear once in face.m_li[])\n",
195                           fli,i,li);
196           text_log->PopIndent();
197         }
198         return false;
199       }
200     }
201     if ( !IsValidLoop( li, text_log ) )
202     {
203       if ( text_log )
204       {
205         text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
206         text_log->PushIndent();
207         text_log->Print("brep.m_L[face.m_li[%d]=%d] is not valid.\n",fli,li);
208         text_log->PopIndent();
209       }
210       return false;
211     }
212     const ON_BrepLoop& loop = m_L[li];
213     if ( loop.m_loop_index != li )
214     {
215       if ( text_log )
216       {
217         text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
218         text_log->PushIndent();
219         text_log->Print("face.m_li[%d]=%d is a deleted loop\n",
220                         fli,li);
221         text_log->PopIndent();
222       }
223       return false;
224     }
225     if ( loop.m_fi != face_index )
226     {
227       if ( text_log )
228       {
229         text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
230         text_log->PushIndent();
231         text_log->Print("face.m_li[%d]=%d but brep.m_L[%d].m_fi=%d (m_fi should be %d)\n",
232                         fli,li,li,loop.m_fi,face_index);
233         text_log->PopIndent();
234       }
235       return false;
236     }
237     if ( fli == 0 ) {
238       if ( loop.m_type != ON_BrepLoop::outer )
239       {
240         if ( text_log )
241         {
242           text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
243           text_log->PushIndent();
244           text_log->Print("brep.m_L[face.m_li[0]=%d].m_type is not outer.\n",li);
245           text_log->PopIndent();
246         }
247         return false;
248       }
249     }
250     else {
251       if ( loop.m_type != ON_BrepLoop::inner )
252       {
253         if ( text_log )
254         {
255           text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
256           text_log->PushIndent();
257           text_log->Print("brep.m_L[face.m_li[%d]=%d].m_type is not inner.\n",fli,li);
258           text_log->PopIndent();
259         }
260         return false;
261       }
262     }
263   }
264 
265   const int si = face.m_si;
266   if ( si < 0 || si >= m_S.Count() )
267   {
268     if ( text_log )
269     {
270       text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
271       text_log->PushIndent();
272       text_log->Print("face.m_si=%d (should be >=0 and <%d=m_S.Count())\n",
273                       face.m_si,m_S.Count());
274       text_log->PopIndent();
275     }
276     return false;
277   }
278 
279   if ( 0 == m_S[si] )
280   {
281     if ( text_log )
282     {
283       text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
284       text_log->PushIndent();
285       text_log->Print("brep.m_S[face.m_si=%d] is NULL\n",face.m_si);
286       text_log->PopIndent();
287     }
288     return false;
289   }
290 
291   if ( 0 == face.ProxySurface() )
292   {
293     if ( text_log )
294     {
295       text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
296       text_log->PushIndent();
297       text_log->Print("face.ProxySurface() is NULL\n");
298       text_log->PopIndent();
299     }
300     return false;
301   }
302 
303   if ( m_S[si] != face.ProxySurface() )
304   {
305     if ( text_log )
306     {
307       text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
308       text_log->PushIndent();
309       text_log->Print("brep.m_S[face.m_si=%d] != face.ProxySurface().\n",si);
310       text_log->PopIndent();
311     }
312     return false;
313   }
314 
315   if ( face.ProxySurfaceIsTransposed() )
316   {
317     if ( text_log )
318     {
319       text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
320       text_log->PushIndent();
321       text_log->Print("face.ProxySurfaceIsTransposed() is true.\n");
322       text_log->PopIndent();
323     }
324     return false;
325   }
326 
327   return true;
328 }
329 
330 bool
IsValidEdgeTopology(int edge_index,ON_TextLog * text_log) const331 ON_Brep::IsValidEdgeTopology( int edge_index, ON_TextLog* text_log ) const
332 {
333   if ( edge_index < 0 || edge_index >= m_E.Count() )
334   {
335     if ( text_log )
336       text_log->Print("brep edge_index = %d (should be >=0 and <%d=brep.m_E.Count() ).\n",
337                       edge_index, m_E.Count());
338     return false;
339   }
340   const ON_BrepEdge& edge = m_E[edge_index];
341   if ( edge.m_edge_index != edge_index )
342   {
343     if ( text_log )
344     {
345       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
346       text_log->PushIndent();
347       text_log->Print("edge.m_edge_index = %d (should be %d).\n",
348                        edge.m_edge_index, edge_index );
349       text_log->PopIndent();
350     }
351     return false;
352   }
353   if ( edge.m_brep != this )
354   {
355     if ( text_log )
356     {
357       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
358       text_log->PushIndent();
359       text_log->Print("edge.m_brep does not point to parent brep\n");
360       text_log->PopIndent();
361     }
362     return false;
363   }
364 
365   if ( !edge.IsValid(text_log) )
366   {
367     if ( text_log )
368     {
369       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
370       text_log->PushIndent();
371       text_log->Print("edge is not a valid.\n");
372       text_log->PopIndent();
373     }
374     return false;
375   }
376 
377   // This checks to make sure that m_C3[] and the edge's proxy information is valid.
378   // This isn't exactly "topology", but if this stuff isn't set right, then the
379   // "geometry" checks might crash.
380 
381   const int c3i = edge.m_c3i;
382   if ( c3i < 0 || c3i >= m_C3.Count() )
383   {
384     if ( text_log )
385     {
386       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
387       text_log->PushIndent();
388       text_log->Print("edge.m_c3i = %d (should be >=0 and <%d=m_C3.Count()\n",
389                       edge.m_c3i,m_C3.Count() );
390       text_log->PopIndent();
391     }
392     return false;
393   }
394 
395   if ( 0 == m_C3[c3i] )
396   {
397     if ( text_log )
398       text_log->Print("ON_Brep.m_E[%d].m_c3i = %d, but m_C3[%d] is NULL.\n",edge_index,c3i,c3i);
399     return false;
400   }
401 
402   if ( 0 == edge.ProxyCurve() )
403   {
404     if ( text_log )
405       text_log->Print("brep.m_E[%d].m_c3i = %d, but edge.ProxyCurve() is NULL.\n",edge_index,c3i);
406     return false;
407   }
408 
409   if ( m_C3[c3i] != edge.ProxyCurve() )
410   {
411     if ( text_log )
412     {
413       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
414       text_log->PushIndent();
415       text_log->Print("m_E[%d].m_c3i=%d, m_C3[%d] != m_E[%d].ProxyCurve()\n",edge_index,c3i,c3i,edge_index);
416       text_log->PopIndent();
417     }
418     return false;
419   }
420 
421   ON_Interval proxy_sub_dom = edge.ProxyCurveDomain();
422   if ( !proxy_sub_dom.IsIncreasing() )
423   {
424     if ( text_log )
425     {
426       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
427       text_log->PushIndent();
428       text_log->Print("m_E[%d].ProxyCurveDomain() = (%g,%g) is not increasing\n",edge_index,proxy_sub_dom[0],proxy_sub_dom[1]);
429       text_log->PopIndent();
430     }
431     return false;
432   }
433 
434   ON_Interval c3_dom = m_C3[c3i]->Domain();
435   if ( !c3_dom.Includes(proxy_sub_dom) )
436   {
437     if ( text_log )
438     {
439       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
440       text_log->PushIndent();
441       text_log->Print("m_C3[%d].Domain() = (%g,%g) does not inlclude m_E[%d].ProxyCurveDomain() = (%g,%g) is not increasing\n",
442                       c3i,c3_dom[0],c3_dom[1],edge_index,proxy_sub_dom[0],proxy_sub_dom[1]);
443       text_log->PopIndent();
444     }
445     return false;
446   }
447 
448   ON_Interval edge_dom = edge.Domain();
449   if ( !edge_dom.IsIncreasing() )
450   {
451     if ( text_log )
452     {
453       text_log->Print("brep.m_E[%d] trim is not valid.\n",edge_index);
454       text_log->PushIndent();
455       text_log->Print("m_E[%d].Domain() = (%g,%g) is not increasing\n",edge_index,edge_dom[0],edge_dom[1]);
456       text_log->PopIndent();
457     }
458     return false;
459   }
460 
461 
462 
463   const int vi0 = edge.m_vi[0];
464   const int vi1 = edge.m_vi[1];
465   if ( vi0 < 0 || vi0 >= m_V.Count() )
466   {
467     if ( text_log )
468     {
469       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
470       text_log->PushIndent();
471       text_log->Print("edge.m_vi[0]=%d (should be >=0 and <%d=m_V.Count()\n",
472                        vi0, m_V.Count() );
473       text_log->PopIndent();
474     }
475     return false;
476   }
477   if ( vi1 < 0 || vi1 >= m_V.Count() )
478   {
479     if ( text_log )
480     {
481       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
482       text_log->PushIndent();
483       text_log->Print("edge.m_vi[1]=%d (should be >=0 and <%d=m_V.Count()\n",
484                        vi1, m_V.Count() );
485       text_log->PopIndent();
486     }
487     return false;
488   }
489   int evi;
490   for ( evi = 0; evi < 2; evi++ )
491   {
492     const ON_BrepVertex& vertex = m_V[edge.m_vi[evi]];
493 
494     if ( edge.m_vi[evi] != vertex.m_vertex_index )
495     {
496       if ( text_log )
497       {
498         text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
499         text_log->PushIndent();
500         text_log->Print("edge.m_vi[%d]=%d is a deleted vertex\n",
501                          evi,edge.m_vi[evi] );
502         text_log->PopIndent();
503       }
504       return false;
505     }
506 
507 
508     const int vertex_edge_count = vertex.m_ei.Count();
509     ON_BOOL32 bFoundIt = false;
510     int vei;
511     for ( vei = 0; vei < vertex_edge_count && !bFoundIt; vei++ )
512     {
513       bFoundIt = (vertex.m_ei[vei] == edge_index);
514     }
515     if ( !bFoundIt )
516     {
517       if ( text_log )
518       {
519         text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
520         text_log->PushIndent();
521         text_log->Print("edge.m_vi[%d]=%d but edge is not referenced in m_V[%d].m_ei[]\n",
522                          evi,edge.m_vi[evi],edge.m_vi[evi] );
523         text_log->PopIndent();
524       }
525       return false;
526     }
527   }
528 
529   const int edge_trim_count = edge.m_ti.Count();
530   if ( edge_trim_count < 0 )
531   {
532     if ( text_log )
533     {
534       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
535       text_log->PushIndent();
536       text_log->Print("edge.m_ti.Count() < 0\n");
537       text_log->PopIndent();
538     }
539     return false;
540   }
541   int i, eti, ti;
542   for (eti = 0; eti < edge_trim_count; eti++ )
543   {
544     ti = edge.m_ti[eti];
545     if ( ti < 0 || ti >= m_T.Count() )
546     {
547       if ( text_log )
548       {
549         text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
550         text_log->PushIndent();
551         text_log->Print("edge.m_ti[%d]=%d (should be >=0 and <%d=m_T.Count())\n",eti,ti);
552         text_log->PopIndent();
553       }
554       return false;
555     }
556     if ( m_T[ti].m_trim_index != ti )
557     {
558       if ( text_log )
559       {
560         text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
561         text_log->PushIndent();
562         text_log->Print("edge.m_ti[%d]=%d is a deleted trim\n",eti,ti);
563         text_log->PopIndent();
564       }
565       return false;
566     }
567     for ( i = 0; i < eti; i++ )
568     {
569       if ( edge.m_ti[i] == ti )
570       {
571         if ( text_log )
572         {
573           text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
574           text_log->PushIndent();
575           text_log->Print("edge.m_ti[%d]=edge.m_ti[%d]=%d (a trim should be referenced once).\n",i,eti,ti);
576           text_log->PopIndent();
577         }
578         return false;
579       }
580     }
581     const ON_BrepTrim& trim = m_T[ti];
582     if ( trim.m_ei != edge_index )
583     {
584       if ( text_log )
585       {
586         text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
587         text_log->PushIndent();
588         text_log->Print("edge.m_ti[%d]=%d but brep.m_T[%d].m_ei=%d\n",eti,ti,ti,trim.m_ei);
589         text_log->PopIndent();
590       }
591       return false;
592     }
593   }
594 
595   return true;
596 }
597 
598 bool
IsValidLoopTopology(int loop_index,ON_TextLog * text_log) const599 ON_Brep::IsValidLoopTopology( int loop_index, ON_TextLog* text_log ) const
600 {
601   int lti, ti;
602 
603   if ( loop_index < 0 || loop_index >= m_L.Count() )
604   {
605     if ( text_log )
606       text_log->Print("brep loop_index = %d (should be >=0 and <%d=brep.m_L.Count() ).\n",
607                       loop_index, m_L.Count());
608     return false;
609   }
610   const ON_BrepLoop& loop = m_L[loop_index];
611   if ( loop.m_loop_index != loop_index )
612   {
613     if ( text_log )
614     {
615       text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
616       text_log->PushIndent();
617       text_log->Print("loop.m_loop_index = %d (should be %d).\n",
618                        loop.m_loop_index, loop_index );
619       text_log->PopIndent();
620     }
621     return false;
622   }
623   if ( loop.m_brep != this )
624   {
625     if ( text_log )
626     {
627       text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
628       text_log->PushIndent();
629       text_log->Print("loop.m_brep does not point to parent brep\n");
630       text_log->PopIndent();
631     }
632     return false;
633   }
634 
635   if ( loop.m_fi < 0 || loop.m_fi >= m_F.Count() )
636   {
637     if ( text_log )
638       text_log->Print("ON_Brep.m_L[%d].m_fi = %d is not invalid.\n",loop_index,loop.m_fi);
639     return false;
640   }
641   if ( m_F[loop.m_fi].m_face_index != loop.m_fi )
642   {
643     if ( text_log )
644       text_log->Print("ON_Brep.m_L[%d].m_fi = %d is a deleted face.\n",loop_index,loop.m_fi);
645     return false;
646   }
647   if ( loop.m_ti.Count() < 1 )
648   {
649       if ( text_log )
650         text_log->Print("ON_Brep.m_L[%d].m_ti.Count() = %d  (should be > 0 )\n",loop_index,loop.m_ti.Count());
651       return false;
652   }
653 
654   for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
655   {
656     ti = loop.m_ti[lti];
657     if ( ti < 0 || ti >= m_T.Count() )
658     {
659       if ( text_log )
660         text_log->Print("ON_Brep.m_L[%d].m_ti[%d] = %d is not invalid.\n",loop_index,lti,ti);
661       return false;
662     }
663     const ON_BrepTrim& trim = m_T[ti];
664     if ( trim.m_trim_index != ti )
665     {
666       if ( text_log )
667         text_log->Print("ON_Brep.m_L[%d].m_ti[%d] = %d is a deleted trim.\n",loop_index,lti,ti);
668       return false;
669     }
670     if ( trim.m_li != loop_index )
671     {
672       if ( text_log )
673       {
674         text_log->Print("brep loop m_L[%d] or trim m_T[%d] is not valid.\n",loop_index,ti);
675         text_log->PushIndent();
676         text_log->Print("loop.m_ti[%d] = %d != %d =trim.m_li\n",lti,ti,trim.m_li);
677         text_log->PopIndent();
678       }
679       return false;
680     }
681   }
682 
683 
684   int first_trim_ti = -4;
685   int first_trim_vi0 = -3;
686   int prev_trim_vi1 = -2;
687   int prev_trim_ti=-9;
688   for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
689   {
690     const ON_BrepTrim& trim = m_T[loop.m_ti[lti]];
691     if ( 0 == lti )
692     {
693       first_trim_ti = loop.m_ti[lti];
694       first_trim_vi0 = trim.m_vi[0];
695     }
696     else if ( prev_trim_vi1 != trim.m_vi[0] )
697     {
698       // 23 May 2003 Dale Lear
699       //     Added this test to make sure adjacent trims
700       //     in a loop shared vertices.
701       if ( text_log )
702       {
703          text_log->Print("brep loop m_L[%d] is not valid.\n",loop_index);
704          text_log->PushIndent();
705          text_log->Print("m_T[loop.m_ti[%d]=%d].m_vi[1] = %d != m_T[loop.m_ti[%d]=%d].m_vi[0]=%d.\n",
706                           lti-1,prev_trim_ti,prev_trim_vi1,lti,loop.m_ti[lti],trim.m_vi[0]);
707          text_log->PopIndent();
708       }
709       return false;
710     }
711     prev_trim_ti = loop.m_ti[lti];
712     prev_trim_vi1 = trim.m_vi[1];
713   }
714 
715   if ( first_trim_ti >= 0 && first_trim_vi0 != prev_trim_vi1 )
716   {
717     // 23 May 2003 Dale Lear
718     //     Added this test to make sure adjacent trims
719     //     in a loop shared vertices.
720     if ( text_log )
721     {
722        text_log->Print("brep loop m_L[%d] is not valid.\n",loop_index);
723        text_log->PushIndent();
724        text_log->Print("m_T[loop.m_ti[%d]=%d].m_vi[1] = %d != m_T[loop.m_ti[0]=%d].m_vi[0]=%d.\n",
725                         loop.m_ti.Count()-1,prev_trim_ti,prev_trim_vi1,first_trim_ti,first_trim_vi0);
726        text_log->PopIndent();
727     }
728     return false;
729   }
730 
731 
732   return true;
733 }
734 
735 bool
IsValidTrimTopology(int trim_index,ON_TextLog * text_log) const736 ON_Brep::IsValidTrimTopology( int trim_index, ON_TextLog* text_log ) const
737 {
738   if ( trim_index < 0 || trim_index >= m_T.Count() )
739   {
740     if ( text_log )
741       text_log->Print("brep trim_index = %d (should be >=0 and <%d=brep.m_T.Count() ).\n",
742                       trim_index, m_T.Count());
743     return false;
744   }
745   const ON_BrepTrim& trim = m_T[trim_index];
746   if ( trim.m_trim_index != trim_index )
747   {
748     if ( text_log )
749     {
750       text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
751       text_log->PushIndent();
752       text_log->Print("trim.m_trim_index = %d (should be %d).\n",
753                        trim.m_trim_index, trim_index );
754       text_log->PopIndent();
755     }
756     return false;
757   }
758   if ( trim.m_brep != this )
759   {
760     if ( text_log )
761     {
762       text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
763       text_log->PushIndent();
764       text_log->Print("trim.m_brep does not point to parent brep\n");
765       text_log->PopIndent();
766     }
767     return false;
768   }
769 
770   if ( trim.m_vi[0] < 0 || trim.m_vi[0] >= m_V.Count() )
771   {
772     if ( text_log )
773       text_log->Print("ON_Brep.m_T[%d].m_vi[0] = %d is not invalid.\n",trim_index,trim.m_vi[0]);
774     return false;
775   }
776   if ( trim.m_vi[1] < 0 || trim.m_vi[1] >= m_V.Count() )
777   {
778     if ( text_log )
779       text_log->Print("ON_Brep.m_T[%d].m_vi[1] = %d is not invalid.\n",trim_index,trim.m_vi[1]);
780     return false;
781   }
782 
783   if ( m_V[trim.m_vi[0]].m_vertex_index != trim.m_vi[0] )
784   {
785     if ( text_log )
786       text_log->Print("ON_Brep.m_T[%d].m_vi[0] is deleted.\n",trim_index);
787     return false;
788   }
789   if ( m_V[trim.m_vi[1]].m_vertex_index != trim.m_vi[1] )
790   {
791     if ( text_log )
792       text_log->Print("ON_Brep.m_T[%d].m_vi[1] is deleted.\n",trim_index);
793     return false;
794   }
795 
796   if ( trim.m_c2i < 0 || trim.m_c2i >= m_C2.Count() )
797   {
798     if ( text_log )
799       text_log->Print("ON_Brep.m_T[%d].m_c2i = %d is not valid.\n",trim_index,trim.m_c2i);
800     return false;
801   }
802 
803   if ( 0 == m_C2[trim.m_c2i] )
804   {
805     if ( text_log )
806       text_log->Print("ON_Brep.m_T[%d].m_c2i = %d, but m_C2[%d] is NULL.\n",trim_index,trim.m_c2i,trim.m_c2i);
807     return false;
808   }
809 
810   if ( 0 == trim.ProxyCurve() )
811   {
812     if ( text_log )
813       text_log->Print("brep.m_T[%d].m_c2i = %d, but trim.ProxyCurve() is NULL.\n",trim_index,trim.m_c2i);
814     return false;
815   }
816 
817   if ( m_C2[trim.m_c2i] != trim.ProxyCurve() )
818   {
819     if ( text_log )
820     {
821       text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
822       text_log->PushIndent();
823       text_log->Print("m_T[%d].m_c2i=%d, m_C2[%d] != m_T[%d].ProxyCurve()\n",
824                       trim_index, trim.m_c2i, trim.m_c2i, trim_index);
825       text_log->PopIndent();
826     }
827     return false;
828   }
829 
830   ON_Interval proxy_sub_dom = trim.ProxyCurveDomain();
831   if ( !proxy_sub_dom.IsIncreasing() )
832   {
833     if ( text_log )
834     {
835       text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
836       text_log->PushIndent();
837       text_log->Print("m_T[%d].ProxyCurveDomain() = (%g,%g) is not increasing\n",trim_index,proxy_sub_dom[0],proxy_sub_dom[1]);
838       text_log->PopIndent();
839     }
840     return false;
841   }
842 
843   ON_Interval c2_dom = m_C2[trim.m_c2i]->Domain();
844   if ( !c2_dom.Includes(proxy_sub_dom) )
845   {
846     if ( text_log )
847     {
848       text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
849       text_log->PushIndent();
850       text_log->Print("m_C2[%d].Domain() = (%g,%g) does not include m_T[%d].ProxyCurveDomain() = (%g,%g) is not increasing\n",
851                       trim.m_c2i,c2_dom[0],c2_dom[1],
852                       trim_index,proxy_sub_dom[0],proxy_sub_dom[1]);
853       text_log->PopIndent();
854     }
855     return false;
856   }
857 
858   ON_Interval trim_dom = trim.Domain();
859   if ( !trim_dom.IsIncreasing() )
860   {
861     if ( text_log )
862     {
863       text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
864       text_log->PushIndent();
865       text_log->Print("m_T[%d].Domain() = (%g,%g) is not increasing\n",trim_index,trim_dom[0],trim_dom[1]);
866       text_log->PopIndent();
867     }
868     return false;
869   }
870 
871   if ( trim.m_li < 0 || trim.m_li >= m_L.Count() )
872   {
873     if ( text_log )
874       text_log->Print("ON_Brep.m_T[%d].m_li = %d is not valid.\n",trim_index,trim.m_li);
875     return false;
876   }
877 
878   const ON_BrepLoop& loop = m_L[trim.m_li];
879 
880   if ( loop.m_loop_index != trim.m_li )
881   {
882     if ( text_log )
883       text_log->Print("ON_Brep.m_T[%d].m_li = %d is a deleted loop.\n",trim_index,trim.m_li);
884     return false;
885   }
886 
887   bool bFoundTrim = false;
888   int lti, loop_trim_count = loop.m_ti.Count();
889   for ( lti = 0; lti < loop_trim_count && !bFoundTrim; lti++ )
890   {
891     if ( loop.m_ti[lti] == trim_index )
892     {
893       bFoundTrim = true;
894       break;
895     }
896   }
897   if ( !bFoundTrim )
898   {
899     if ( text_log )
900     {
901       text_log->Print("brep.m_T[%d] trim or brep.m_L[%d] loop is not valid.\n",trim_index,trim.m_li);
902       text_log->PushIndent();
903       text_log->Print("trim.m_li = %d but loop.m_ti[] does not contain %d (should appear once in).\n",
904                       trim.m_li,trim_index);
905       text_log->PopIndent();
906     }
907     return false;
908   }
909 
910   if ( trim.m_type == ON_BrepTrim::singular )
911   {
912     // trim has no 3d edge
913     if ( trim.m_ei != -1 )
914     {
915       if ( text_log )
916         text_log->Print("ON_Brep.m_T[%d].m_type = singular, but m_ei = %d (should be -1).\n",trim_index,trim.m_ei);
917       return false;
918     }
919     if ( trim.m_bRev3d )
920     {
921       if ( text_log )
922         text_log->Print("ON_Brep.m_T[%d].m_type = singular, but m_bRev3d = %d (should be 0).\n",trim_index,trim.m_bRev3d);
923       return false;
924     }
925     if ( trim.m_vi[0] != trim.m_vi[1] )
926     {
927       if ( text_log )
928         text_log->Print("ON_Brep.m_T[%d].m_type = singular, but m_vi = (%d,%d) (should be same vertex index).\n",
929                         trim_index,trim.m_vi[0],trim.m_vi[1]);
930       return false;
931     }
932   }
933   else
934   {
935     // trim should be connected to a 3d edge
936     if ( trim.m_ei < 0 || trim.m_ei >= m_E.Count() )
937     {
938       if ( text_log )
939         text_log->Print("ON_Brep.m_T[%d].m_ei = %d is not invalid.\n",trim_index,trim.m_ei);
940       return false;
941     }
942 
943     const ON_BrepEdge& edge = m_E[trim.m_ei];
944     if ( edge.m_edge_index != trim.m_ei )
945     {
946       if ( text_log )
947         text_log->Print("ON_Brep.m_T[%d].m_ei is deleted.\n",trim_index);
948       return false;
949     }
950 
951     const int evi0 = trim.m_bRev3d ? 1 : 0;
952     const int evi1 = trim.m_bRev3d ? 0 : 1;
953     if ( trim.m_vi[0] != edge.m_vi[evi0] )
954     {
955       if ( text_log )
956         text_log->Print("ON_Brep.m_T[%d].m_bRev3d = %d, but m_vi[0] != m_E[m_ei].m_vi[%d].\n",trim_index,trim.m_bRev3d,evi0);
957       return false;
958     }
959     if ( trim.m_vi[1] != edge.m_vi[evi1] )
960     {
961       if ( text_log )
962         text_log->Print("ON_Brep.m_T[%d].m_bRev3d = %d, but m_vi[0] != m_E[m_ei].m_vi[%d].\n",trim_index,trim.m_bRev3d,evi1);
963       return false;
964     }
965   }
966 
967   return true;
968 }
969 
970 bool
IsValidTopology(ON_TextLog * text_log) const971 ON_Brep::IsValidTopology( ON_TextLog* text_log ) const
972 {
973   const int curve2d_count = m_C2.Count();
974   const int curve3d_count = m_C3.Count();
975   const int surface_count = m_S.Count();
976   const int vertex_count  = m_V.Count();
977   const int edge_count    = m_E.Count();
978   const int trim_count    = m_T.Count();
979   const int loop_count    = m_L.Count();
980   const int face_count    = m_F.Count();
981 
982   int vi, ei, fi, ti, li;
983 
984   if ( 0 == face_count && 0 == edge_count && 0 == vertex_count )
985   {
986     if ( text_log )
987       text_log->Print( "ON_Brep has no faces, edges, or vertices\n");
988     return false;
989   }
990 
991   if ( 0 != face_count )
992   {
993     if ( 0 == edge_count )
994     {
995       if ( text_log )
996         text_log->Print( "ON_Brep has no edges.\n");
997       return false;
998     }
999     if ( 0 == loop_count )
1000     {
1001       if ( text_log )
1002         text_log->Print( "ON_Brep has no loops.\n");
1003       return false;
1004     }
1005     if ( 0 == surface_count )
1006     {
1007       if ( text_log )
1008         text_log->Print( "ON_Brep has no surfaces.\n");
1009       return false;
1010     }
1011     if ( 0 == trim_count )
1012     {
1013       if ( text_log )
1014         text_log->Print( "ON_Brep has no trims.\n");
1015       return false;
1016     }
1017     if ( 0 == curve2d_count )
1018     {
1019       if ( text_log )
1020         text_log->Print( "ON_Brep has no 2d curves.\n");
1021       return false;
1022     }
1023   }
1024 
1025   if ( 0 != edge_count )
1026   {
1027     if ( 0 == curve3d_count )
1028     {
1029       if ( text_log )
1030         text_log->Print( "ON_Brep has no 3d curves.\n");
1031       return false;
1032     }
1033     if ( 0 == vertex_count )
1034     {
1035       if ( text_log )
1036         text_log->Print( "ON_Brep has no vertices.\n");
1037       return false;
1038     }
1039   }
1040 
1041   // check element indices match array positions
1042   for ( vi = 0; vi < vertex_count; vi++ )
1043   {
1044     if ( m_V[vi].m_vertex_index == -1 )
1045     {
1046       const ON_BrepVertex& vertex = m_V[vi];
1047       if ( vertex.m_ei.Count() > 0 )
1048       {
1049         if ( text_log )
1050           text_log->Print( "ON_Brep.m_V[%d] is deleted (m_vertex_index = -1) but vertex.m_ei.Count() = %d.\n",
1051                            vi, vertex.m_ei.Count() );
1052         return false;
1053       }
1054     }
1055     else if ( m_V[vi].m_vertex_index != vi )
1056     {
1057       if ( text_log )
1058         text_log->Print( "ON_Brep.m_V[%d].m_vertex_index = %d (should be %d)\n",
1059                          vi, m_V[vi].m_vertex_index, vi );
1060       return false;
1061     }
1062   }
1063 
1064   for ( ei = 0; ei < edge_count; ei++ )
1065   {
1066     if ( m_E[ei].m_edge_index == -1 )
1067     {
1068       const ON_BrepEdge& edge = m_E[ei];
1069       if ( edge.m_ti.Count() > 0 )
1070       {
1071         if ( text_log )
1072           text_log->Print( "ON_Brep.m_E[%d] is deleted (m_edge_index = -1) but edge.m_ei.Count() = %d.\n",
1073                            ei, edge.m_ti.Count() );
1074         return false;
1075       }
1076       if ( edge.m_c3i != -1 )
1077       {
1078         if ( text_log )
1079           text_log->Print( "ON_Brep.m_E[%d] is deleted (m_edge_index = -1) but edge.m_c3i=%d (should be -1).\n",
1080                            ei, edge.m_c3i );
1081         return false;
1082       }
1083       if ( edge.ProxyCurve() )
1084       {
1085         if ( text_log )
1086           text_log->Print( "ON_Brep.m_E[%d] is deleted (m_edge_index = -1) but edge.m_curve is not NULL.\n",
1087                            ei );
1088         return false;
1089       }
1090       if ( edge.m_vi[0] != -1 )
1091       {
1092         if ( text_log )
1093           text_log->Print( "ON_Brep.m_E[%d] is deleted (m_edge_index = -1) but edge.m_vi[0]=%d (should be -1).\n",
1094                            ei, edge.m_vi[0] );
1095         return false;
1096       }
1097       if ( edge.m_vi[1] != -1 )
1098       {
1099         if ( text_log )
1100           text_log->Print( "ON_Brep.m_E[%d] is deleted (m_edge_index = -1) but edge.m_vi[1]=%d (should be -1).\n",
1101                            ei, edge.m_vi[1] );
1102         return false;
1103       }
1104     }
1105     else if ( m_E[ei].m_edge_index != ei )
1106     {
1107       if ( text_log )
1108         text_log->Print( "ON_Brep.m_E[%d].m_edge_index = %d (should be %d)\n",
1109                          ei, m_E[ei].m_edge_index, ei );
1110       return false;
1111     }
1112   }
1113 
1114   for ( ti = 0; ti < trim_count; ti++ )
1115   {
1116     if ( m_T[ti].m_trim_index == -1 )
1117     {
1118       const ON_BrepTrim& trim = m_T[ti];
1119       if ( trim.m_ei != -1 )
1120       {
1121         if ( text_log )
1122           text_log->Print( "ON_Brep.m_T[%d] is deleted (m_trim_index = -1) but trim.m_ei=%d (should be -1).\n",
1123                            ti, trim.m_ei );
1124         return false;
1125       }
1126       if ( trim.m_li != -1 )
1127       {
1128         if ( text_log )
1129           text_log->Print( "ON_Brep.m_T[%d] is deleted (m_trim_index = -1) but trim.m_li=%d (should be -1).\n",
1130                            ti, trim.m_li );
1131         return false;
1132       }
1133       if ( trim.m_c2i != -1 )
1134       {
1135         if ( text_log )
1136           text_log->Print( "ON_Brep.m_T[%d] is deleted (m_trim_index = -1) but trim.m_c2i=%d (should be -1).\n",
1137                            ti, trim.m_c2i );
1138         return false;
1139       }
1140       if ( trim.m_vi[0] != -1 )
1141       {
1142         if ( text_log )
1143           text_log->Print( "ON_Brep.m_T[%d] is deleted (m_trim_index = -1) but trim.m_vi[0]=%d (should be -1).\n",
1144                            ti, trim.m_vi[0] );
1145         return false;
1146       }
1147       if ( trim.m_vi[1] != -1 )
1148       {
1149         if ( text_log )
1150           text_log->Print( "ON_Brep.m_T[%d] is deleted (m_trim_index = -1) but trim.m_vi[1]=%d (should be -1).\n",
1151                            ti, trim.m_vi[1] );
1152         return false;
1153       }
1154     }
1155     else if ( m_T[ti].m_trim_index != ti  )
1156     {
1157       if ( text_log )
1158         text_log->Print( "ON_Brep.m_T[%d].m_trim_index = %d (should be %d)\n",
1159                          ti, m_T[ti].m_trim_index, ti );
1160       return false;
1161     }
1162     else if ( !m_T[ti].IsValid( text_log ) )
1163     {
1164       if ( text_log )
1165         text_log->Print( "ON_Brep.m_T[%d] is not valid\n",ti );
1166       return false;
1167     }
1168   }
1169 
1170   for ( li = 0; li < loop_count; li++ )
1171   {
1172     if ( m_L[li].m_loop_index == -1 )
1173     {
1174       const ON_BrepLoop& loop = m_L[li];
1175       if ( loop.m_fi != -1 )
1176       {
1177         if ( text_log )
1178           text_log->Print( "ON_Brep.m_L[%d] is deleted (m_loop_index = -1) but loop.m_fi=%d (should be -1).\n",
1179                            li, loop.m_fi );
1180         return false;
1181       }
1182       if ( loop.m_ti.Count() > 0 )
1183       {
1184         if ( text_log )
1185           text_log->Print( "ON_Brep.m_L[%d] is deleted (m_loop_index = -1) but loop.m_ti.Count()=%d.\n",
1186                            li, loop.m_ti.Count() );
1187         return false;
1188       }
1189     }
1190     else if ( m_L[li].m_loop_index != li )
1191     {
1192       if ( text_log )
1193         text_log->Print( "ON_Brep.m_L[%d].m_loop_index = %d (should be %d)\n",
1194                          li, m_L[li].m_loop_index, li );
1195       return false;
1196     }
1197   }
1198 
1199   for ( fi = 0; fi < face_count; fi++ )
1200   {
1201     if ( m_F[fi].m_face_index == -1 )
1202     {
1203       const ON_BrepFace& face = m_F[fi];
1204       if ( face.m_si != -1 )
1205       {
1206         if ( text_log )
1207           text_log->Print( "ON_Brep.m_F[%d] is deleted (m_face_index = -1) but face.m_si=%d (should be -1).\n",
1208                            fi, face.m_si );
1209         return false;
1210       }
1211       if ( face.ProxySurface() )
1212       {
1213         if ( text_log )
1214           text_log->Print( "ON_Brep.m_F[%d] is deleted (m_face_index = -1) but face.ProxySurface() is not NULL.\n",
1215                            fi );
1216         return false;
1217       }
1218       if ( face.m_li.Count() > 0 )
1219       {
1220         if ( text_log )
1221           text_log->Print( "ON_Brep.m_F[%d] is deleted (m_face_index = -1) but face.m_li.Count()=%d.\n",
1222                            fi, face.m_li.Count() );
1223         return false;
1224       }
1225     }
1226     else if ( m_F[fi].m_face_index != fi )
1227     {
1228       if ( text_log )
1229         text_log->Print( "ON_Brep.m_F[%d].m_face_index = %d (should be %d)\n",
1230                          fi, m_F[fi].m_face_index, fi );
1231       return false;
1232     }
1233   }
1234 
1235   // check vertices
1236   for ( vi = 0; vi < vertex_count; vi++ ) {
1237     if ( m_V[vi].m_vertex_index == -1 )
1238       continue;
1239     if ( !IsValidVertexTopology( vi, text_log ) ) {
1240       if ( text_log )
1241         text_log->Print("ON_Brep.m_V[%d] is invalid.\n",vi);
1242       return false;
1243     }
1244   }
1245 
1246   // check edges
1247   for ( ei = 0; ei < edge_count; ei++ )
1248   {
1249     if ( m_E[ei].m_edge_index == -1 )
1250       continue;
1251     if ( !IsValidEdgeTopology( ei, text_log ) ) {
1252       if ( text_log )
1253         text_log->Print("ON_Brep.m_E[%d] is invalid.\n",ei);
1254       return false;
1255     }
1256   }
1257 
1258   // check faces
1259   for ( fi = 0; fi < face_count; fi++ )
1260   {
1261     if ( m_F[fi].m_face_index == -1 )
1262       continue;
1263     if ( !IsValidFaceTopology( fi, text_log ) ) {
1264       if ( text_log )
1265         text_log->Print("ON_Brep.m_F[%d] is invalid.\n",fi);
1266       return false;
1267     }
1268   }
1269 
1270   // check trims
1271   for ( ti = 0; ti < trim_count; ti++ )
1272   {
1273     const ON_BrepTrim& trim = m_T[ti];
1274     if ( trim.m_trim_index == -1 )
1275       continue;
1276     if ( !IsValidTrimTopology( ti, text_log ) ) {
1277       if ( text_log )
1278         text_log->Print("ON_Brep.m_T[%d] is invalid.\n",ti);
1279       return false;
1280     }
1281   }
1282 
1283   // check loops
1284   for ( li = 0; li < loop_count; li++ )
1285   {
1286     const ON_BrepLoop& loop = m_L[li];
1287     if ( loop.m_loop_index == -1 )
1288       continue;
1289     if ( !IsValidLoopTopology( li, text_log ) ) {
1290       if ( text_log )
1291         text_log->Print("ON_Brep.m_L[%d] is invalid.\n",li);
1292       return false;
1293     }
1294   }
1295 
1296   return true;
1297 }
1298 
1299 
1300 ////////////////////////////////////////////////////////////////////////////////////
1301 ////////////////////////////////////////////////////////////////////////////////////
1302 ////////////////////////////////////////////////////////////////////////////////////
1303 
1304 bool
IsValidVertexGeometry(int vertex_index,ON_TextLog * text_log) const1305 ON_Brep::IsValidVertexGeometry( int vertex_index, ON_TextLog* text_log ) const
1306 {
1307   if ( vertex_index < 0 || vertex_index >= m_V.Count() )
1308   {
1309     if ( text_log )
1310       text_log->Print("brep vertex_index = %d (should be >=0 and <%d=brep.m_V.Count() ).\n",
1311                       vertex_index, m_V.Count());
1312     return false;
1313   }
1314   const ON_BrepVertex& vertex = m_V[vertex_index];
1315   if ( vertex.m_vertex_index != vertex_index )
1316   {
1317     if ( text_log )
1318     {
1319       text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
1320       text_log->PushIndent();
1321       text_log->Print("vertex.m_vertex_index = %d (should be %d).\n",
1322                        vertex.m_vertex_index, vertex_index );
1323       text_log->PopIndent();
1324     }
1325     return false;
1326   }
1327 
1328   if ( !vertex.point.IsValid() )
1329   {
1330     if ( text_log )
1331     {
1332       text_log->Print("brep.m_V[%d] vertex geometry is not valid.\n",vertex_index);
1333       text_log->PushIndent();
1334       text_log->Print("vertex.point = (%g,%g,%g) is not valid.\n",vertex.point.x,vertex.point.y,vertex.point.z );
1335       text_log->PopIndent();
1336     }
1337     return false;
1338   }
1339   return true;
1340 }
1341 
1342 bool
IsValidEdgeGeometry(int edge_index,ON_TextLog * text_log) const1343 ON_Brep::IsValidEdgeGeometry( int edge_index, ON_TextLog* text_log ) const
1344 {
1345   if ( edge_index < 0 || edge_index >= m_E.Count() )
1346   {
1347     if ( text_log )
1348       text_log->Print("brep edge_index = %d (should be >=0 and <%d=brep.m_E.Count() ).\n",
1349                       edge_index, m_E.Count());
1350     return false;
1351   }
1352   const ON_BrepEdge& edge = m_E[edge_index];
1353   if ( edge.m_edge_index != edge_index )
1354   {
1355     if ( text_log )
1356     {
1357       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
1358       text_log->PushIndent();
1359       text_log->Print("edge.m_edge_index = %d (should be %d).\n",
1360                        edge.m_edge_index, edge_index );
1361       text_log->PopIndent();
1362     }
1363     return false;
1364   }
1365 
1366   int vi0 = edge.m_vi[0];
1367   int vi1 = edge.m_vi[1];
1368   if ( edge.IsClosed() )
1369   {
1370     if ( vi0 != vi1 )
1371     {
1372       if ( text_log )
1373       {
1374         text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
1375         text_log->PushIndent();
1376         text_log->Print("edge.m_vi[]=(%d,%d) but edge.IsClosed() is true\n",
1377                          vi0,vi1);
1378         text_log->PopIndent();
1379       }
1380       return false;
1381     }
1382   }
1383   else {
1384     if ( vi0 == vi1 )
1385     {
1386       if ( text_log )
1387       {
1388         text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
1389         text_log->PushIndent();
1390         text_log->Print("edge.m_vi[0]=edge.m_vi[1]=%d but edge.IsClosed() is false.\n",
1391                          vi0);
1392         text_log->PopIndent();
1393       }
1394       return false;
1395     }
1396   }
1397 
1398   return true;
1399 }
1400 
1401 bool
IsValidFaceGeometry(int face_index,ON_TextLog * text_log) const1402 ON_Brep::IsValidFaceGeometry( int face_index, ON_TextLog* text_log ) const
1403 {
1404   if ( face_index < 0 || face_index >= m_F.Count() )
1405   {
1406     if ( text_log )
1407       text_log->Print("brep face_index = %d (should be >=0 and <%d=brep.m_F.Count() ).\n",
1408                       face_index, m_F.Count());
1409     return false;
1410   }
1411   const ON_BrepFace& face = m_F[face_index];
1412   if ( face.m_face_index != face_index )
1413   {
1414     if ( text_log )
1415     {
1416       text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
1417       text_log->PushIndent();
1418       text_log->Print("face.m_face_index = %d (should be %d).\n",
1419                        face.m_face_index, face_index );
1420       text_log->PopIndent();
1421     }
1422     return false;
1423   }
1424   return true;
1425 }
1426 
1427 bool
IsValidLoopGeometry(int loop_index,ON_TextLog * text_log) const1428 ON_Brep::IsValidLoopGeometry( int loop_index, ON_TextLog* text_log ) const
1429 {
1430   if ( loop_index < 0 || loop_index >= m_L.Count() )
1431   {
1432     if ( text_log )
1433       text_log->Print("brep loop_index = %d (should be >=0 and <%d=brep.m_L.Count() ).\n",
1434                       loop_index, m_L.Count());
1435     return false;
1436   }
1437   const ON_BrepLoop& loop = m_L[loop_index];
1438   if ( loop.m_loop_index != loop_index )
1439   {
1440     if ( text_log )
1441     {
1442       text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
1443       text_log->PushIndent();
1444       text_log->Print("loop.m_loop_index = %d (should be %d).\n",
1445                        loop.m_loop_index, loop_index );
1446       text_log->PopIndent();
1447     }
1448     return false;
1449   }
1450   return true;
1451 }
1452 
1453 bool
IsValidTrimGeometry(int trim_index,ON_TextLog * text_log) const1454 ON_Brep::IsValidTrimGeometry( int trim_index, ON_TextLog* text_log ) const
1455 {
1456   if ( trim_index < 0 || trim_index >= m_T.Count() )
1457   {
1458     if ( text_log )
1459       text_log->Print("brep trim_index = %d (should be >=0 and <%d=brep.m_T.Count() ).\n",
1460                       trim_index, m_T.Count());
1461     return false;
1462   }
1463   const ON_BrepTrim& trim = m_T[trim_index];
1464   if ( trim.m_trim_index != trim_index )
1465   {
1466     if ( text_log )
1467     {
1468       text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
1469       text_log->PushIndent();
1470       text_log->Print("trim.m_trim_index = %d (should be %d).\n",
1471                        trim.m_trim_index, trim_index );
1472       text_log->PopIndent();
1473     }
1474     return false;
1475   }
1476   return true;
1477 }
1478 
1479 bool
IsValidGeometry(ON_TextLog * text_log) const1480 ON_Brep::IsValidGeometry( ON_TextLog* text_log ) const
1481 {
1482   const int curve2d_count = m_C2.Count();
1483   const int curve3d_count = m_C3.Count();
1484   const int surface_count = m_S.Count();
1485   const int vertex_count  = m_V.Count();
1486   const int edge_count    = m_E.Count();
1487   const int trim_count    = m_T.Count();
1488   const int loop_count    = m_L.Count();
1489   const int face_count    = m_F.Count();
1490 
1491   int c2i, c3i, si, vi, ei, fi, ti, li;
1492 
1493   // check 2d curve geometry
1494   for ( c2i = 0; c2i < curve2d_count; c2i++ ) {
1495     if ( !m_C2[c2i] )
1496     {
1497       continue;
1498       // NULL 2d curves are ok if they are not referenced
1499     }
1500     if ( !m_C2[c2i]->IsValid(text_log) )
1501     {
1502       if ( text_log )
1503         text_log->Print("ON_Brep.m_C2[%d] is invalid.\n",c2i);
1504       return false;
1505     }
1506     int c2_dim = m_C2[c2i]->Dimension();
1507     if ( c2_dim != 2 )
1508     {
1509       if ( text_log )
1510         text_log->Print("ON_Brep.m_C2[%d]->Dimension() = %d (should be 2).\n", c2i, c2_dim );
1511       return false;
1512     }
1513   }
1514 
1515   // check 3d curve geometry
1516   for ( c3i = 0; c3i < curve3d_count; c3i++ ) {
1517     if ( !m_C3[c3i] )
1518     {
1519       continue;
1520       // NULL 3d curves are ok if they are not referenced
1521     }
1522     if ( !m_C3[c3i]->IsValid(text_log) )
1523     {
1524       if ( text_log )
1525         text_log->Print("ON_Brep.m_C3[%d] is invalid.\n",c3i);
1526       return false;
1527     }
1528     int c3_dim = m_C3[c3i]->Dimension();
1529     if ( c3_dim != 3 )
1530     {
1531       if ( text_log )
1532         text_log->Print("ON_Brep.m_C3[%d]->Dimension() = %d (should be 3).\n", c3i, c3_dim );
1533       return false;
1534     }
1535   }
1536 
1537   // check 3d surface geometry
1538   for ( si = 0; si < surface_count; si++ ) {
1539     if ( !m_S[si] )
1540     {
1541       continue;
1542       // NULL 3d surfaces are ok if they are not referenced
1543     }
1544     if ( !m_S[si]->IsValid(text_log) )
1545     {
1546       if ( text_log )
1547         text_log->Print("ON_Brep.m_S[%d] is invalid.\n",si);
1548       return false;
1549     }
1550     int dim = m_S[si]->Dimension();
1551     if ( dim != 3 )
1552     {
1553       if ( text_log )
1554         text_log->Print("ON_Brep.m_S[%d]->Dimension() = %d (should be 3).\n", si, dim );
1555       return false;
1556     }
1557   }
1558 
1559   // check vertices
1560   for ( vi = 0; vi < vertex_count; vi++ ) {
1561     if ( m_V[vi].m_vertex_index == -1 )
1562       continue;
1563     if ( !IsValidVertexGeometry( vi, text_log ) ) {
1564       if ( text_log )
1565         text_log->Print("ON_Brep.m_V[%d] is invalid.\n",vi);
1566       return false;
1567     }
1568   }
1569 
1570   // check edges
1571   for ( ei = 0; ei < edge_count; ei++ )
1572   {
1573     if ( m_E[ei].m_edge_index == -1 )
1574       continue;
1575     if ( !IsValidEdgeGeometry( ei, text_log ) ) {
1576       if ( text_log )
1577         text_log->Print("ON_Brep.m_E[%d] is invalid.\n",ei);
1578       return false;
1579     }
1580   }
1581 
1582   // check faces
1583   for ( fi = 0; fi < face_count; fi++ )
1584   {
1585     if ( m_F[fi].m_face_index == -1 )
1586       continue;
1587     if ( !IsValidFaceGeometry( fi, text_log ) ) {
1588       if ( text_log )
1589         text_log->Print("ON_Brep.m_F[%d] is invalid.\n",fi);
1590       return false;
1591     }
1592   }
1593 
1594   // check trims
1595   for ( ti = 0; ti < trim_count; ti++ )
1596   {
1597     if ( m_T[ti].m_trim_index == -1 )
1598       continue;
1599     if ( !IsValidTrimGeometry( ti, text_log ) ) {
1600       if ( text_log )
1601         text_log->Print("ON_Brep.m_T[%d] is invalid.\n",ti);
1602       return false;
1603     }
1604   }
1605 
1606   // check loops
1607   for ( li = 0; li < loop_count; li++ )
1608   {
1609     if ( m_L[li].m_loop_index == -1 )
1610       continue;
1611     if ( !IsValidLoopGeometry( li, text_log ) ) {
1612       if ( text_log )
1613         text_log->Print("ON_Brep.m_L[%d] is invalid.\n",li);
1614       return false;
1615     }
1616   }
1617 
1618   return true;
1619 }
1620 
1621 ////////////////////////////////////////////////////////////////////////////////////
1622 ////////////////////////////////////////////////////////////////////////////////////
1623 ////////////////////////////////////////////////////////////////////////////////////
1624 
1625 bool
IsValidVertexTolerancesAndFlags(int vertex_index,ON_TextLog * text_log) const1626 ON_Brep::IsValidVertexTolerancesAndFlags( int vertex_index, ON_TextLog* text_log ) const
1627 {
1628   if ( vertex_index < 0 || vertex_index >= m_V.Count() )
1629   {
1630     if ( text_log )
1631       text_log->Print("brep vertex_index = %d (should be >=0 and <%d=brep.m_V.Count() ).\n",
1632                       vertex_index, m_V.Count());
1633     return false;
1634   }
1635   const ON_BrepVertex& vertex = m_V[vertex_index];
1636   if ( vertex.m_vertex_index != vertex_index )
1637   {
1638     if ( text_log )
1639     {
1640       text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
1641       text_log->PushIndent();
1642       text_log->Print("vertex.m_vertex_index = %d (should be %d).\n",
1643                        vertex.m_vertex_index, vertex_index );
1644       text_log->PopIndent();
1645     }
1646     return false;
1647   }
1648 
1649   if ( vertex.m_tolerance < 0.0 )
1650   {
1651     if ( text_log )
1652     {
1653       text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
1654       text_log->PushIndent();
1655       text_log->Print("vertex.m_tolerace = %g (should be >= 0.0)\n",vertex.m_tolerance);
1656       text_log->PopIndent();
1657     }
1658     return false;
1659   }
1660 
1661   return true;
1662 }
1663 
1664 bool
IsValidEdgeTolerancesAndFlags(int edge_index,ON_TextLog * text_log) const1665 ON_Brep::IsValidEdgeTolerancesAndFlags( int edge_index, ON_TextLog* text_log ) const
1666 {
1667   if ( edge_index < 0 || edge_index >= m_E.Count() )
1668   {
1669     if ( text_log )
1670       text_log->Print("brep edge_index = %d (should be >=0 and <%d=brep.m_E.Count() ).\n",
1671                       edge_index, m_E.Count());
1672     return false;
1673   }
1674   const ON_BrepEdge& edge = m_E[edge_index];
1675   if ( edge.m_edge_index != edge_index )
1676   {
1677     if ( text_log )
1678     {
1679       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
1680       text_log->PushIndent();
1681       text_log->Print("edge.m_edge_index = %d (should be %d).\n",
1682                        edge.m_edge_index, edge_index );
1683       text_log->PopIndent();
1684     }
1685     return false;
1686   }
1687 
1688   if ( edge.m_tolerance < 0.0 )
1689   {
1690     if ( text_log )
1691     {
1692       text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
1693       text_log->PushIndent();
1694       text_log->Print("edge.m_tolerance=%g (should be >= 0.0)\n",edge.m_tolerance);
1695       text_log->PopIndent();
1696     }
1697     return false;
1698   }
1699 
1700   return true;
1701 }
1702 
1703 bool
IsValidFaceTolerancesAndFlags(int face_index,ON_TextLog * text_log) const1704 ON_Brep::IsValidFaceTolerancesAndFlags( int face_index, ON_TextLog* text_log ) const
1705 {
1706   if ( face_index < 0 || face_index >= m_F.Count() )
1707   {
1708     if ( text_log )
1709       text_log->Print("brep face_index = %d (should be >=0 and <%d=brep.m_F.Count() ).\n",
1710                       face_index, m_F.Count());
1711     return false;
1712   }
1713   const ON_BrepFace& face = m_F[face_index];
1714   if ( face.m_face_index != face_index )
1715   {
1716     if ( text_log )
1717     {
1718       text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
1719       text_log->PushIndent();
1720       text_log->Print("face.m_face_index = %d (should be %d).\n",
1721                        face.m_face_index, face_index );
1722       text_log->PopIndent();
1723     }
1724     return false;
1725   }
1726   return true;
1727 }
1728 
1729 bool
IsValidLoopTolerancesAndFlags(int loop_index,ON_TextLog * text_log) const1730 ON_Brep::IsValidLoopTolerancesAndFlags( int loop_index, ON_TextLog* text_log ) const
1731 {
1732   if ( loop_index < 0 || loop_index >= m_L.Count() )
1733   {
1734     if ( text_log )
1735       text_log->Print("brep loop_index = %d (should be >=0 and <%d=brep.m_L.Count() ).\n",
1736                       loop_index, m_L.Count());
1737     return false;
1738   }
1739   const ON_BrepLoop& loop = m_L[loop_index];
1740   if ( loop.m_loop_index != loop_index )
1741   {
1742     if ( text_log )
1743     {
1744       text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
1745       text_log->PushIndent();
1746       text_log->Print("loop.m_loop_index = %d (should be %d).\n",
1747                        loop.m_loop_index, loop_index );
1748       text_log->PopIndent();
1749     }
1750     return false;
1751   }
1752   return true;
1753 }
1754 
1755 bool
IsValidTrimTolerancesAndFlags(int trim_index,ON_TextLog * text_log) const1756 ON_Brep::IsValidTrimTolerancesAndFlags( int trim_index, ON_TextLog* text_log ) const
1757 {
1758   if ( trim_index < 0 || trim_index >= m_T.Count() )
1759   {
1760     if ( text_log )
1761       text_log->Print("brep trim_index = %d (should be >=0 and <%d=brep.m_T.Count() ).\n",
1762                       trim_index, m_T.Count());
1763     return false;
1764   }
1765   const ON_BrepTrim& trim = m_T[trim_index];
1766   if ( trim.m_trim_index != trim_index )
1767   {
1768     if ( text_log )
1769     {
1770       text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
1771       text_log->PushIndent();
1772       text_log->Print("trim.m_trim_index = %d (should be %d).\n",
1773                        trim.m_trim_index, trim_index );
1774       text_log->PopIndent();
1775     }
1776     return false;
1777   }
1778   return true;
1779 }
1780 
1781 bool
IsValidTolerancesAndFlags(ON_TextLog * text_log) const1782 ON_Brep::IsValidTolerancesAndFlags( ON_TextLog* text_log ) const
1783 {
1784   const int vertex_count  = m_V.Count();
1785   const int edge_count    = m_E.Count();
1786   const int trim_count    = m_T.Count();
1787   const int loop_count    = m_L.Count();
1788   const int face_count    = m_F.Count();
1789 
1790   int vi, ei, fi, ti, li;
1791 
1792   // check vertices
1793   for ( vi = 0; vi < vertex_count; vi++ ) {
1794     if ( m_V[vi].m_vertex_index == -1 )
1795       continue;
1796     if ( !IsValidVertexTolerancesAndFlags( vi, text_log ) ) {
1797       if ( text_log )
1798         text_log->Print("ON_Brep.m_V[%d] is invalid.\n",vi);
1799       return false;
1800     }
1801   }
1802 
1803   // check edges
1804   for ( ei = 0; ei < edge_count; ei++ )
1805   {
1806     if ( m_E[ei].m_edge_index == -1 )
1807       continue;
1808     if ( !IsValidEdgeTolerancesAndFlags( ei, text_log ) ) {
1809       if ( text_log )
1810         text_log->Print("ON_Brep.m_E[%d] is invalid.\n",ei);
1811       return false;
1812     }
1813   }
1814 
1815   // check faces
1816   for ( fi = 0; fi < face_count; fi++ )
1817   {
1818     if ( m_F[fi].m_face_index == -1 )
1819       continue;
1820     if ( !IsValidFaceTolerancesAndFlags( fi, text_log ) ) {
1821       if ( text_log )
1822         text_log->Print("ON_Brep.m_F[%d] is invalid.\n",fi);
1823       return false;
1824     }
1825   }
1826 
1827   // check trims
1828   for ( ti = 0; ti < trim_count; ti++ )
1829   {
1830     if ( m_T[ti].m_trim_index == -1 )
1831       continue;
1832     if ( !IsValidTrimTolerancesAndFlags( ti, text_log ) ) {
1833       if ( text_log )
1834         text_log->Print("ON_Brep.m_T[%d] is invalid.\n",ti);
1835       return false;
1836     }
1837   }
1838 
1839   // check loops
1840   for ( li = 0; li < loop_count; li++ )
1841   {
1842     if ( m_L[li].m_loop_index == -1 )
1843       continue;
1844     if ( !IsValidLoopTolerancesAndFlags( li, text_log ) ) {
1845       if ( text_log )
1846         text_log->Print("ON_Brep.m_L[%d] is invalid.\n",li);
1847       return false;
1848     }
1849   }
1850 
1851   return true;
1852 }
1853 
1854