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