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