00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00019 static
00020 void ON_BrepExtrudeHelper_ReserveSpace(
00021 ON_Brep& brep,
00022 int extruded_trim_count,
00023 int cap_count
00024 )
00025 {
00026 if ( extruded_trim_count >= 0 && cap_count >= 0 )
00027 {
00028 const int vertex_count0 = brep.m_V.Count();
00029 const int trim_count0 = brep.m_T.Count();
00030 const int loop_count0 = brep.m_L.Count();
00031 const int edge_count0 = brep.m_E.Count();
00032 const int face_count0 = brep.m_F.Count();
00033 const int srf_count0 = brep.m_S.Count();
00034 const int c2_count0 = brep.m_C2.Count();
00035 const int c3_count0 = brep.m_C3.Count();
00036
00037
00038
00039 brep.m_V.Reserve( vertex_count0 + extruded_trim_count + 1 );
00040 brep.m_T.Reserve( trim_count0 + (4+cap_count)*extruded_trim_count );
00041 brep.m_F.Reserve( face_count0 + extruded_trim_count + cap_count );
00042 brep.m_E.Reserve( edge_count0 + 2*extruded_trim_count + 1 );
00043 brep.m_L.Reserve( loop_count0 + extruded_trim_count + cap_count );
00044 brep.m_S.Reserve( srf_count0 + extruded_trim_count + cap_count );
00045 brep.m_C2.Reserve( c2_count0 + (4+cap_count)*extruded_trim_count );
00046 brep.m_C3.Reserve( c3_count0 + 2*extruded_trim_count + 1 );
00047 }
00048 }
00049
00050 static
00051 ON_SumSurface* ON_BrepExtrudeHelper_MakeSumSrf( const ON_Curve& path_curve,
00052 const ON_BrepEdge& base_edge, ON_BOOL32 bRev )
00053 {
00054 ON_SumSurface* sum_srf = 0;
00055
00056 if ( base_edge.ProxyCurve() )
00057 {
00058 ON_Curve* srf_path_curve = path_curve.DuplicateCurve();
00059 ON_Curve* srf_base_curve = base_edge.DuplicateCurve();
00060 if ( !bRev )
00061 srf_base_curve->Reverse();
00062 ON_3dPoint sum_basepoint = -ON_3dVector(srf_path_curve->PointAtStart());
00063 sum_srf = new ON_SumSurface();
00064 sum_srf->m_curve[0] = srf_base_curve;
00065 sum_srf->m_curve[1] = srf_path_curve;
00066 sum_srf->m_basepoint = sum_basepoint;
00067 sum_srf->BoundingBox();
00068 }
00069 return sum_srf;
00070 }
00071
00072 static
00073 ON_NurbsSurface* ON_BrepExtrudeHelper_MakeConeSrf( const ON_3dPoint& apex_point,
00074 const ON_BrepEdge& edge, ON_BOOL32 bRev )
00075 {
00076
00077
00078
00079
00080
00081
00082
00083
00084 ON_NurbsSurface* cone_srf = new ON_NurbsSurface();
00085 if ( cone_srf->CreateConeSurface( apex_point, edge ) )
00086 {
00087 if ( bRev )
00088 cone_srf->Reverse(0);
00089
00090 double d = 0.0;
00091 ON_Interval edom = edge.Domain();
00092 ON_3dPoint pt;
00093 int i, hint=0;
00094 for ( i = 0; i <= 16; i++ )
00095 {
00096 if ( !edge.EvPoint( edom.ParameterAt(i/16.0), pt, 0, &hint ) )
00097 continue;
00098 if ( pt.DistanceTo(apex_point) > d )
00099 d = pt.DistanceTo(apex_point);
00100 }
00101 if ( d > ON_SQRT_EPSILON )
00102 cone_srf->SetDomain(1,0.0,d);
00103 }
00104 else
00105 {
00106 delete cone_srf;
00107 cone_srf = 0;
00108 }
00109 return cone_srf;
00110 }
00111
00112 static
00113 ON_BOOL32 ON_BrepExtrudeHelper_MakeSides(
00114 ON_Brep& brep,
00115 int loop_index,
00116 const ON_Curve& path_curve,
00117 ON_BOOL32 bCap,
00118 ON_SimpleArray<int>& side_face_index
00119 )
00120 {
00121 int lti, ti, i, vid[4], eid[4], bRev3d[4];
00122
00123
00124
00125
00126
00127
00128 const int loop_trim_count = brep.m_L[loop_index].m_ti.Count();
00129 if ( loop_trim_count == 0 )
00130 return false;
00131
00132
00133 const int trim_count0 = brep.m_T.Count();
00134 const int edge_count0 = brep.m_E.Count();
00135
00136 ON_BrepExtrudeHelper_ReserveSpace( brep, loop_trim_count, bCap?1:0 );
00137
00138 side_face_index.Reserve( side_face_index.Count() + loop_trim_count);
00139 int prev_face_index = -1;
00140 int first_face_east_trim_index = -1;
00141
00142 for ( lti = 0; lti < loop_trim_count; lti++ )
00143 {
00144 ON_SumSurface* sum_srf = 0;
00145 side_face_index.Append(-1);
00146 ti = brep.m_L[loop_index].m_ti[lti];
00147 if ( ti < 0 || ti >= trim_count0 )
00148 continue;
00149
00150 for ( i = 0; i < 4; i++ )
00151 {
00152 vid[i] = -1;
00153 eid[i] = -1;
00154 }
00155 bRev3d[0] = false;
00156 bRev3d[1] = false;
00157 bRev3d[2] = false;
00158 bRev3d[3] = false;
00159
00160
00161 {
00162 ON_BrepTrim& trim = brep.m_T[ti];
00163 if ( trim.m_ei >= 0 && trim.m_ei < edge_count0 )
00164 {
00165 const ON_BrepEdge& base_edge = brep.m_E[trim.m_ei];
00166
00167
00168
00169 if ( trim.m_type == ON_BrepTrim::seam )
00170 {
00171 prev_face_index = -1;
00172 continue;
00173 }
00174
00175
00176 vid[0] = trim.m_vi[1];
00177 vid[1] = trim.m_vi[0];
00178 eid[0] = base_edge.m_edge_index;
00179 bRev3d[0] = (trim.m_bRev3d?false:true);
00180 sum_srf = ON_BrepExtrudeHelper_MakeSumSrf( path_curve, base_edge, trim.m_bRev3d );
00181 }
00182 }
00183 if ( !sum_srf )
00184 continue;
00185
00186 if ( prev_face_index >= 0 )
00187 {
00188 const ON_BrepTrim& prev_west_trim = brep.m_T[ brep.m_L[ brep.m_F[prev_face_index].m_li[0]].m_ti[3] ];
00189 vid[2] = prev_west_trim.m_vi[0];
00190 eid[1] = prev_west_trim.m_ei;
00191 bRev3d[1] = (prev_west_trim.m_bRev3d?false:true);
00192 }
00193 if ( first_face_east_trim_index >= 0 && brep.m_T[first_face_east_trim_index].m_vi[0] == vid[0] )
00194 {
00195 const ON_BrepTrim& first_face_east_trim = brep.m_T[first_face_east_trim_index];
00196 vid[3] = first_face_east_trim.m_vi[1];
00197 eid[3] = first_face_east_trim.m_ei;
00198 bRev3d[3] = (first_face_east_trim.m_bRev3d?false:true);
00199 }
00200 const ON_BrepFace* side_face = brep.NewFace(sum_srf,vid,eid,bRev3d);
00201 if ( side_face )
00202 {
00203 *side_face_index.Last() = side_face->m_face_index;
00204 prev_face_index = side_face->m_face_index;
00205 if ( first_face_east_trim_index < 0 )
00206 first_face_east_trim_index = brep.m_L[ side_face->m_li[0] ].m_ti[1];
00207 }
00208 }
00209
00210 return true;
00211 }
00212
00213 static
00214 bool ON_BrepExtrudeHelper_CheckPathCurve( const ON_Curve& path_curve, ON_3dVector& path_vector )
00215 {
00216 ON_Line path_line;
00217 path_line.from = path_curve.PointAtStart();
00218 path_line.to = path_curve.PointAtEnd();
00219 path_vector = path_line.Direction();
00220 return ( path_vector.IsZero() ? false : true );
00221 }
00222
00223 static
00224 bool ON_BrepExtrudeHelper_MakeTopLoop(
00225 ON_Brep& brep,
00226 ON_BrepFace& top_face,
00227 int bottom_loop_index,
00228 const ON_3dVector path_vector,
00229 const int* side_face_index
00230 )
00231 {
00232 bool rc = true;
00233
00234 int lti, top_trim_index, i;
00235 if ( bottom_loop_index < 0 || bottom_loop_index >= brep.m_L.Count() )
00236 return false;
00237 ON_BrepLoop::TYPE loop_type = brep.m_L[bottom_loop_index].m_type;
00238 if ( loop_type != ON_BrepLoop::inner )
00239 loop_type = ON_BrepLoop::outer;
00240 ON_BrepLoop& top_loop = brep.NewLoop( loop_type, top_face );
00241 const ON_BrepLoop& bottom_loop = brep.m_L[bottom_loop_index];
00242 const int loop_trim_count = bottom_loop.m_ti.Count();
00243 brep.m_T.Reserve( brep.m_T.Count() + loop_trim_count );
00244
00245
00246
00247
00248
00249
00250 ON_SimpleArray<int> top_vertex_index(loop_trim_count);
00251 ON_SimpleArray<int> top_edge_index(loop_trim_count);
00252 ON_SimpleArray<bool> top_trim_bRev3d(loop_trim_count);
00253 for ( lti = 0; lti < loop_trim_count; lti++ )
00254 {
00255 top_vertex_index.Append(-1);
00256 top_edge_index.Append(-1);
00257 top_trim_bRev3d.Append(false);
00258 }
00259
00260
00261
00262 for ( lti = 0; lti < loop_trim_count; lti++ )
00263 {
00264 if ( side_face_index[lti] >= 0 )
00265 {
00266 const ON_BrepFace& side_face = brep.m_F[side_face_index[lti]];
00267 const ON_BrepLoop& side_loop = brep.m_L[side_face.m_li[0]];
00268 const ON_BrepTrim& side_north_trim = brep.m_T[side_loop.m_ti[2]];
00269 top_vertex_index[lti] = side_north_trim.m_vi[0];
00270 top_vertex_index[(lti+1)%loop_trim_count] = side_north_trim.m_vi[1];
00271 top_edge_index[lti] = side_north_trim.m_ei;
00272 }
00273 else
00274 {
00275
00276 int lti_prev = (lti+loop_trim_count-1)%loop_trim_count;
00277 int lti_next = (lti+1)%loop_trim_count;
00278 if ( side_face_index[lti_prev] < 0
00279 && side_face_index[lti_next] < 0
00280 && top_vertex_index[lti] < 0
00281 && top_vertex_index[lti_next] < 0
00282 )
00283 {
00284 int bottom_ti_prev = bottom_loop.m_ti[lti_prev];
00285 int bottom_ti = bottom_loop.m_ti[lti];
00286 int bottom_ti_next = bottom_loop.m_ti[lti_next];
00287 if ( bottom_ti >= 0 && bottom_ti < brep.m_T.Count()
00288 && bottom_ti_prev >= 0 && bottom_ti_prev < brep.m_T.Count()
00289 && bottom_ti_next >= 0 && bottom_ti_next < brep.m_T.Count()
00290 )
00291 {
00292 const ON_BrepTrim& bottom_trim_prev = brep.m_T[bottom_ti_prev];
00293 const ON_BrepTrim& bottom_trim = brep.m_T[bottom_ti];
00294 const ON_BrepTrim& bottom_trim_next = brep.m_T[bottom_ti_next];
00295 if ( ON_BrepTrim::seam == bottom_trim_prev.m_type
00296 && ON_BrepTrim::singular == bottom_trim.m_type
00297 && ON_BrepTrim::seam == bottom_trim_next.m_type
00298 && bottom_trim.m_vi[0] == bottom_trim.m_vi[1]
00299 )
00300 {
00301 int vi = bottom_trim.m_vi[0];
00302 if ( vi >= 0 && vi < brep.m_V.Count() )
00303 {
00304 ON_BrepVertex& top_vertex = brep.NewVertex(brep.m_V[vi].point+path_vector,0.0);
00305 top_vertex_index[lti] = top_vertex.m_vertex_index;
00306 top_vertex_index[lti_next] = top_vertex_index[lti];
00307 }
00308 }
00309 }
00310 }
00311 }
00312 }
00313
00314
00315
00316
00317 {
00318 bool bKeepChecking = true;
00319 while( bKeepChecking )
00320 {
00321
00322
00323 bKeepChecking = false;
00324
00325 for ( lti = 0; lti < loop_trim_count; lti++ )
00326 {
00327 if ( top_vertex_index[lti] == -1 )
00328 {
00329 for ( i = lti+1; i < loop_trim_count; i++ )
00330 {
00331 if ( ON_BrepTrim::singular != brep.m_T[bottom_loop.m_ti[i-1]].m_type )
00332 break;
00333 if ( top_vertex_index[i] >= 0 )
00334 {
00335 top_vertex_index[lti] = top_vertex_index[i];
00336 bKeepChecking = true;
00337 break;
00338 }
00339 }
00340 }
00341
00342 if ( top_vertex_index[lti] == -1 )
00343 {
00344 for ( i = lti-1; i >= 0; i-- )
00345 {
00346 if ( ON_BrepTrim::singular != brep.m_T[bottom_loop.m_ti[i+1]].m_type )
00347 break;
00348 if ( top_vertex_index[i] >= 0 )
00349 {
00350 top_vertex_index[lti] = top_vertex_index[i];
00351 bKeepChecking = true;
00352 break;
00353 }
00354 }
00355 }
00356 }
00357 }
00358 }
00359
00360
00361 for ( lti = 0; lti < loop_trim_count; lti++ )
00362 {
00363 if ( -1 != top_edge_index[lti] )
00364 continue;
00365 int bottom_ti = bottom_loop.m_ti[lti];
00366 if ( bottom_ti < 0 || bottom_ti >= brep.m_T.Count() )
00367 continue;
00368 const ON_BrepTrim& bottom_trim = brep.m_T[bottom_ti];
00369 if ( ON_BrepTrim::seam != bottom_trim.m_type )
00370 continue;
00371 if ( bottom_trim.m_ei < 0 )
00372 continue;
00373 if ( bottom_trim.m_ei >= brep.m_E.Count() )
00374 continue;
00375
00376
00377 const ON_BrepEdge& bottom_edge = brep.m_E[bottom_trim.m_ei];
00378 ON_Curve* top_c3 = bottom_edge.DuplicateCurve();
00379 if ( 0 == top_c3 )
00380 continue;
00381
00382 top_c3->Translate(path_vector);
00383 ON_3dPoint P0 = top_c3->PointAtStart();
00384 ON_3dPoint P1 = top_c3->PointAtEnd();
00385 int top_c3i = brep.AddEdgeCurve(top_c3);
00386 top_c3 = 0;
00387
00388 int e_vi0 = top_vertex_index[lti];
00389 int e_vi1 = top_vertex_index[(lti+1)%loop_trim_count];
00390 if ( bottom_trim.m_bRev3d )
00391 {
00392
00393 ON_3dPoint tmp_P = P0; P0 = P1; P1 = tmp_P;
00394 }
00395 if ( e_vi0 < 0 )
00396 {
00397 e_vi0 = brep.NewVertex(P0).m_vertex_index;
00398 top_vertex_index[lti] = e_vi0;
00399 }
00400 if ( e_vi1 < 0 )
00401 {
00402 e_vi1 = brep.NewVertex(P1).m_vertex_index;
00403 top_vertex_index[(lti+1)%loop_trim_count] = e_vi1;
00404 }
00405 if ( bottom_trim.m_bRev3d )
00406 {
00407
00408 int tmp_i = e_vi0; e_vi0 = e_vi1; e_vi1 = tmp_i;
00409 }
00410 ON_BrepEdge& top_edge = brep.NewEdge(brep.m_V[e_vi0],brep.m_V[e_vi1],top_c3i);
00411 top_edge.m_tolerance = bottom_edge.m_tolerance;
00412 top_edge_index[lti] = top_edge.m_edge_index;
00413 top_trim_bRev3d[lti] = bottom_trim.m_bRev3d?true:false;
00414
00415
00416
00417 int mate_lti;
00418 for( mate_lti = lti+1; mate_lti < loop_trim_count; mate_lti++ )
00419 {
00420 if ( top_edge_index[mate_lti] != -1 )
00421 continue;
00422 int bottom_mate_ti = bottom_loop.m_ti[mate_lti];
00423 if ( bottom_mate_ti < 0 || bottom_mate_ti >= brep.m_T.Count() )
00424 continue;
00425 const ON_BrepTrim& bottom_mate_trim = brep.m_T[bottom_mate_ti];
00426 if ( bottom_mate_trim.m_type != ON_BrepTrim::seam )
00427 continue;
00428 if ( bottom_mate_trim.m_ei != bottom_trim.m_ei )
00429 continue;
00430 top_edge_index[mate_lti] = top_edge.m_edge_index;
00431 top_trim_bRev3d[mate_lti] = bottom_mate_trim.m_bRev3d?true:false;
00432 break;
00433 }
00434 }
00435
00436
00437 for ( lti = 0; lti < loop_trim_count; lti++ )
00438 {
00439 const ON_BrepTrim& bottom_trim = brep.m_T[ bottom_loop.m_ti[lti] ];
00440 ON_Curve* top_c2 = bottom_trim.DuplicateCurve();
00441 int top_c2i = (0!=top_c2) ? brep.AddTrimCurve(top_c2) : bottom_trim.m_c2i;
00442 top_trim_index = -1;
00443 if ( bottom_trim.m_type == ON_BrepTrim::singular && top_vertex_index[lti] >= 0 )
00444 {
00445 top_trim_index = brep.NewSingularTrim(brep.m_V[top_vertex_index[lti]], top_loop, bottom_trim.m_iso, top_c2i ).m_trim_index;
00446 }
00447 else if ( bottom_trim.m_type != ON_BrepTrim::singular && top_edge_index[lti] >= 0 && top_edge_index[lti] < brep.m_E.Count() )
00448 {
00449 ON_BrepEdge& top_edge = brep.m_E[top_edge_index[lti]];
00450 top_trim_index = brep.NewTrim( top_edge, top_trim_bRev3d[lti], top_loop, top_c2i ).m_trim_index;
00451 }
00452 else
00453 {
00454 ON_ERROR("ON_BrepExtrudeHelper_MakeTopLoop ran into capping trouble.");
00455 rc = false;
00456 break;
00457 }
00458 ON_BrepTrim& top_trim = brep.m_T[top_trim_index];
00459 top_trim.m_pline = bottom_trim.m_pline;
00460 top_trim.m_pbox = bottom_trim.m_pbox;
00461 top_trim.m_iso = bottom_trim.m_iso;
00462 top_trim.m_type = bottom_trim.m_type;
00463 top_trim.m_tolerance[0] = bottom_trim.m_tolerance[0];
00464 top_trim.m_tolerance[1] = bottom_trim.m_tolerance[1];
00465 top_trim.m__legacy_2d_tol = bottom_trim.m__legacy_2d_tol;
00466 top_trim.m__legacy_3d_tol = bottom_trim.m__legacy_2d_tol;
00467 top_trim.m__legacy_flags = bottom_trim.m__legacy_flags;
00468 }
00469 if (rc)
00470 {
00471 top_loop.m_pbox = bottom_loop.m_pbox;
00472 }
00473 return rc;
00474 }
00475
00476 static
00477 bool ON_BrepExtrudeHelper_CheckLoop( const ON_Brep& brep, int loop_index )
00478 {
00479 bool rc = false;
00480 if ( loop_index >= 0 )
00481 {
00482 ON_BrepLoop::TYPE loop_type = brep.m_L[loop_index].m_type;
00483 if ( loop_type == ON_BrepLoop::inner || loop_type == ON_BrepLoop::outer )
00484 rc = true;
00485 }
00486 return rc;
00487 }
00488
00489 static
00490 bool ON_BrepExtrudeHelper_MakeCap(
00491 ON_Brep& brep,
00492 int bottom_loop_index,
00493 const ON_3dVector path_vector,
00494 const int* side_face_index
00495 )
00496 {
00497 bool bCap = true;
00498
00499 if ( !ON_BrepExtrudeHelper_CheckLoop( brep, bottom_loop_index ) )
00500 return false;
00501 brep.m_F.Reserve(brep.m_F.Count() + 1);
00502 brep.m_L.Reserve(brep.m_L.Count() + 1);
00503 const ON_BrepLoop& bottom_loop = brep.m_L[bottom_loop_index];
00504 const ON_BrepFace& bottom_face = brep.m_F[bottom_loop.m_fi];
00505 const ON_Surface* bottom_surface = bottom_face.SurfaceOf();
00506 ON_Surface* top_surface = bottom_surface->Duplicate();
00507 top_surface->Translate( path_vector );
00508 int top_surface_index = brep.AddSurface( top_surface );
00509 ON_BrepFace& top_face = brep.NewFace( top_surface_index );
00510
00511 bCap = ON_BrepExtrudeHelper_MakeTopLoop( brep, top_face, bottom_loop_index, path_vector, side_face_index );
00512 if ( bCap )
00513 {
00514 ON_BrepLoop& top_loop = brep.m_L[brep.m_L.Count()-1];
00515 if ( bottom_loop.m_type == ON_BrepLoop::inner )
00516 {
00517
00518
00519 brep.FlipLoop(top_loop);
00520 }
00521 else if ( bottom_loop.m_type == ON_BrepLoop::outer )
00522 {
00523
00524
00525 brep.FlipFace(top_face);
00526 }
00527 }
00528 else
00529 {
00530
00531 brep.DeleteFace( top_face, false );
00532 delete brep.m_S[top_surface_index];
00533 brep.m_S[top_surface_index] = 0;
00534 }
00535 return bCap;
00536 }
00537
00538
00539
00540 int ON_BrepExtrudeFace(
00541 ON_Brep& brep,
00542 int face_index,
00543 const ON_Curve& path_curve,
00544 bool bCap
00545 )
00546 {
00547 int rc = 0;
00548
00549 if ( face_index < 0 || face_index >= brep.m_F.Count() )
00550 return false;
00551
00552 const int face_loop_count = brep.m_F[face_index].m_li.Count();
00553 if ( face_loop_count < 1 )
00554 return false;
00555
00556
00557 if ( brep.m_F[face_index].m_li.Count() == 1 )
00558 {
00559 rc = ON_BrepExtrudeLoop( brep, brep.m_F[face_index].m_li[0], path_curve, bCap );
00560 }
00561 else
00562 {
00563 ON_3dVector path_vector;
00564 ON_SimpleArray<int> side_face_index;
00565 ON_SimpleArray<int> side_face_index_loop_mark;
00566 int li, fli;
00567
00568 if ( !ON_BrepExtrudeHelper_CheckPathCurve( path_curve, path_vector ) )
00569 return 0;
00570
00571
00572 const int loop_count0 = brep.m_L.Count();
00573 const int face_count0 = brep.m_F.Count();
00574
00575
00576
00577 int new_side_trim_count = 0;
00578 for ( fli = 0; fli < face_loop_count; fli++ )
00579 {
00580 li = brep.m_F[face_index].m_li[fli];
00581 if ( li < 0 || li >= loop_count0 )
00582 return false;
00583 if ( !ON_BrepExtrudeHelper_CheckLoop( brep, li ) )
00584 continue;
00585 new_side_trim_count += brep.m_L[li].m_ti.Count();
00586 }
00587 if ( new_side_trim_count == 0 )
00588 return false;
00589 ON_BrepExtrudeHelper_ReserveSpace( brep, new_side_trim_count, bCap?1:0 );
00590
00591 side_face_index.Reserve(new_side_trim_count);
00592 side_face_index_loop_mark.Reserve(face_loop_count);
00593
00594 const ON_BrepFace& face = brep.m_F[face_index];
00595
00596 rc = true;
00597 int outer_loop_index = -1;
00598 int outer_fli = -1;
00599 for ( fli = 0; fli < face_loop_count && rc; fli++ )
00600 {
00601 side_face_index_loop_mark.Append( side_face_index.Count() );
00602 li = face.m_li[fli];
00603 if ( !ON_BrepExtrudeHelper_CheckLoop( brep, li ) )
00604 continue;
00605 ON_BrepLoop& loop = brep.m_L[li];
00606 if ( bCap && loop.m_type == ON_BrepLoop::outer )
00607 {
00608 if ( outer_loop_index >= 0 )
00609 bCap = false;
00610 else
00611 {
00612 outer_loop_index = li;
00613 outer_fli = fli;
00614 }
00615 }
00616 rc = ON_BrepExtrudeHelper_MakeSides( brep, li, path_curve, bCap, side_face_index );
00617 }
00618
00619 if ( bCap && rc && outer_loop_index >= 0 )
00620 {
00621 const int face_count1 = brep.m_F.Count();
00622 bCap = ON_BrepExtrudeHelper_MakeCap(
00623 brep,
00624 outer_loop_index,
00625 path_vector,
00626 side_face_index.Array() + side_face_index_loop_mark[outer_fli] );
00627 if ( bCap && brep.m_F.Count() > face_count1)
00628 {
00629
00630 rc = 2;
00631
00632 ON_BrepFace& cap_face = brep.m_F[brep.m_F.Count()-1];
00633 for ( fli = 0; fli < face_loop_count && rc; fli++ )
00634 {
00635 li = face.m_li[fli];
00636 if ( li == outer_loop_index )
00637 continue;
00638 if ( !ON_BrepExtrudeHelper_CheckLoop( brep, li ) )
00639 continue;
00640 if ( ON_BrepExtrudeHelper_MakeTopLoop(
00641 brep,
00642 cap_face,
00643 li,
00644 path_vector,
00645 side_face_index.Array() + side_face_index_loop_mark[fli] ) )
00646 {
00647 ON_BrepLoop& top_loop = brep.m_L[brep.m_L.Count()-1];
00648 top_loop.m_type = brep.m_L[li].m_type;
00649 }
00650 }
00651 }
00652 }
00653
00654 if ( brep.m_F[face_index].m_bRev )
00655 {
00656 for ( int fi = face_count0; fi < brep.m_F.Count(); fi++ )
00657 {
00658 brep.FlipFace(brep.m_F[fi]);
00659 }
00660 }
00661 }
00662
00663 return rc;
00664 }
00665
00666
00667 int ON_BrepExtrudeLoop(
00668 ON_Brep& brep,
00669 int loop_index,
00670 const ON_Curve& path_curve,
00671 bool bCap
00672 )
00673 {
00674 ON_SimpleArray<int> side_face_index;
00675 ON_3dVector path_vector;
00676
00677 const int face_count0 = brep.m_F.Count();
00678
00679 if ( loop_index < 0 || loop_index >= brep.m_L.Count() )
00680 return false;
00681
00682 if ( !ON_BrepExtrudeHelper_CheckPathCurve(path_curve,path_vector) )
00683 return false;
00684
00685
00686 if ( brep.m_L[loop_index].m_type != ON_BrepLoop::outer && brep.m_L[loop_index].m_type != ON_BrepLoop::inner )
00687 bCap = false;
00688
00689
00690 if ( !ON_BrepExtrudeHelper_MakeSides( brep, loop_index, path_curve, bCap, side_face_index ) )
00691 return false;
00692
00693
00694 if ( bCap )
00695 bCap = ON_BrepExtrudeHelper_MakeCap( brep, loop_index, path_vector, side_face_index.Array() );
00696
00697 const ON_BrepLoop& loop = brep.m_L[loop_index];
00698 if ( loop.m_fi >= 0 && loop.m_fi < brep.m_F.Count() && brep.m_F[loop.m_fi].m_bRev )
00699 {
00700 for ( int fi = face_count0; fi < brep.m_F.Count(); fi++ )
00701 {
00702 brep.FlipFace( brep.m_F[fi] );
00703 }
00704 }
00705
00706 return (bCap?2:1);
00707 }
00708
00709
00710
00711 int ON_BrepExtrudeEdge(
00712 ON_Brep& brep,
00713 int edge_index,
00714 const ON_Curve& path_curve
00715 )
00716 {
00717 ON_3dVector path_vector;
00718
00719 if ( edge_index < 0 && edge_index >= brep.m_E.Count() )
00720 return false;
00721
00722 if ( !ON_BrepExtrudeHelper_CheckPathCurve(path_curve,path_vector) )
00723 return false;
00724
00725
00726
00727 bool bRev = false;
00728 ON_SumSurface* sum_srf = ON_BrepExtrudeHelper_MakeSumSrf(
00729 path_curve, brep.m_E[edge_index], bRev );
00730
00731 if ( !sum_srf )
00732 return false;
00733
00734 int vid[4], eid[4], bRev3d[4];
00735
00736 vid[0] = brep.m_E[edge_index].m_vi[bRev?0:1];
00737 vid[1] = brep.m_E[edge_index].m_vi[bRev?1:0];
00738 vid[2] = -1;
00739 vid[3] = -1;
00740
00741 eid[0] = edge_index;
00742 eid[1] = -1;
00743 eid[2] = -1;
00744 eid[3] = -1;
00745
00746 bRev3d[0] = bRev?0:1;
00747 bRev3d[1] = 0;
00748 bRev3d[2] = 0;
00749 bRev3d[3] = 0;
00750
00751 return brep.NewFace( sum_srf, vid, eid, bRev3d ) ? true : false;
00752 }
00753
00754
00755 bool ON_BrepExtrude(
00756 ON_Brep& brep,
00757 const ON_Curve& path_curve,
00758 bool bCap
00759 )
00760 {
00761 ON_Workspace ws;
00762 const int vcount0 = brep.m_V.Count();
00763 const int tcount0 = brep.m_T.Count();
00764 const int lcount0 = brep.m_L.Count();
00765 const int ecount0 = brep.m_E.Count();
00766 const int fcount0 = brep.m_F.Count();
00767
00768 const ON_3dPoint PathStart = path_curve.PointAtStart();
00769 ON_3dPoint P = path_curve.PointAtEnd();
00770 if ( !PathStart.IsValid() || !P.IsValid() )
00771 return false;
00772 const ON_3dVector height = P - PathStart;
00773 if ( !height.IsValid() || height.Length() <= ON_ZERO_TOLERANCE )
00774 return false;
00775
00776 ON_Xform tr;
00777 tr.Translation(height);
00778
00779
00780 int side_count = 0;
00781 int i, vi, ei, fi;
00782 bool* bSideEdge = (bool*)ws.GetIntMemory(ecount0*sizeof(bSideEdge[0]));
00783 for ( ei = 0; ei < ecount0; ei++ )
00784 {
00785 const ON_BrepEdge& e = brep.m_E[ei];
00786 if ( 1 == e.m_ti.Count() )
00787 {
00788 side_count++;
00789 bSideEdge[ei] = true;
00790 }
00791 else
00792 {
00793 bSideEdge[ei] = false;
00794 }
00795 }
00796
00797 brep.m_V.Reserve( 2*vcount0 );
00798 i = 4*side_count + (bCap?tcount0:0);
00799 brep.m_T.Reserve( tcount0 + i );
00800 brep.m_C2.Reserve( brep.m_C2.Count() + i );
00801 brep.m_L.Reserve( lcount0 + side_count + (bCap?lcount0:0) );
00802 i = side_count + (bCap?ecount0:side_count);
00803 brep.m_E.Reserve( ecount0 + i );
00804 brep.m_C3.Reserve( brep.m_C3.Count() + i );
00805 i = side_count + (bCap?fcount0:0);
00806 brep.m_F.Reserve( fcount0 + i );
00807 brep.m_S.Reserve( brep.m_S.Count() + i );
00808
00809 bool bOK = true;
00810
00811
00812 int* topvimap = ws.GetIntMemory(vcount0);
00813 memset(topvimap,0,vcount0*sizeof(topvimap[0]));
00814 if ( bCap )
00815 {
00816 for ( vi = 0; vi < vcount0; vi++ )
00817 {
00818 const ON_BrepVertex& bottomv = brep.m_V[vi];
00819 ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance);
00820 topvimap[vi] = topv.m_vertex_index;
00821 }
00822 }
00823 else
00824 {
00825 for ( ei = 0; ei < ecount0; ei++ )
00826 {
00827 if ( bSideEdge[ei] )
00828 {
00829 const ON_BrepEdge& bottome = brep.m_E[ei];
00830 int bottomvi0 = bottome.m_vi[0];
00831 if ( bottomvi0 < 0 || bottomvi0 >= vcount0 )
00832 {
00833 bOK = false;
00834 break;
00835 }
00836 int bottomvi1 = bottome.m_vi[1];
00837 if ( bottomvi1 < 0 || bottomvi1 >= vcount0 )
00838 {
00839 bOK = false;
00840 break;
00841 }
00842 if ( !topvimap[bottomvi0] )
00843 {
00844 const ON_BrepVertex& bottomv = brep.m_V[bottomvi0];
00845 ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance);
00846 topvimap[bottomvi0] = topv.m_vertex_index;
00847 }
00848 if ( !topvimap[bottomvi1] )
00849 {
00850 const ON_BrepVertex& bottomv = brep.m_V[bottomvi1];
00851 ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance);
00852 topvimap[bottomvi1] = topv.m_vertex_index;
00853 }
00854 }
00855 }
00856 }
00857
00858
00859 int* topeimap = ws.GetIntMemory(ecount0);
00860 memset(topeimap,0,ecount0*sizeof(topeimap[0]));
00861 if ( bOK ) for ( ei = 0; ei < ecount0; ei++ )
00862 {
00863 if ( bCap || bSideEdge[ei] )
00864 {
00865 const ON_BrepEdge& bottome = brep.m_E[ei];
00866 ON_BrepVertex& topv0 = brep.m_V[topvimap[bottome.m_vi[0]]];
00867 ON_BrepVertex& topv1 = brep.m_V[topvimap[bottome.m_vi[1]]];
00868 ON_Curve* c3 = bottome.DuplicateCurve();
00869 if ( !c3 )
00870 {
00871 bOK = false;
00872 break;
00873 }
00874 c3->Transform(tr);
00875 int c3i = brep.AddEdgeCurve(c3);
00876 ON_BrepEdge& tope = brep.NewEdge(topv0,topv1,c3i,0,bottome.m_tolerance);
00877 topeimap[ei] = tope.m_edge_index;
00878 }
00879 }
00880
00881
00882 int* sideveimap = ws.GetIntMemory(vcount0);
00883 memset(sideveimap,0,vcount0*sizeof(sideveimap[0]));
00884 if ( bOK ) for ( vi = 0; vi < vcount0; vi++ )
00885 {
00886 ON_BrepVertex& bottomv = brep.m_V[vi];
00887 for ( int vei = 0; vei < bottomv.m_ei.Count(); vei++ )
00888 {
00889 if ( bSideEdge[bottomv.m_ei[vei]] && topvimap[vi] )
00890 {
00891 ON_BrepVertex& topv = brep.m_V[topvimap[vi]];
00892 ON_Curve* c3 = path_curve.DuplicateCurve();
00893 if ( !c3 )
00894 {
00895 bOK = false;
00896 }
00897 else
00898 {
00899 ON_3dVector D = bottomv.point - PathStart;
00900 c3->Translate(D);
00901 int c3i = brep.AddEdgeCurve(c3);
00902 const ON_BrepEdge& e = brep.NewEdge(bottomv,topv,c3i,0,0.0);
00903 sideveimap[vi] = e.m_edge_index;
00904 }
00905 break;
00906 }
00907 }
00908 }
00909
00910 if ( bOK && bCap )
00911 {
00912
00913 for (fi = 0; fi < fcount0; fi++ )
00914 {
00915 const ON_BrepFace& bottomf = brep.m_F[fi];
00916 ON_Surface* srf = bottomf.DuplicateSurface();
00917 if ( !srf )
00918 {
00919 bOK = false;
00920 break;
00921 }
00922 srf->Transform(tr);
00923 int si = brep.AddSurface(srf);
00924 ON_BrepFace& topf = brep.NewFace(si);
00925 topf.m_bRev = !bottomf.m_bRev;
00926 const int loop_count = bottomf.m_li.Count();
00927 topf.m_li.Reserve(loop_count);
00928 for ( int fli = 0; fli < loop_count; fli++ )
00929 {
00930 const ON_BrepLoop& bottoml = brep.m_L[bottomf.m_li[fli]];
00931 ON_BrepLoop& topl = brep.NewLoop(bottoml.m_type,topf);
00932 const int loop_trim_count = bottoml.m_ti.Count();
00933 topl.m_ti.Reserve(loop_trim_count);
00934 for ( int lti = 0; lti < loop_trim_count; lti++ )
00935 {
00936 const ON_BrepTrim& bottomt = brep.m_T[bottoml.m_ti[lti]];
00937 ON_NurbsCurve* c2 = ON_NurbsCurve::New();
00938 if ( !bottomt.GetNurbForm(*c2) )
00939 {
00940 delete c2;
00941 bOK = false;
00942 break;
00943 }
00944 int c2i = brep.AddTrimCurve(c2);
00945 ON_BrepTrim* topt = 0;
00946 if ( bottomt.m_ei >= 0 )
00947 {
00948 ON_BrepEdge& tope = brep.m_E[topeimap[bottomt.m_ei]];
00949 topt = &brep.NewTrim(tope,bottomt.m_bRev3d,topl,c2i);
00950 }
00951 else
00952 {
00953
00954 ON_BrepVertex& topv = brep.m_V[topvimap[bottomt.m_vi[0]]];
00955 topt = &brep.NewSingularTrim(topv,topl,bottomt.m_iso,c2i);
00956 }
00957 topt->m_tolerance[0] = bottomt.m_tolerance[0];
00958 topt->m_tolerance[1] = bottomt.m_tolerance[1];
00959 topt->m_pbox = bottomt.m_pbox;
00960 topt->m_type = bottomt.m_type;
00961 topt->m_iso = bottomt.m_iso;
00962 }
00963 topl.m_pbox = bottoml.m_pbox;
00964 }
00965 }
00966 }
00967
00968
00969 int bRev3d[4] = {0,0,1,1};
00970 int vid[4], eid[4];
00971 if( bOK ) for ( ei = 0; ei < ecount0; ei++ )
00972 {
00973 if ( bSideEdge[ei] && topeimap[ei] )
00974 {
00975 ON_BrepEdge& bottome = brep.m_E[ei];
00976 ON_BrepEdge& tope = brep.m_E[topeimap[ei]];
00977 vid[0] = bottome.m_vi[0];
00978 vid[1] = bottome.m_vi[1];
00979 vid[2] = topvimap[vid[1]];
00980 vid[3] = topvimap[vid[0]];
00981 if ( sideveimap[vid[0]] && sideveimap[vid[1]] )
00982 {
00983 ON_BrepEdge& leftedge = brep.m_E[sideveimap[vid[0]]];
00984 ON_BrepEdge& rightedge = brep.m_E[sideveimap[vid[1]]];
00985 ON_Curve* cx = bottome.DuplicateCurve();
00986 if ( !cx )
00987 {
00988 bOK = false;
00989 break;
00990 }
00991 ON_Curve* cy = leftedge.DuplicateCurve();
00992 if ( !cy )
00993 {
00994 delete cx;
00995 bOK = false;
00996 break;
00997 }
00998 ON_SumSurface* srf = new ON_SumSurface();
00999 srf->m_curve[0] = cx;
01000 srf->m_curve[1] = cy;
01001 srf->m_basepoint = srf->m_curve[1]->PointAtStart();
01002 srf->m_basepoint.x = -srf->m_basepoint.x;
01003 srf->m_basepoint.y = -srf->m_basepoint.y;
01004 srf->m_basepoint.z = -srf->m_basepoint.z;
01005 eid[0] = bottome.m_edge_index;
01006 eid[1] = rightedge.m_edge_index;
01007 eid[2] = tope.m_edge_index;
01008 eid[3] = leftedge.m_edge_index;
01009 ON_BrepFace* face = brep.NewFace(srf,vid,eid,bRev3d);
01010 if ( !face )
01011 {
01012 bOK = false;
01013 break;
01014 }
01015 else if ( bottome.m_ti.Count() == 2 )
01016 {
01017 const ON_BrepTrim& trim0 = brep.m_T[bottome.m_ti[0]];
01018 const ON_BrepTrim& trim1 = brep.m_T[bottome.m_ti[1]];
01019 const ON_BrepLoop& loop0 = brep.m_L[trim0.m_li];
01020 const ON_BrepLoop& loop1 = brep.m_L[trim1.m_li];
01021 bool bBottomFaceRev = brep.m_F[(loop0.m_fi != face->m_face_index) ? loop0.m_fi : loop1.m_fi].m_bRev;
01022 bool bSideFaceRev = ( trim0.m_bRev3d != trim1.m_bRev3d )
01023 ? bBottomFaceRev
01024 : !bBottomFaceRev;
01025 face->m_bRev = bSideFaceRev;
01026 }
01027 }
01028 }
01029 }
01030
01031 if ( !bOK )
01032 {
01033 for ( vi = brep.m_V.Count(); vi >= vcount0; vi-- )
01034 {
01035 brep.DeleteVertex(brep.m_V[vi]);
01036 }
01037 }
01038
01039 return bOK;
01040 }
01041
01042
01043
01044 int ON_BrepExtrudeVertex(
01045 ON_Brep& brep,
01046 int vertex_index,
01047 const ON_Curve& path_curve
01048 )
01049 {
01050 ON_3dVector path_vector;
01051 if ( vertex_index < 0 && vertex_index >= brep.m_V.Count() )
01052 return false;
01053 if ( !ON_BrepExtrudeHelper_CheckPathCurve(path_curve,path_vector) )
01054 return false;
01055 ON_Curve* c3 = path_curve.Duplicate();
01056 brep.m_V.Reserve( brep.m_V.Count() + 1 );
01057 ON_BrepVertex& v0 = brep.m_V[vertex_index];
01058 ON_BrepVertex& v1 = brep.NewVertex( v0.point + path_vector, 0.0 );
01059 c3->Translate( v0.point - c3->PointAtStart() );
01060 int c3i = brep.AddEdgeCurve( c3 );
01061 ON_BrepEdge& edge = brep.NewEdge( v0, v1, c3i );
01062 edge.m_tolerance = 0.0;
01063 return true;
01064 }
01065
01066
01067 int ON_BrepConeFace(
01068 ON_Brep& brep,
01069 int face_index,
01070 ON_3dPoint apex_point
01071 )
01072 {
01073 int rc = 0;
01074
01075 if ( face_index < 0 || face_index >= brep.m_F.Count() )
01076 return false;
01077
01078 const int face_loop_count = brep.m_F[face_index].m_li.Count();
01079 if ( face_loop_count < 1 )
01080 return false;
01081
01082 if ( brep.m_F[face_index].m_li.Count() == 1 )
01083 {
01084 rc = ON_BrepConeLoop( brep, brep.m_F[face_index].m_li[0], apex_point );
01085 }
01086 else
01087 {
01088 int li, fli;
01089
01090
01091 const int loop_count0 = brep.m_L.Count();
01092
01093
01094
01095
01096 int new_side_trim_count = 0;
01097 for ( fli = 0; fli < face_loop_count; fli++ )
01098 {
01099 li = brep.m_F[face_index].m_li[fli];
01100 if ( li < 0 || li >= loop_count0 )
01101 return false;
01102 if ( !ON_BrepExtrudeHelper_CheckLoop( brep, li ) )
01103 continue;
01104 new_side_trim_count += brep.m_L[li].m_ti.Count();
01105 }
01106 if ( new_side_trim_count == 0 )
01107 return false;
01108 ON_BrepExtrudeHelper_ReserveSpace( brep, new_side_trim_count, 0 );
01109
01110 const ON_BrepFace& face = brep.m_F[face_index];
01111
01112
01113 brep.NewVertex( apex_point, 0.0 );
01114
01115 rc = true;
01116 for ( fli = 0; fli < face_loop_count && rc; fli++ )
01117 {
01118 li = face.m_li[fli];
01119 if ( !ON_BrepExtrudeHelper_CheckLoop( brep, li ) )
01120 continue;
01121
01122 rc = ON_BrepConeLoop( brep, li, apex_point );
01123 }
01124 }
01125
01126 return rc;
01127 }
01128
01129
01130 bool ON_BrepConeLoop(
01131 ON_Brep& brep,
01132 int loop_index,
01133 ON_3dPoint apex_point
01134 )
01135 {
01136 if ( loop_index < 0 && loop_index >= brep.m_L.Count() )
01137 return false;
01138
01139 int lti, ti, i, vid[4], eid[4], bRev3d[4];
01140
01141
01142
01143
01144
01145
01146 const int loop_trim_count = brep.m_L[loop_index].m_ti.Count();
01147 if ( loop_trim_count == 0 )
01148 return false;
01149
01150
01151 const int trim_count0 = brep.m_T.Count();
01152 const int edge_count0 = brep.m_E.Count();
01153
01154 ON_BrepExtrudeHelper_ReserveSpace( brep, loop_trim_count, 0 );
01155
01156 int prev_face_index = -1;
01157 int first_face_east_trim_index = -1;
01158
01159 ON_BrepVertex& apex_vertex = brep.NewVertex( apex_point, 0.0 );
01160
01161 for ( lti = 0; lti < loop_trim_count; lti++ )
01162 {
01163 ON_NurbsSurface* cone_srf = 0;
01164 ti = brep.m_L[loop_index].m_ti[lti];
01165 if ( ti < 0 || ti >= trim_count0 )
01166 continue;
01167
01168 for ( i = 0; i < 4; i++ )
01169 {
01170 vid[i] = -1;
01171 eid[i] = -1;
01172 }
01173 bRev3d[0] = false;
01174 bRev3d[1] = false;
01175 bRev3d[2] = false;
01176 bRev3d[3] = false;
01177
01178
01179
01180 {
01181 ON_BrepTrim& trim = brep.m_T[ti];
01182 if ( trim.m_ei >= 0 && trim.m_ei < edge_count0 )
01183 {
01184 const ON_BrepEdge& base_edge = brep.m_E[trim.m_ei];
01185
01186
01187 vid[0] = trim.m_vi[1];
01188 vid[1] = trim.m_vi[0];
01189 eid[0] = base_edge.m_edge_index;
01190 bRev3d[0] = (trim.m_bRev3d?false:true);
01191 cone_srf = ON_BrepExtrudeHelper_MakeConeSrf( apex_point, base_edge, bRev3d[0] );
01192 }
01193 }
01194 if ( !cone_srf )
01195 continue;
01196 vid[2] = apex_vertex.m_vertex_index;
01197 vid[3] = apex_vertex.m_vertex_index;
01198
01199 if ( prev_face_index >= 0 )
01200 {
01201 const ON_BrepTrim& prev_west_trim = brep.m_T[ brep.m_L[ brep.m_F[prev_face_index].m_li[0]].m_ti[3] ];
01202 vid[2] = prev_west_trim.m_vi[0];
01203 eid[1] = prev_west_trim.m_ei;
01204 bRev3d[1] = (prev_west_trim.m_bRev3d?false:true);
01205 }
01206 if ( first_face_east_trim_index >= 0 && brep.m_T[first_face_east_trim_index].m_vi[0] == vid[0] )
01207 {
01208 const ON_BrepTrim& first_face_east_trim = brep.m_T[first_face_east_trim_index];
01209 vid[3] = first_face_east_trim.m_vi[1];
01210 eid[3] = first_face_east_trim.m_ei;
01211 bRev3d[3] = (first_face_east_trim.m_bRev3d?false:true);
01212 }
01213 const ON_BrepFace* side_face = brep.NewFace(cone_srf,vid,eid,bRev3d);
01214 if ( side_face )
01215 {
01216 prev_face_index = side_face->m_face_index;
01217 if ( first_face_east_trim_index < 0 )
01218 first_face_east_trim_index = brep.m_L[ side_face->m_li[0] ].m_ti[1];
01219 }
01220 }
01221
01222 return true;
01223 }
01224
01225
01226
01227 int ON_BrepConeEdge(
01228 ON_Brep& brep,
01229 int edge_index,
01230 ON_3dPoint apex_point
01231 )
01232 {
01233
01234
01235 if ( edge_index < 0 && edge_index >= brep.m_E.Count() )
01236 return false;
01237
01238
01239 ON_NurbsSurface* cone_srf = ON_BrepExtrudeHelper_MakeConeSrf(
01240 apex_point, brep.m_E[edge_index], false );
01241
01242 if ( !cone_srf )
01243 return false;
01244
01245 int vid[4], eid[4], bRev3d[4];
01246
01247 vid[0] = brep.m_E[edge_index].m_vi[0];
01248 vid[1] = brep.m_E[edge_index].m_vi[1];
01249 vid[2] = -1;
01250 vid[3] = -1;
01251
01252 eid[0] = edge_index;
01253 eid[1] = -1;
01254 eid[2] = -1;
01255 eid[3] = -1;
01256
01257 bRev3d[0] = 0;
01258 bRev3d[1] = 0;
01259 bRev3d[2] = 0;
01260 bRev3d[3] = 0;
01261
01262 return brep.NewFace( cone_srf, vid, eid, bRev3d ) ? true : false;
01263 }
01264