source: trunk/src/opengl/glu/nurbs/internals/subdivider.cpp

Last change on this file was 2689, checked in by jeroen, 26 years ago

* empty log message *

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