1f220fa62Smrg/* 2f220fa62Smrg** License Applicability. Except to the extent portions of this file are 3f220fa62Smrg** made subject to an alternative license as permitted in the SGI Free 4f220fa62Smrg** Software License B, Version 1.1 (the "License"), the contents of this 5f220fa62Smrg** file are subject only to the provisions of the License. You may not use 6f220fa62Smrg** this file except in compliance with the License. You may obtain a copy 7f220fa62Smrg** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 8f220fa62Smrg** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: 9f220fa62Smrg** 10f220fa62Smrg** http://oss.sgi.com/projects/FreeB 11f220fa62Smrg** 12f220fa62Smrg** Note that, as provided in the License, the Software is distributed on an 13f220fa62Smrg** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS 14f220fa62Smrg** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND 15f220fa62Smrg** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A 16f220fa62Smrg** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. 17f220fa62Smrg** 18f220fa62Smrg** Original Code. The Original Code is: OpenGL Sample Implementation, 19f220fa62Smrg** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, 20f220fa62Smrg** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. 21f220fa62Smrg** Copyright in any portions created by third parties is as indicated 22f220fa62Smrg** elsewhere herein. All Rights Reserved. 23f220fa62Smrg** 24f220fa62Smrg** Additional Notice Provisions: The application programming interfaces 25f220fa62Smrg** established by SGI in conjunction with the Original Code are The 26f220fa62Smrg** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released 27f220fa62Smrg** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version 28f220fa62Smrg** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X 29f220fa62Smrg** Window System(R) (Version 1.3), released October 19, 1998. This software 30f220fa62Smrg** was created using the OpenGL(R) version 1.2.1 Sample Implementation 31f220fa62Smrg** published by SGI, but has not been independently verified as being 32f220fa62Smrg** compliant with the OpenGL(R) version 1.2.1 Specification. 33f220fa62Smrg*/ 34f220fa62Smrg 35f220fa62Smrg/* 36f220fa62Smrg * subdivider.cxx 37f220fa62Smrg * 38f220fa62Smrg */ 39f220fa62Smrg 40f220fa62Smrg#include "glimports.h" 41f220fa62Smrg#include "myassert.h" 42f220fa62Smrg#include "mystdio.h" 43f220fa62Smrg#include "subdivider.h" 44f220fa62Smrg#include "arc.h" 45f220fa62Smrg#include "bezierarc.h" 46f220fa62Smrg#include "bin.h" 47f220fa62Smrg#include "renderhints.h" 48f220fa62Smrg#include "backend.h" 49f220fa62Smrg#include "mapdesc.h" 50f220fa62Smrg#include "quilt.h" 51f220fa62Smrg#include "patchlist.h" 52f220fa62Smrg#include "patch.h" 53f220fa62Smrg#include "nurbsconsts.h" 54f220fa62Smrg#include "trimvertpool.h" 55f220fa62Smrg#include "simplemath.h" 56f220fa62Smrg 57f220fa62Smrg#include "polyUtil.h" //for function area() 58f220fa62Smrg 59f220fa62Smrg//#define PARTITION_TEST 60f220fa62Smrg#ifdef PARTITION_TEST 61f220fa62Smrg#include "partitionY.h" 62f220fa62Smrg#include "monoTriangulation.h" 63f220fa62Smrg#include "dataTransform.h" 64f220fa62Smrg#include "monoChain.h" 65f220fa62Smrg 66f220fa62Smrg#endif 67f220fa62Smrg 68f220fa62Smrg 69f220fa62Smrg#define OPTIMIZE_UNTRIMED_CASE 70f220fa62Smrg 71f220fa62Smrg 72f220fa62SmrgBin* 73f220fa62SmrgSubdivider::makePatchBoundary( const REAL *from, const REAL *to ) 74f220fa62Smrg{ 75f220fa62Smrg Bin* ret = new Bin(); 76f220fa62Smrg REAL smin = from[0]; 77f220fa62Smrg REAL smax = to[0]; 78f220fa62Smrg REAL tmin = from[1]; 79f220fa62Smrg REAL tmax = to[1]; 80f220fa62Smrg 81f220fa62Smrg pjarc = 0; 82f220fa62Smrg 83f220fa62Smrg Arc_ptr jarc = new(arcpool) Arc( arc_bottom, 0 ); 84f220fa62Smrg arctessellator.bezier( jarc, smin, smax, tmin, tmin ); 85f220fa62Smrg ret->addarc( jarc ); 86f220fa62Smrg pjarc = jarc->append( pjarc ); 87f220fa62Smrg 88f220fa62Smrg jarc = new(arcpool) Arc( arc_right, 0 ); 89f220fa62Smrg arctessellator.bezier( jarc, smax, smax, tmin, tmax ); 90f220fa62Smrg ret->addarc( jarc ); 91f220fa62Smrg pjarc = jarc->append( pjarc ); 92f220fa62Smrg 93f220fa62Smrg jarc = new(arcpool) Arc( arc_top, 0 ); 94f220fa62Smrg arctessellator.bezier( jarc, smax, smin, tmax, tmax ); 95f220fa62Smrg ret->addarc( jarc ); 96f220fa62Smrg pjarc = jarc->append( pjarc ); 97f220fa62Smrg 98f220fa62Smrg jarc = new(arcpool) Arc( arc_left, 0 ); 99f220fa62Smrg arctessellator.bezier( jarc, smin, smin, tmax, tmin ); 100f220fa62Smrg ret->addarc( jarc ); 101f220fa62Smrg jarc->append( pjarc ); 102f220fa62Smrg 103f220fa62Smrg assert( jarc->check() != 0 ); 104f220fa62Smrg return ret; 105f220fa62Smrg} 106f220fa62Smrg 107f220fa62Smrg/*--------------------------------------------------------------------------- 108f220fa62Smrg * Subdivider - construct a subdivider 109f220fa62Smrg *--------------------------------------------------------------------------- 110f220fa62Smrg */ 111f220fa62Smrg 112f220fa62SmrgSubdivider::Subdivider( Renderhints& r, Backend& b ) 113f220fa62Smrg : slicer( b ), 114f220fa62Smrg arctessellator( trimvertexpool, pwlarcpool ), 115f220fa62Smrg arcpool( sizeof( Arc), 1, "arcpool" ), 116f220fa62Smrg bezierarcpool( sizeof( BezierArc ), 1, "Bezarcpool" ), 117f220fa62Smrg pwlarcpool( sizeof( PwlArc ), 1, "Pwlarcpool" ), 118f220fa62Smrg renderhints( r ), 119f220fa62Smrg backend( b ) 120f220fa62Smrg{ 121f220fa62Smrg} 122f220fa62Smrg 123f220fa62Smrgvoid 124f220fa62SmrgSubdivider::setJumpbuffer( JumpBuffer *j ) 125f220fa62Smrg{ 126f220fa62Smrg jumpbuffer = j; 127f220fa62Smrg} 128f220fa62Smrg 129f220fa62Smrg/*--------------------------------------------------------------------------- 130f220fa62Smrg * clear - reset all state after possible error condition 131f220fa62Smrg *--------------------------------------------------------------------------- 132f220fa62Smrg */ 133f220fa62Smrg 134f220fa62Smrgvoid 135f220fa62SmrgSubdivider::clear( void ) 136f220fa62Smrg{ 137f220fa62Smrg trimvertexpool.clear(); 138f220fa62Smrg arcpool.clear(); 139f220fa62Smrg pwlarcpool.clear(); 140f220fa62Smrg bezierarcpool.clear(); 141f220fa62Smrg} 142f220fa62Smrg 143f220fa62Smrg/*--------------------------------------------------------------------------- 144f220fa62Smrg * ~Subdivider - destroy a subdivider 145f220fa62Smrg *--------------------------------------------------------------------------- 146f220fa62Smrg */ 147f220fa62Smrg 148f220fa62SmrgSubdivider::~Subdivider( void ) 149f220fa62Smrg{ 150f220fa62Smrg} 151f220fa62Smrg 152f220fa62Smrg/*--------------------------------------------------------------------------- 153f220fa62Smrg * addArc - add a bezier arc to a trim loop and to a bin 154f220fa62Smrg *--------------------------------------------------------------------------- 155f220fa62Smrg */ 156f220fa62Smrgvoid 157f220fa62SmrgSubdivider::addArc( REAL *cpts, Quilt *quilt, long _nuid ) 158f220fa62Smrg{ 159f220fa62Smrg BezierArc *bezierArc = new(bezierarcpool) BezierArc; 160f220fa62Smrg Arc *jarc = new(arcpool) Arc( arc_none, _nuid ); 161f220fa62Smrg jarc->pwlArc = 0; 162f220fa62Smrg jarc->bezierArc = bezierArc; 163f220fa62Smrg bezierArc->order = quilt->qspec->order; 164f220fa62Smrg bezierArc->stride = quilt->qspec->stride; 165f220fa62Smrg bezierArc->mapdesc = quilt->mapdesc; 166f220fa62Smrg bezierArc->cpts = cpts; 167f220fa62Smrg initialbin.addarc( jarc ); 168f220fa62Smrg pjarc = jarc->append( pjarc ); 169f220fa62Smrg} 170f220fa62Smrg 171f220fa62Smrg/*--------------------------------------------------------------------------- 172f220fa62Smrg * addArc - add a pwl arc to a trim loop and to a bin 173f220fa62Smrg *--------------------------------------------------------------------------- 174f220fa62Smrg */ 175f220fa62Smrg 176f220fa62Smrgvoid 177f220fa62SmrgSubdivider::addArc( int npts, TrimVertex *pts, long _nuid ) 178f220fa62Smrg{ 179f220fa62Smrg Arc *jarc = new(arcpool) Arc( arc_none, _nuid ); 180f220fa62Smrg jarc->pwlArc = new(pwlarcpool) PwlArc( npts, pts ); 181f220fa62Smrg initialbin.addarc( jarc ); 182f220fa62Smrg pjarc = jarc->append( pjarc ); 183f220fa62Smrg} 184f220fa62Smrg 185f220fa62Smrgvoid 186f220fa62SmrgSubdivider::beginQuilts( void ) 187f220fa62Smrg{ 188f220fa62Smrg qlist = 0; 189f220fa62Smrg} 190f220fa62Smrg 191f220fa62Smrgvoid 192f220fa62SmrgSubdivider::addQuilt( Quilt *quilt ) 193f220fa62Smrg{ 194f220fa62Smrg quilt->next = qlist; 195f220fa62Smrg qlist = quilt; 196f220fa62Smrg} 197f220fa62Smrg 198f220fa62Smrg/*--------------------------------------------------------------------------- 199f220fa62Smrg * drawSurfaces - main entry point for surface tessellation 200f220fa62Smrg *--------------------------------------------------------------------------- 201f220fa62Smrg */ 202f220fa62Smrg 203f220fa62Smrgvoid 204f220fa62SmrgSubdivider::drawSurfaces( long nuid ) 205f220fa62Smrg{ 206f220fa62Smrg renderhints.init( ); 207f220fa62Smrg 208f220fa62Smrg if (qlist == NULL) 209f220fa62Smrg { 210f220fa62Smrg //initialbin could be nonempty due to some errors 211f220fa62Smrg freejarcs(initialbin); 212f220fa62Smrg return; 213f220fa62Smrg } 214f220fa62Smrg 215f220fa62Smrg for( Quilt *q = qlist; q; q = q->next ) { 216f220fa62Smrg if( q->isCulled( ) == CULL_TRIVIAL_REJECT ) { 217f220fa62Smrg freejarcs( initialbin ); 218f220fa62Smrg return; 219f220fa62Smrg } 220f220fa62Smrg } 221f220fa62Smrg 222f220fa62Smrg 223f220fa62Smrg REAL from[2], to[2]; 224f220fa62Smrg qlist->getRange( from, to, spbrkpts, tpbrkpts ); 225f220fa62Smrg#ifdef OPTIMIZE_UNTRIMED_CASE 226f220fa62Smrg //perform optimization only when the samplng method is 227f220fa62Smrg //DOMAIN_DISTANCE and the display methdo is either 228f220fa62Smrg //fill or outline_polygon. 229f220fa62Smrg int optimize = (is_domain_distance_sampling && (renderhints.display_method != N_OUTLINE_PATCH)); 230f220fa62Smrg#endif 231f220fa62Smrg 232f220fa62Smrg if( ! initialbin.isnonempty() ) { 233f220fa62Smrg#ifdef OPTIMIZE_UNTRIMED_CASE 234f220fa62Smrg if(! optimize ) 235f220fa62Smrg { 236f220fa62Smrg 237f220fa62Smrg makeBorderTrim( from, to ); 238f220fa62Smrg } 239f220fa62Smrg#else 240f220fa62Smrg makeBorderTrim( from, to ); 241f220fa62Smrg#endif 242f220fa62Smrg } else { 243f220fa62Smrg REAL rate[2]; 244f220fa62Smrg qlist->findRates( spbrkpts, tpbrkpts, rate ); 245f220fa62Smrg 246f220fa62Smrg if( decompose( initialbin, min(rate[0], rate[1]) ) ) 247f220fa62Smrg mylongjmp( jumpbuffer, 31 ); 248f220fa62Smrg } 249f220fa62Smrg 250f220fa62Smrg backend.bgnsurf( renderhints.wiretris, renderhints.wirequads, nuid ); 251f220fa62Smrg 252f220fa62Smrg#ifdef PARTITION_TEST 253f220fa62Smrg if( initialbin.isnonempty() && spbrkpts.end-2 == spbrkpts.start && 254f220fa62Smrg tpbrkpts.end-2 == tpbrkpts.start) 255f220fa62Smrg{ 256f220fa62Smrg for(int i=spbrkpts.start; i<spbrkpts.end-1; i++){ 257f220fa62Smrg for(int j=tpbrkpts.start; j<tpbrkpts.end-1; j++){ 258f220fa62Smrg Real pta[2], ptb[2]; 259f220fa62Smrg pta[0] = spbrkpts.pts[i]; 260f220fa62Smrg ptb[0] = spbrkpts.pts[i+1]; 261f220fa62Smrg pta[1] = tpbrkpts.pts[j]; 262f220fa62Smrg ptb[1] = tpbrkpts.pts[j+1]; 263f220fa62Smrg qlist->downloadAll(pta, ptb, backend); 264f220fa62Smrg 265f220fa62Smrg directedLine *poly; 266f220fa62Smrg 267f220fa62Smrg { 268f220fa62Smrg 269f220fa62Smrg poly = bin_to_DLineLoops(initialbin); 270f220fa62Smrg 271f220fa62Smrg poly=poly->deleteDegenerateLinesAllPolygons(); 272f220fa62Smrg 273f220fa62Smrg sampledLine* retSampledLines; 274f220fa62Smrg//printf("before MC_partition\n"); 275f220fa62Smrg poly = MC_partitionY(poly, &retSampledLines); 276f220fa62Smrg//printf("after MC_partition\n"); 277f220fa62Smrg 278f220fa62Smrg } 279f220fa62Smrg 280f220fa62Smrg 281f220fa62Smrg { 282f220fa62Smrg primStream pStream(5000,5000); 283f220fa62Smrg directedLine* temp; 284f220fa62Smrg 285f220fa62Smrg for(temp=poly; temp != NULL; temp=temp->getNextPolygon()) 286f220fa62Smrg 287f220fa62Smrg monoTriangulation(temp, &pStream); 288f220fa62Smrg 289f220fa62Smrg slicer.evalStream(&pStream); 290f220fa62Smrg 291f220fa62Smrg } 292f220fa62Smrg //need to clean up space 293f220fa62Smrg } 294f220fa62Smrg } 295f220fa62Smrg freejarcs( initialbin ); 296f220fa62Smrg backend.endsurf(); 297f220fa62Smrg return; 298f220fa62Smrg 299f220fa62Smrg /* 300f220fa62Smrg printf("num_polygons=%i\n", poly->numPolygons()); 301f220fa62Smrg printf("num_edges=%i\n", poly->numEdgesAllPolygons()); 302f220fa62Smrg poly->writeAllPolygons("zloutputFile"); 303f220fa62Smrg return; 304f220fa62Smrg { 305f220fa62Smrg primStream pStream(20,20); 306f220fa62Smrg for(directedLine* tempD = poly; tempD != NULL; tempD = tempD->getNextPolygon()) 307f220fa62Smrg monoTriangulation(tempD, &pStream); 308f220fa62Smrg } 309f220fa62Smrg return; 310f220fa62Smrg */ 311f220fa62Smrg} 312f220fa62Smrg#endif //PARTITION_TEST 313f220fa62Smrg 314f220fa62Smrg 315f220fa62Smrg#ifdef OPTIMIZE_UNTRIMED_CASE 316f220fa62Smrg if( (!initialbin.isnonempty()) && optimize ) 317f220fa62Smrg { 318f220fa62Smrg int i,j; 319f220fa62Smrg int num_u_steps; 320f220fa62Smrg int num_v_steps; 321f220fa62Smrg for(i=spbrkpts.start; i<spbrkpts.end-1; i++){ 322f220fa62Smrg for(j=tpbrkpts.start; j<tpbrkpts.end-1; j++){ 323f220fa62Smrg Real pta[2], ptb[2]; 324f220fa62Smrg pta[0] = spbrkpts.pts[i]; 325f220fa62Smrg ptb[0] = spbrkpts.pts[i+1]; 326f220fa62Smrg pta[1] = tpbrkpts.pts[j]; 327f220fa62Smrg ptb[1] = tpbrkpts.pts[j+1]; 328f220fa62Smrg qlist->downloadAll(pta, ptb, backend); 329f220fa62Smrg 330f220fa62Smrg num_u_steps = (int) (domain_distance_u_rate * (ptb[0]-pta[0])); 331f220fa62Smrg num_v_steps = (int) (domain_distance_v_rate * (ptb[1]-pta[1])); 332f220fa62Smrg 333f220fa62Smrg if(num_u_steps <= 0) num_u_steps = 1; 334f220fa62Smrg if(num_v_steps <= 0) num_v_steps = 1; 335f220fa62Smrg 336f220fa62Smrg backend.surfgrid(pta[0], ptb[0], num_u_steps, 337f220fa62Smrg ptb[1], pta[1], num_v_steps); 338f220fa62Smrg backend.surfmesh(0,0,num_u_steps,num_v_steps); 339f220fa62Smrg 340f220fa62Smrg 341f220fa62Smrg 342f220fa62Smrg continue; 343f220fa62Smrg /* the following is left for reference purpose, don't delete 344f220fa62Smrg { 345f220fa62Smrg Bin* tempSource; 346f220fa62Smrg Patchlist patchlist(qlist, pta, ptb); 347f220fa62Smrg patchlist.getstepsize(); 348f220fa62Smrg 349f220fa62Smrg tempSource=makePatchBoundary(pta, ptb); 350f220fa62Smrg 351f220fa62Smrg tessellation(*tempSource, patchlist); 352f220fa62Smrg 353f220fa62Smrg render(*tempSource); 354f220fa62Smrg delete tempSource; 355f220fa62Smrg } 356f220fa62Smrg */ 357f220fa62Smrg } 358f220fa62Smrg } 359f220fa62Smrg } 360f220fa62Smrg else 361f220fa62Smrg subdivideInS( initialbin ); 362f220fa62Smrg#else 363f220fa62Smrg 364f220fa62Smrg subdivideInS( initialbin ); 365f220fa62Smrg#endif 366f220fa62Smrg 367f220fa62Smrg backend.endsurf(); 368f220fa62Smrg 369f220fa62Smrg} 370f220fa62Smrg 371f220fa62Smrgvoid 372f220fa62SmrgSubdivider::subdivideInS( Bin& source ) 373f220fa62Smrg{ 374f220fa62Smrg if( renderhints.display_method == N_OUTLINE_PARAM ) { 375f220fa62Smrg outline( source ); 376f220fa62Smrg freejarcs( source ); 377f220fa62Smrg } else { 378f220fa62Smrg setArcTypeBezier(); 379f220fa62Smrg setNonDegenerate(); 380f220fa62Smrg splitInS( source, spbrkpts.start, spbrkpts.end ); 381f220fa62Smrg } 382f220fa62Smrg} 383f220fa62Smrg 384f220fa62Smrg 385f220fa62Smrg/*--------------------------------------------------------------------------- 386f220fa62Smrg * splitInS - split a patch and a bin by an isoparametric line 387f220fa62Smrg *--------------------------------------------------------------------------- 388f220fa62Smrg */ 389f220fa62Smrg 390f220fa62Smrgvoid 391f220fa62SmrgSubdivider::splitInS( Bin& source, int start, int end ) 392f220fa62Smrg{ 393f220fa62Smrg if( source.isnonempty() ) { 394f220fa62Smrg if( start != end ) { 395f220fa62Smrg int i = start + (end - start) / 2; 396f220fa62Smrg Bin left, right; 397f220fa62Smrg split( source, left, right, 0, spbrkpts.pts[i] ); 398f220fa62Smrg splitInS( left, start, i ); 399f220fa62Smrg splitInS( right, i+1, end ); 400f220fa62Smrg } else { 401f220fa62Smrg if( start == spbrkpts.start || start == spbrkpts.end ) { 402f220fa62Smrg freejarcs( source ); 403f220fa62Smrg } else if( renderhints.display_method == N_OUTLINE_PARAM_S ) { 404f220fa62Smrg outline( source ); 405f220fa62Smrg freejarcs( source ); 406f220fa62Smrg } else { 407f220fa62Smrg setArcTypeBezier(); 408f220fa62Smrg setNonDegenerate(); 409f220fa62Smrg s_index = start; 410f220fa62Smrg splitInT( source, tpbrkpts.start, tpbrkpts.end ); 411f220fa62Smrg } 412f220fa62Smrg } 413f220fa62Smrg } 414f220fa62Smrg} 415f220fa62Smrg 416f220fa62Smrg/*--------------------------------------------------------------------------- 417f220fa62Smrg * splitInT - split a patch and a bin by an isoparametric line 418f220fa62Smrg *--------------------------------------------------------------------------- 419f220fa62Smrg */ 420f220fa62Smrg 421f220fa62Smrgvoid 422f220fa62SmrgSubdivider::splitInT( Bin& source, int start, int end ) 423f220fa62Smrg{ 424f220fa62Smrg if( source.isnonempty() ) { 425f220fa62Smrg if( start != end ) { 426f220fa62Smrg int i = start + (end - start) / 2; 427f220fa62Smrg Bin left, right; 428f220fa62Smrg split( source, left, right, 1, tpbrkpts.pts[i] ); 429f220fa62Smrg splitInT( left, start, i ); 430f220fa62Smrg splitInT( right, i+1, end ); 431f220fa62Smrg } else { 432f220fa62Smrg if( start == tpbrkpts.start || start == tpbrkpts.end ) { 433f220fa62Smrg freejarcs( source ); 434f220fa62Smrg } else if( renderhints.display_method == N_OUTLINE_PARAM_ST ) { 435f220fa62Smrg outline( source ); 436f220fa62Smrg freejarcs( source ); 437f220fa62Smrg } else { 438f220fa62Smrg t_index = start; 439f220fa62Smrg setArcTypeBezier(); 440f220fa62Smrg setDegenerate(); 441f220fa62Smrg 442f220fa62Smrg REAL pta[2], ptb[2]; 443f220fa62Smrg pta[0] = spbrkpts.pts[s_index-1]; 444f220fa62Smrg pta[1] = tpbrkpts.pts[t_index-1]; 445f220fa62Smrg 446f220fa62Smrg ptb[0] = spbrkpts.pts[s_index]; 447f220fa62Smrg ptb[1] = tpbrkpts.pts[t_index]; 448f220fa62Smrg qlist->downloadAll( pta, ptb, backend ); 449f220fa62Smrg 450f220fa62Smrg Patchlist patchlist( qlist, pta, ptb ); 451f220fa62Smrg/* 452f220fa62Smrgprintf("-------samplingSplit-----\n"); 453f220fa62Smrgsource.show("samplingSplit source"); 454f220fa62Smrg*/ 455f220fa62Smrg samplingSplit( source, patchlist, renderhints.maxsubdivisions, 0 ); 456f220fa62Smrg setNonDegenerate(); 457f220fa62Smrg setArcTypeBezier(); 458f220fa62Smrg } 459f220fa62Smrg } 460f220fa62Smrg } 461f220fa62Smrg} 462f220fa62Smrg 463f220fa62Smrg/*-------------------------------------------------------------------------- 464f220fa62Smrg * samplingSplit - recursively subdivide patch, cull check each subpatch 465f220fa62Smrg *-------------------------------------------------------------------------- 466f220fa62Smrg */ 467f220fa62Smrg 468f220fa62Smrgvoid 469f220fa62SmrgSubdivider::samplingSplit( 470f220fa62Smrg Bin& source, 471f220fa62Smrg Patchlist& patchlist, 472f220fa62Smrg int subdivisions, 473f220fa62Smrg int param ) 474f220fa62Smrg{ 475f220fa62Smrg if( ! source.isnonempty() ) return; 476f220fa62Smrg 477f220fa62Smrg if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT ) { 478f220fa62Smrg freejarcs( source ); 479f220fa62Smrg return; 480f220fa62Smrg } 481f220fa62Smrg 482f220fa62Smrg patchlist.getstepsize(); 483f220fa62Smrg 484f220fa62Smrg if( renderhints.display_method == N_OUTLINE_PATCH ) { 485f220fa62Smrg tessellation( source, patchlist ); 486f220fa62Smrg outline( source ); 487f220fa62Smrg freejarcs( source ); 488f220fa62Smrg return; 489f220fa62Smrg } 490f220fa62Smrg 491f220fa62Smrg //patchlist.clamp(); 492f220fa62Smrg 493f220fa62Smrg tessellation( source, patchlist ); 494f220fa62Smrg 495f220fa62Smrg if( patchlist.needsSamplingSubdivision() && (subdivisions > 0) ) { 496f220fa62Smrg if( ! patchlist.needsSubdivision( 0 ) ) 497f220fa62Smrg param = 1; 498f220fa62Smrg else if( ! patchlist.needsSubdivision( 1 ) ) 499f220fa62Smrg param = 0; 500f220fa62Smrg else 501f220fa62Smrg param = 1 - param; 502f220fa62Smrg 503f220fa62Smrg Bin left, right; 504f220fa62Smrg REAL mid = ( patchlist.pspec[param].range[0] + 505f220fa62Smrg patchlist.pspec[param].range[1] ) * 0.5; 506f220fa62Smrg split( source, left, right, param, mid ); 507f220fa62Smrg Patchlist subpatchlist( patchlist, param, mid ); 508f220fa62Smrg samplingSplit( left, subpatchlist, subdivisions-1, param ); 509f220fa62Smrg samplingSplit( right, patchlist, subdivisions-1, param ); 510f220fa62Smrg } else { 511f220fa62Smrg setArcTypePwl(); 512f220fa62Smrg setDegenerate(); 513f220fa62Smrg nonSamplingSplit( source, patchlist, subdivisions, param ); 514f220fa62Smrg setDegenerate(); 515f220fa62Smrg setArcTypeBezier(); 516f220fa62Smrg } 517f220fa62Smrg} 518f220fa62Smrg 519f220fa62Smrgvoid 520f220fa62SmrgSubdivider::nonSamplingSplit( 521f220fa62Smrg Bin& source, 522f220fa62Smrg Patchlist& patchlist, 523f220fa62Smrg int subdivisions, 524f220fa62Smrg int param ) 525f220fa62Smrg{ 526f220fa62Smrg if( patchlist.needsNonSamplingSubdivision() && (subdivisions > 0) ) { 527f220fa62Smrg param = 1 - param; 528f220fa62Smrg 529f220fa62Smrg Bin left, right; 530f220fa62Smrg REAL mid = ( patchlist.pspec[param].range[0] + 531f220fa62Smrg patchlist.pspec[param].range[1] ) * 0.5; 532f220fa62Smrg split( source, left, right, param, mid ); 533f220fa62Smrg Patchlist subpatchlist( patchlist, param, mid ); 534f220fa62Smrg if( left.isnonempty() ) { 535f220fa62Smrg if( subpatchlist.cullCheck() == CULL_TRIVIAL_REJECT ) 536f220fa62Smrg freejarcs( left ); 537f220fa62Smrg else 538f220fa62Smrg nonSamplingSplit( left, subpatchlist, subdivisions-1, param ); 539f220fa62Smrg } 540f220fa62Smrg if( right.isnonempty() ) { 541f220fa62Smrg if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT ) 542f220fa62Smrg freejarcs( right ); 543f220fa62Smrg else 544f220fa62Smrg nonSamplingSplit( right, patchlist, subdivisions-1, param ); 545f220fa62Smrg } 546f220fa62Smrg 547f220fa62Smrg } else { 548f220fa62Smrg // make bbox calls 549f220fa62Smrg patchlist.bbox(); 550f220fa62Smrg backend.patch( patchlist.pspec[0].range[0], patchlist.pspec[0].range[1], 551f220fa62Smrg patchlist.pspec[1].range[0], patchlist.pspec[1].range[1] ); 552f220fa62Smrg 553f220fa62Smrg if( renderhints.display_method == N_OUTLINE_SUBDIV ) { 554f220fa62Smrg outline( source ); 555f220fa62Smrg freejarcs( source ); 556f220fa62Smrg } else { 557f220fa62Smrg setArcTypePwl(); 558f220fa62Smrg setDegenerate(); 559f220fa62Smrg findIrregularS( source ); 560f220fa62Smrg monosplitInS( source, smbrkpts.start, smbrkpts.end ); 561f220fa62Smrg } 562f220fa62Smrg } 563f220fa62Smrg} 564f220fa62Smrg 565f220fa62Smrg/*-------------------------------------------------------------------------- 566f220fa62Smrg * tessellation - set tessellation of interior and boundary of patch 567f220fa62Smrg *-------------------------------------------------------------------------- 568f220fa62Smrg */ 569f220fa62Smrg 570f220fa62Smrgvoid 571f220fa62SmrgSubdivider::tessellation( Bin& bin, Patchlist &patchlist ) 572f220fa62Smrg{ 573f220fa62Smrg // tessellate unsampled trim curves 574f220fa62Smrg tessellate( bin, patchlist.pspec[1].sidestep[1], patchlist.pspec[0].sidestep[1], 575f220fa62Smrg patchlist.pspec[1].sidestep[0], patchlist.pspec[0].sidestep[0] ); 576f220fa62Smrg 577f220fa62Smrg // set interior sampling rates 578f220fa62Smrg slicer.setstriptessellation( patchlist.pspec[0].stepsize, patchlist.pspec[1].stepsize ); 579f220fa62Smrg 580f220fa62Smrg //added by zl: set the order which will be used in slicer.c++ 581f220fa62Smrg slicer.set_ulinear( (patchlist.get_uorder() == 2)); 582f220fa62Smrg slicer.set_vlinear( (patchlist.get_vorder() == 2)); 583f220fa62Smrg 584f220fa62Smrg // set boundary sampling rates 585f220fa62Smrg stepsizes[0] = patchlist.pspec[1].stepsize; 586f220fa62Smrg stepsizes[1] = patchlist.pspec[0].stepsize; 587f220fa62Smrg stepsizes[2] = patchlist.pspec[1].stepsize; 588f220fa62Smrg stepsizes[3] = patchlist.pspec[0].stepsize; 589f220fa62Smrg} 590f220fa62Smrg 591f220fa62Smrg/*--------------------------------------------------------------------------- 592f220fa62Smrg * monosplitInS - split a patch and a bin by an isoparametric line 593f220fa62Smrg *--------------------------------------------------------------------------- 594f220fa62Smrg */ 595f220fa62Smrg 596f220fa62Smrgvoid 597f220fa62SmrgSubdivider::monosplitInS( Bin& source, int start, int end ) 598f220fa62Smrg{ 599f220fa62Smrg if( source.isnonempty() ) { 600f220fa62Smrg if( start != end ) { 601f220fa62Smrg int i = start + (end - start) / 2; 602f220fa62Smrg Bin left, right; 603f220fa62Smrg split( source, left, right, 0, smbrkpts.pts[i] ); 604f220fa62Smrg monosplitInS( left, start, i ); 605f220fa62Smrg monosplitInS( right, i+1, end ); 606f220fa62Smrg } else { 607f220fa62Smrg if( renderhints.display_method == N_OUTLINE_SUBDIV_S ) { 608f220fa62Smrg outline( source ); 609f220fa62Smrg freejarcs( source ); 610f220fa62Smrg } else { 611f220fa62Smrg setArcTypePwl(); 612f220fa62Smrg setDegenerate(); 613f220fa62Smrg findIrregularT( source ); 614f220fa62Smrg monosplitInT( source, tmbrkpts.start, tmbrkpts.end ); 615f220fa62Smrg } 616f220fa62Smrg } 617f220fa62Smrg } 618f220fa62Smrg} 619f220fa62Smrg 620f220fa62Smrg/*--------------------------------------------------------------------------- 621f220fa62Smrg * monosplitInT - split a patch and a bin by an isoparametric line 622f220fa62Smrg *--------------------------------------------------------------------------- 623f220fa62Smrg */ 624f220fa62Smrg 625f220fa62Smrgvoid 626f220fa62SmrgSubdivider::monosplitInT( Bin& source, int start, int end ) 627f220fa62Smrg{ 628f220fa62Smrg if( source.isnonempty() ) { 629f220fa62Smrg if( start != end ) { 630f220fa62Smrg int i = start + (end - start) / 2; 631f220fa62Smrg Bin left, right; 632f220fa62Smrg split( source, left, right, 1, tmbrkpts.pts[i] ); 633f220fa62Smrg monosplitInT( left, start, i ); 634f220fa62Smrg monosplitInT( right, i+1, end ); 635f220fa62Smrg } else { 636f220fa62Smrg if( renderhints.display_method == N_OUTLINE_SUBDIV_ST ) { 637f220fa62Smrg outline( source ); 638f220fa62Smrg freejarcs( source ); 639f220fa62Smrg } else { 640f220fa62Smrg/* 641f220fa62Smrgprintf("*******render\n"); 642f220fa62Smrgsource.show("source\n"); 643f220fa62Smrg*/ 644f220fa62Smrg render( source ); 645f220fa62Smrg freejarcs( source ); 646f220fa62Smrg } 647f220fa62Smrg } 648f220fa62Smrg } 649f220fa62Smrg} 650f220fa62Smrg 651f220fa62Smrg 652f220fa62Smrg/*---------------------------------------------------------------------------- 653f220fa62Smrg * findIrregularS - determine points of non-monotonicity is s direction 654f220fa62Smrg *---------------------------------------------------------------------------- 655f220fa62Smrg */ 656f220fa62Smrg 657f220fa62Smrgvoid 658f220fa62SmrgSubdivider::findIrregularS( Bin& bin ) 659f220fa62Smrg{ 660f220fa62Smrg assert( bin.firstarc()->check() != 0 ); 661f220fa62Smrg 662f220fa62Smrg smbrkpts.grow( bin.numarcs() ); 663f220fa62Smrg 664f220fa62Smrg for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) { 665f220fa62Smrg REAL *a = jarc->prev->tail(); 666f220fa62Smrg REAL *b = jarc->tail(); 667f220fa62Smrg REAL *c = jarc->head(); 668f220fa62Smrg 669f220fa62Smrg if( b[1] == a[1] && b[1] == c[1] ) continue; 670f220fa62Smrg 671f220fa62Smrg //corrected code 672f220fa62Smrg if((b[1]<=a[1] && b[1] <= c[1]) || 673f220fa62Smrg (b[1]>=a[1] && b[1] >= c[1])) 674f220fa62Smrg { 675f220fa62Smrg //each arc (jarc, jarc->prev, jarc->next) is a 676f220fa62Smrg //monotone arc consisting of multiple line segements. 677f220fa62Smrg //it may happen that jarc->prev and jarc->next are the same, 678f220fa62Smrg //that is, jarc->prev and jarc form a closed loop. 679f220fa62Smrg //In such case, a and c will be the same. 680f220fa62Smrg if(a[0]==c[0] && a[1] == c[1]) 681f220fa62Smrg { 682f220fa62Smrg if(jarc->pwlArc->npts >2) 683f220fa62Smrg { 684f220fa62Smrg c = jarc->pwlArc->pts[jarc->pwlArc->npts-2].param; 685f220fa62Smrg } 686f220fa62Smrg else 687f220fa62Smrg { 688f220fa62Smrg assert(jarc->prev->pwlArc->npts>2); 689f220fa62Smrg a = jarc->prev->pwlArc->pts[jarc->prev->pwlArc->npts-2].param; 690f220fa62Smrg } 691f220fa62Smrg 692f220fa62Smrg } 693f220fa62Smrg if(area(a,b,c) < 0) 694f220fa62Smrg { 695f220fa62Smrg smbrkpts.add(b[0]); 696f220fa62Smrg } 697f220fa62Smrg 698f220fa62Smrg } 699f220fa62Smrg 700f220fa62Smrg /* old code, 701f220fa62Smrg if( b[1] <= a[1] && b[1] <= c[1] ) { 702f220fa62Smrg if( ! ccwTurn_tr( jarc->prev, jarc ) ) 703f220fa62Smrg smbrkpts.add( b[0] ); 704f220fa62Smrg } else if( b[1] >= a[1] && b[1] >= c[1] ) { 705f220fa62Smrg if( ! ccwTurn_tl( jarc->prev, jarc ) ) 706f220fa62Smrg smbrkpts.add( b[0] ); 707f220fa62Smrg } 708f220fa62Smrg */ 709f220fa62Smrg 710f220fa62Smrg } 711f220fa62Smrg 712f220fa62Smrg smbrkpts.filter(); 713f220fa62Smrg} 714f220fa62Smrg 715f220fa62Smrg/*---------------------------------------------------------------------------- 716f220fa62Smrg * findIrregularT - determine points of non-monotonicity in t direction 717f220fa62Smrg * where one arc is parallel to the s axis. 718f220fa62Smrg *---------------------------------------------------------------------------- 719f220fa62Smrg */ 720f220fa62Smrg 721f220fa62Smrgvoid 722f220fa62SmrgSubdivider::findIrregularT( Bin& bin ) 723f220fa62Smrg{ 724f220fa62Smrg assert( bin.firstarc()->check() != 0 ); 725f220fa62Smrg 726f220fa62Smrg tmbrkpts.grow( bin.numarcs() ); 727f220fa62Smrg 728f220fa62Smrg for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) { 729f220fa62Smrg REAL *a = jarc->prev->tail(); 730f220fa62Smrg REAL *b = jarc->tail(); 731f220fa62Smrg REAL *c = jarc->head(); 732f220fa62Smrg 733f220fa62Smrg if( b[0] == a[0] && b[0] == c[0] ) continue; 734f220fa62Smrg 735f220fa62Smrg if( b[0] <= a[0] && b[0] <= c[0] ) { 736f220fa62Smrg if( a[1] != b[1] && b[1] != c[1] ) continue; 737f220fa62Smrg if( ! ccwTurn_sr( jarc->prev, jarc ) ) 738f220fa62Smrg tmbrkpts.add( b[1] ); 739f220fa62Smrg } else if ( b[0] >= a[0] && b[0] >= c[0] ) { 740f220fa62Smrg if( a[1] != b[1] && b[1] != c[1] ) continue; 741f220fa62Smrg if( ! ccwTurn_sl( jarc->prev, jarc ) ) 742f220fa62Smrg tmbrkpts.add( b[1] ); 743f220fa62Smrg } 744f220fa62Smrg } 745f220fa62Smrg tmbrkpts.filter( ); 746f220fa62Smrg} 747f220fa62Smrg 748f220fa62Smrg/*----------------------------------------------------------------------------- 749f220fa62Smrg * makeBorderTrim - if no user input trimming data then create 750f220fa62Smrg * a trimming curve around the boundaries of the Quilt. The curve consists of 751f220fa62Smrg * four Jordan arcs, one for each side of the Quilt, connected, of course, 752f220fa62Smrg * head to tail. 753f220fa62Smrg *----------------------------------------------------------------------------- 754f220fa62Smrg */ 755f220fa62Smrg 756f220fa62Smrgvoid 757f220fa62SmrgSubdivider::makeBorderTrim( const REAL *from, const REAL *to ) 758f220fa62Smrg{ 759f220fa62Smrg REAL smin = from[0]; 760f220fa62Smrg REAL smax = to[0]; 761f220fa62Smrg REAL tmin = from[1]; 762f220fa62Smrg REAL tmax = to[1]; 763f220fa62Smrg 764f220fa62Smrg pjarc = 0; 765f220fa62Smrg 766f220fa62Smrg Arc_ptr jarc = new(arcpool) Arc( arc_bottom, 0 ); 767f220fa62Smrg arctessellator.bezier( jarc, smin, smax, tmin, tmin ); 768f220fa62Smrg initialbin.addarc( jarc ); 769f220fa62Smrg pjarc = jarc->append( pjarc ); 770f220fa62Smrg 771f220fa62Smrg jarc = new(arcpool) Arc( arc_right, 0 ); 772f220fa62Smrg arctessellator.bezier( jarc, smax, smax, tmin, tmax ); 773f220fa62Smrg initialbin.addarc( jarc ); 774f220fa62Smrg pjarc = jarc->append( pjarc ); 775f220fa62Smrg 776f220fa62Smrg jarc = new(arcpool) Arc( arc_top, 0 ); 777f220fa62Smrg arctessellator.bezier( jarc, smax, smin, tmax, tmax ); 778f220fa62Smrg initialbin.addarc( jarc ); 779f220fa62Smrg pjarc = jarc->append( pjarc ); 780f220fa62Smrg 781f220fa62Smrg jarc = new(arcpool) Arc( arc_left, 0 ); 782f220fa62Smrg arctessellator.bezier( jarc, smin, smin, tmax, tmin ); 783f220fa62Smrg initialbin.addarc( jarc ); 784f220fa62Smrg jarc->append( pjarc ); 785f220fa62Smrg 786f220fa62Smrg assert( jarc->check() != 0 ); 787f220fa62Smrg} 788f220fa62Smrg 789f220fa62Smrg/*---------------------------------------------------------------------------- 790f220fa62Smrg * render - renders all monotone regions in a bin and frees the bin 791f220fa62Smrg *---------------------------------------------------------------------------- 792f220fa62Smrg */ 793f220fa62Smrg 794f220fa62Smrgvoid 795f220fa62SmrgSubdivider::render( Bin& bin ) 796f220fa62Smrg{ 797f220fa62Smrg bin.markall(); 798f220fa62Smrg 799f220fa62Smrg#ifdef N_ISOLINE_S 800f220fa62Smrg slicer.setisolines( ( renderhints.display_method == N_ISOLINE_S ) ? 1 : 0 ); 801f220fa62Smrg#else 802f220fa62Smrg slicer.setisolines( 0 ); 803f220fa62Smrg#endif 804f220fa62Smrg 805f220fa62Smrg for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) { 806f220fa62Smrg if( jarc->ismarked() ) { 807f220fa62Smrg assert( jarc->check( ) != 0 ); 808f220fa62Smrg Arc_ptr jarchead = jarc; 809f220fa62Smrg do { 810f220fa62Smrg jarc->clearmark(); 811f220fa62Smrg jarc = jarc->next; 812f220fa62Smrg } while (jarc != jarchead); 813f220fa62Smrg slicer.slice( jarc ); 814f220fa62Smrg } 815f220fa62Smrg } 816f220fa62Smrg} 817f220fa62Smrg 818f220fa62Smrg/*--------------------------------------------------------------------------- 819f220fa62Smrg * outline - render the trimmed patch by outlining the boundary 820f220fa62Smrg *--------------------------------------------------------------------------- 821f220fa62Smrg */ 822f220fa62Smrg 823f220fa62Smrgvoid 824f220fa62SmrgSubdivider::outline( Bin& bin ) 825f220fa62Smrg{ 826f220fa62Smrg bin.markall(); 827f220fa62Smrg for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) { 828f220fa62Smrg if( jarc->ismarked() ) { 829f220fa62Smrg assert( jarc->check( ) != 0 ); 830f220fa62Smrg Arc_ptr jarchead = jarc; 831f220fa62Smrg do { 832f220fa62Smrg slicer.outline( jarc ); 833f220fa62Smrg jarc->clearmark(); 834f220fa62Smrg jarc = jarc->prev; 835f220fa62Smrg } while (jarc != jarchead); 836f220fa62Smrg } 837f220fa62Smrg } 838f220fa62Smrg} 839f220fa62Smrg 840f220fa62Smrg/*--------------------------------------------------------------------------- 841f220fa62Smrg * freejarcs - free all arcs in a bin 842f220fa62Smrg *--------------------------------------------------------------------------- 843f220fa62Smrg */ 844f220fa62Smrg 845f220fa62Smrgvoid 846f220fa62SmrgSubdivider::freejarcs( Bin& bin ) 847f220fa62Smrg{ 848f220fa62Smrg bin.adopt(); /* XXX - should not be necessary */ 849f220fa62Smrg 850f220fa62Smrg Arc_ptr jarc; 851f220fa62Smrg while( (jarc = bin.removearc()) != NULL ) { 852f220fa62Smrg if( jarc->pwlArc ) jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0; 853f220fa62Smrg if( jarc->bezierArc) jarc->bezierArc->deleteMe( bezierarcpool ); jarc->bezierArc = 0; 854f220fa62Smrg jarc->deleteMe( arcpool ); 855f220fa62Smrg } 856f220fa62Smrg} 857f220fa62Smrg 858f220fa62Smrg/*---------------------------------------------------------------------------- 859f220fa62Smrg * tessellate - tessellate all Bezier arcs in a bin 860f220fa62Smrg * 1) only accepts linear Bezier arcs as input 861f220fa62Smrg * 2) the Bezier arcs are stored in the pwlArc structure 862f220fa62Smrg * 3) only vertical or horizontal lines work 863f220fa62Smrg * -- should 864f220fa62Smrg * 1) represent Bezier arcs in BezierArc structure 865f220fa62Smrg * (this requires a multitude of changes to the code) 866f220fa62Smrg * 2) accept high degree Bezier arcs (hard) 867f220fa62Smrg * 3) map the curve onto the surface to determine tessellation 868f220fa62Smrg * 4) work for curves of arbitrary geometry 869f220fa62Smrg *---------------------------------------------------------------------------- 870f220fa62Smrg */ 871f220fa62Smrg 872f220fa62Smrg 873f220fa62Smrgvoid 874f220fa62SmrgSubdivider::tessellate( Bin& bin, REAL rrate, REAL trate, REAL lrate, REAL brate ) 875f220fa62Smrg{ 876f220fa62Smrg for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) { 877f220fa62Smrg if( jarc->isbezier( ) ) { 878f220fa62Smrg assert( jarc->pwlArc->npts == 2 ); 879f220fa62Smrg TrimVertex *pts = jarc->pwlArc->pts; 880f220fa62Smrg REAL s1 = pts[0].param[0]; 881f220fa62Smrg REAL t1 = pts[0].param[1]; 882f220fa62Smrg REAL s2 = pts[1].param[0]; 883f220fa62Smrg REAL t2 = pts[1].param[1]; 884f220fa62Smrg 885f220fa62Smrg jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0; 886f220fa62Smrg 887f220fa62Smrg switch( jarc->getside() ) { 888f220fa62Smrg case arc_left: 889f220fa62Smrg assert( s1 == s2 ); 890f220fa62Smrg arctessellator.pwl_left( jarc, s1, t1, t2, lrate ); 891f220fa62Smrg break; 892f220fa62Smrg case arc_right: 893f220fa62Smrg assert( s1 == s2 ); 894f220fa62Smrg arctessellator.pwl_right( jarc, s1, t1, t2, rrate ); 895f220fa62Smrg break; 896f220fa62Smrg case arc_top: 897f220fa62Smrg assert( t1 == t2 ); 898f220fa62Smrg arctessellator.pwl_top( jarc, t1, s1, s2, trate ); 899f220fa62Smrg break; 900f220fa62Smrg case arc_bottom: 901f220fa62Smrg assert( t1 == t2 ); 902f220fa62Smrg arctessellator.pwl_bottom( jarc, t1, s1, s2, brate ); 903f220fa62Smrg break; 904f220fa62Smrg case arc_none: 905f220fa62Smrg (void) abort(); 906f220fa62Smrg break; 907f220fa62Smrg } 908f220fa62Smrg assert( ! jarc->isbezier() ); 909f220fa62Smrg assert( jarc->check() != 0 ); 910f220fa62Smrg } 911f220fa62Smrg } 912f220fa62Smrg} 913