1/* 2copyright 2004 Alexander Malmberg <alexander@malmberg.org> 3*/ 4 5#include "Testing.h" 6 7#include <Foundation/NSAutoreleasePool.h> 8#include <AppKit/NSBezierPath.h> 9 10#include <math.h> 11 12 13#define nextafterf(x,y) next(x,y) 14 15static float next(float x,float y) 16{ 17 if (y<x) 18 return x-(x?0.00001:0.000005); 19// return x-(x?0.0001:0.00001); 20 else if (y>x) 21 return x+(x?0.00001:0.000005); 22// return x+(x?0.0001:0.00001); 23 else 24 return y; 25} 26 27 28//#define DRAW 29 30#ifdef DRAW 31 32#include <AppKit/NSApplication.h> 33#include <AppKit/NSGraphics.h> 34#include <AppKit/NSView.h> 35#include <AppKit/NSWindow.h> 36#include <AppKit/PSOperators.h> 37 38@interface MyView : NSView 39-(void) clear; 40-(void) drawPath: (NSBezierPath *)p; 41-(void) drawPoint: (NSPoint)p count: (int)c; 42-(void) pause; 43@end 44 45#define MOVE \ 46 { \ 47 double x0,y0,x1,y1; \ 48 double w=800,h=800; \ 49 \ 50 x0=76.980; \ 51 x1=76.981; \ 52 y0=-0.0005; \ 53 y1=0.0005; \ 54 \ 55 ww=w/(x1-x0); \ 56 hh=h/(y1-y0); \ 57 PSscale(ww,hh); \ 58 PStranslate(-x0,-y0); \ 59 } 60 61@implementation MyView 62-(void) clear 63{ 64 [self lockFocus]; 65 PSsetrgbcolor(1,1,1); 66 NSRectFill([self bounds]); 67 [self unlockFocus]; 68 [[self window] flushWindow]; 69} 70-(void) drawPath: (NSBezierPath *)p 71{ 72 double ww,hh; 73 [self lockFocus]; 74 MOVE 75 PSsetrgbcolor(0.8,0.4,0.4); 76 [p fill]; 77 PSsetrgbcolor(0.3,1.0,0.3); 78 PSsetalpha(0.5); 79 [[p bezierPathByFlatteningPath] fill]; 80 [self unlockFocus]; 81 [[self window] flushWindow]; 82} 83-(void) drawPoint: (NSPoint)p count: (int)c 84{ 85#define NC 3 86static float colors[NC][3]={ 87{1,0,0}, 88{0,1,0}, 89{0,0,1}, 90}; 91 double ww,hh; 92 c%=NC; 93 if (c<0) 94 c+=NC; 95 [self lockFocus]; 96 MOVE 97 PSsetrgbcolor(colors[c][0],colors[c][1],colors[c][2]); 98 PSrectfill(p.x-4/ww,p.y-4/hh,8/ww,8/hh); 99 [self unlockFocus]; 100 [[self window] flushWindow]; 101#undef NC 102} 103-(void) pause 104{ 105 char buf[128]; 106 gets(buf); 107} 108@end 109 110MyView *view; 111 112#endif 113 114 115 116int main(int argc, char **argv) 117{ 118 CREATE_AUTORELEASE_POOL(arp); 119 NSBezierPath *p=[[NSBezierPath alloc] init]; 120 int i; 121 const char *str; 122 int X=-1000; 123 124 125#ifdef DRAW 126 { 127 NSWindow *w; 128 129 [NSApplication sharedApplication]; 130 w=[[NSWindow alloc] initWithContentRect: NSMakeRect(50,50,800,800) 131 styleMask: NSTitledWindowMask 132 backing: NSBackingStoreRetained 133 defer: YES]; 134 135 view=[[MyView alloc] init]; 136 [w setContentView: view]; 137 [w orderFront: nil]; 138 } 139#endif 140 141#ifdef DRAW 142#define DP(e,x,y) [view drawPoint: NSMakePoint(x,y) count: e]; 143#define CLEAR [view clear]; 144#define PAUSE [view pause]; 145#define DRAWPATH [view drawPath: p]; 146#else 147#define DP(e,x,y) 148#define CLEAR 149#define PAUSE 150#define DRAWPATH 151#endif 152 153#define T(e,x,y) \ 154 { \ 155 int i,r; \ 156 DP(e,x,y) \ 157 r=[p windingCountAtPoint: NSMakePoint(x,y)]; \ 158 for (i=5;i;i--) \ 159 { \ 160 if ([p windingCountAtPoint: NSMakePoint(x,y)]!=r) \ 161 break; \ 162 } \ 163 if (i) \ 164 { \ 165 pass(NO, \ 166 "path '%s', %15.8e %15.8e, expected %i, got inconsistant results", \ 167 str,(double)x,(double)y, \ 168 e); \ 169 } \ 170 else \ 171 { \ 172 pass(r == e, \ 173 "path '%s', %15.8e %15.8e, expected %i, got %i", \ 174 str,(double)x,(double)y, \ 175 e,r); \ 176 } \ 177 } 178 179#define CHECK_AROUND(x,y, p00,p10,p20, p01,p11,p21, p02,p12,p22) \ 180 if (p00!=X) T(p00,nextafterf(x,-1000),nextafterf(y, 1000)) \ 181 if (p10!=X) T(p10, x ,nextafterf(y, 1000)) \ 182 if (p20!=X) T(p20,nextafterf(x, 1000),nextafterf(y, 1000)) \ 183 \ 184 if (p01!=X) T(p01,nextafterf(x,-1000), y ) \ 185 if (p11!=X) T(p11, x , y ) \ 186 if (p21!=X) T(p21,nextafterf(x, 1000), y ) \ 187 \ 188 if (p02!=X) T(p02,nextafterf(x,-1000),nextafterf(y,-1000)) \ 189 if (p12!=X) T(p12, x ,nextafterf(y,-1000)) \ 190 if (p22!=X) T(p22,nextafterf(x, 1000),nextafterf(y,-1000)) 191 192#if 1 193 str="empty"; 194 T(0,0,0) 195 196 197 for (i=0;i<3;i++) 198 { 199 [p removeAllPoints]; 200 [p moveToPoint: NSMakePoint(100,100)]; 201 [p lineToPoint: NSMakePoint(100,200)]; 202 [p lineToPoint: NSMakePoint(200,200)]; 203 [p lineToPoint: NSMakePoint(200,100)]; 204 205 if (i==0) 206 { 207 str="(u) rect"; 208 } 209 else if (i==1) 210 { 211 [p closePath]; 212 str="(c) rect"; 213 } 214 else 215 { 216 [p lineToPoint: NSMakePoint(100,100)]; 217 [p closePath]; 218 str="(d) rect"; 219 } 220 221 /* Obvious stuff. */ 222 T(0,0,0) 223 T(1,150,150) 224 225 /* Check around each corner. */ 226 CHECK_AROUND(100,100, 227 0,X,1, 228 0,X,X, 229 0,0,0) 230 231 CHECK_AROUND(200,100, 232 1,X,0, 233 X,X,0, 234 0,0,0) 235 236 CHECK_AROUND(200,200, 237 0,0,0, 238 X,X,0, 239 1,X,0) 240 241 CHECK_AROUND(100,200, 242 0,0,0, 243 0,X,X, 244 0,X,1) 245 246 if (!i) 247 [p closePath]; 248 } 249 250 251 for (i=0;i<3;i++) 252 { 253 [p removeAllPoints]; 254 [p moveToPoint: NSMakePoint(0,-100)]; 255 [p lineToPoint: NSMakePoint(-100,0)]; 256 [p lineToPoint: NSMakePoint(0,100)]; 257 [p lineToPoint: NSMakePoint(100,0)]; 258 259 if (i==0) 260 { 261 str="(u) tilted rect"; 262 } 263 else if (i==1) 264 { 265 [p closePath]; 266 str="(c) tilted rect"; 267 } 268 else 269 { 270 [p lineToPoint: NSMakePoint(0,-100)]; 271 [p closePath]; 272 str="(d) tilted rect"; 273 } 274 275 /* Obvious stuff. */ 276 T(1,0,0) 277 T(0,200,200) 278 279 /* Check around each corner. */ 280 CHECK_AROUND(0,-100, 281 1,1,1, 282 0,X,0, 283 0,0,0) 284 285 CHECK_AROUND(0,100, 286 0,0,0, 287 0,X,0, 288 1,1,1) 289 290 CHECK_AROUND(-100,0, 291 0,0,1, 292 0,X,1, 293 0,0,1) 294 295 CHECK_AROUND(100,0, 296 1,0,0, 297 1,X,0, 298 1,0,0) 299 300 /* Check some points on the edges. */ 301 CHECK_AROUND(50,50, 302 X,0,0, 303 1,X,0, 304 1,1,X) 305 306 CHECK_AROUND(-50,50, 307 0,0,X, 308 0,X,1, 309 X,1,1) 310 311 CHECK_AROUND(-50,-50, 312 X,1,1, 313 0,X,1, 314 0,0,X) 315 316 CHECK_AROUND(50,-50, 317 1,1,X, 318 1,X,0, 319 X,0,0) 320 } 321 322 for (i=0;i<3;i++) 323 { 324 [p removeAllPoints]; 325 [p moveToPoint: NSMakePoint(200,200)]; 326 [p lineToPoint: NSMakePoint(200,100)]; 327 [p lineToPoint: NSMakePoint(100,100)]; 328 [p lineToPoint: NSMakePoint(100,200)]; 329 if (i==2) 330 [p lineToPoint: NSMakePoint(200,200)]; 331 if (i>=1) 332 [p closePath]; 333 334 [p moveToPoint: NSMakePoint(200,200)]; 335 [p lineToPoint: NSMakePoint(300,200)]; 336 [p lineToPoint: NSMakePoint(300,100)]; 337 [p lineToPoint: NSMakePoint(200,100)]; 338 if (i==2) 339 [p lineToPoint: NSMakePoint(200,200)]; 340 if (i>=1) 341 [p closePath]; 342 343 if (i==0) 344 str="(u) touching rects"; 345 else if (i==1) 346 str="(c) touching rects"; 347 else 348 str="(d) touching rects"; 349 350 /* Obvious stuff. */ 351 T(0,0,0) 352 T(1,150,150) 353 T(1,250,150) 354 355 /* Check around the touching corners and edge. */ 356 CHECK_AROUND(200,200, 357 0,0,0, 358 X,X,X, 359 1,1,1) 360 361 CHECK_AROUND(200,100, 362 1,1,1, 363 X,X,X, 364 0,0,0) 365 366 CHECK_AROUND(200,150, 367 1,1,1, 368 1,1,1, 369 1,1,1) 370 } 371 372 for (i=0;i<3;i++) 373 { 374 [p removeAllPoints]; 375 [p moveToPoint: NSMakePoint(-100,200)]; 376 [p lineToPoint: NSMakePoint(100,200)]; 377 [p lineToPoint: NSMakePoint(100,-200)]; 378 [p lineToPoint: NSMakePoint(-100,-200)]; 379 if (i==2) 380 [p lineToPoint: NSMakePoint(-100,200)]; 381 if (i>=1) 382 [p closePath]; 383 384 [p moveToPoint: NSMakePoint(200,100)]; 385 [p lineToPoint: NSMakePoint(200,-100)]; 386 [p lineToPoint: NSMakePoint(-200,-100)]; 387 [p lineToPoint: NSMakePoint(-200,100)]; 388 if (i==2) 389 [p lineToPoint: NSMakePoint(200,100)]; 390 if (i>=1) 391 [p closePath]; 392 393 if (i==0) 394 str="(u) intersecting rects"; 395 else if (i==1) 396 str="(c) intersecting rects"; 397 else 398 str="(d) intersecting rects"; 399 400 /* Obvious stuff. */ 401 T(2,0,0) 402 T(0,200,200) 403 T(1,150,0) 404 T(1,0,150) 405 } 406 407 for (i=0;i<3;i++) 408 { 409 [p removeAllPoints]; 410 [p moveToPoint: NSMakePoint(200,0)]; 411 [p lineToPoint: NSMakePoint(100,-100)]; 412 [p lineToPoint: NSMakePoint(100,100)]; 413 if (i==2) 414 [p lineToPoint: NSMakePoint(200,0)]; 415 if (i>=1) 416 [p closePath]; 417 418 [p moveToPoint: NSMakePoint(200,0)]; 419 [p lineToPoint: NSMakePoint(300,100)]; 420 [p lineToPoint: NSMakePoint(300,-100)]; 421 if (i==2) 422 [p lineToPoint: NSMakePoint(200,0)]; 423 if (i>=1) 424 [p closePath]; 425 426 if (i==0) 427 str="(u) touching triangles"; 428 else if (i==1) 429 str="(c) touching triangles"; 430 else 431 str="(d) touching triangles"; 432 433 /* Obvious stuff. */ 434 T(0,0,0) 435 T(1,150,0) 436 T(1,250,0) 437 438 CHECK_AROUND(200,0, 439 1,0,1, 440 1,X,1, 441 1,0,1) 442 } 443 444 for (i=0;i<3;i++) 445 { 446 CLEAR 447 [p removeAllPoints]; 448 [p moveToPoint: NSMakePoint(100,100)]; 449 [p lineToPoint: NSMakePoint(300,100)]; 450 [p lineToPoint: NSMakePoint(100,-100)]; 451 [p lineToPoint: NSMakePoint(300,-100)]; 452 if (i==2) 453 [p lineToPoint: NSMakePoint(100,100)]; 454 if (i>=1) 455 [p closePath]; 456// [view drawPath: p]; 457 458 if (i==0) 459 str="(u) self-intersection"; 460 else if (i==1) 461 str="(c) self-intersection"; 462 else 463 str="(d) self-intersection"; 464 465 /* Obvious stuff. */ 466 T(0,0,0) 467 T(1,200,50) 468 T(-1,200,-50) 469 470 CHECK_AROUND(200,0, 471 0,1,0, 472 0,X,0, 473 0,-1,0) 474// [view pause]; 475 } 476 477 for (i=0;i<3;i++) 478 { 479 [p removeAllPoints]; 480 [p moveToPoint: NSMakePoint(-100,200)]; 481 [p lineToPoint: NSMakePoint(100,200)]; 482 [p lineToPoint: NSMakePoint(100,-200)]; 483 [p lineToPoint: NSMakePoint(-100,-200)]; 484 if (i==2) 485 [p lineToPoint: NSMakePoint(-100,200)]; 486 if (i>=1) 487 [p closePath]; 488 489 [p moveToPoint: NSMakePoint(200,100)]; 490 [p lineToPoint: NSMakePoint(200,-100)]; 491 [p lineToPoint: NSMakePoint(-200,-100)]; 492 [p lineToPoint: NSMakePoint(-200,100)]; 493 if (i==2) 494 [p lineToPoint: NSMakePoint(200,100)]; 495 if (i>=1) 496 [p closePath]; 497 498 if (i==0) 499 str="(u) intersecting rects"; 500 else if (i==1) 501 str="(c) intersecting rects"; 502 else 503 str="(d) intersecting rects"; 504 505 /* Obvious stuff. */ 506 T(2,0,0) 507 T(0,200,200) 508 T(1,150,0) 509 T(1,0,150) 510 511 /* Intersection corners. */ 512 CHECK_AROUND(100,100, 513 1,X,0, 514 X,X,X, 515 2,X,1) 516 517 CHECK_AROUND(100,-100, 518 2,X,1, 519 X,X,X, 520 1,X,0) 521 522 CHECK_AROUND(-100,-100, 523 1,X,2, 524 X,X,X, 525 0,X,1) 526 527 CHECK_AROUND(-100,100, 528 0,X,1, 529 X,X,X, 530 1,X,2) 531 } 532 533 for (i=0;i<3;i++) 534 { 535// CLEAR 536 [p removeAllPoints]; 537 [p moveToPoint: NSMakePoint(100,100)]; 538 [p curveToPoint: NSMakePoint(100,-100) 539 controlPoint1: NSMakePoint(200,100) 540 controlPoint2: NSMakePoint(200,-100)]; 541 if (i==2) 542 [p lineToPoint: NSMakePoint(100,100)]; 543 if (i>=1) 544 [p closePath]; 545 546 547// DRAWPATH 548 549 if (i==0) 550 str="(u) curve 1"; 551 else if (i==1) 552 str="(c) curve 1"; 553 else 554 str="(d) curve 1"; 555 556 /* Obvious stuff. */ 557 T(0,0,0) 558 T(0,210,0) 559 T(0,190,0) 560 T(1,110,0) 561 562 /* "Extreme" point is at 175, 0. This is at the half-way point, so 563 any tesselation by the standard method should get it right. */ 564 CHECK_AROUND(175, 0, 565 1,0,0, 566 1,X,0, 567 1,0,0) 568 569// PAUSE 570 } 571 572 for (i=0;i<3;i++) 573 { 574 CLEAR 575 [p removeAllPoints]; 576 [p moveToPoint: NSMakePoint(-100,100)]; 577 [p curveToPoint: NSMakePoint(100,100) 578 controlPoint1: NSMakePoint(-100,-100) 579 controlPoint2: NSMakePoint(100,-100)]; 580 [p lineToPoint: NSMakePoint(100,-100)]; 581 [p curveToPoint: NSMakePoint(-100,-100) 582 controlPoint1: NSMakePoint(100,100) 583 controlPoint2: NSMakePoint(-100,100)]; 584 if (i==2) 585 [p lineToPoint: NSMakePoint(-100,100)]; 586 if (i>=1) 587 [p closePath]; 588 589 590 DRAWPATH 591 592 if (i==0) 593 str="(u) curve 2"; 594 else if (i==1) 595 str="(c) curve 2"; 596 else 597 str="(d) curve 2"; 598 599 /* Obvious stuff. */ 600 T(-1,0,0) 601 T(1,-90,0) 602 T(1, 90,0) 603 604 /* The two curves intersect at y=0, x= +- 400 * sqrt(3) / 9. */ 605 606 CHECK_AROUND(-400*sqrt(3)/9, 0, 607 1,0,-1, 608 1,X,-1, 609 1,0,-1) 610 611 CHECK_AROUND( 400*sqrt(3)/9, 0, 612 -1,0,1, 613 -1,X,1, 614 -1,0,1) 615 616 PAUSE 617 } 618 619 for (i=0;i<3;i++) 620 { 621 CLEAR 622 [p removeAllPoints]; 623 [p moveToPoint: NSMakePoint(100,100)]; 624 [p curveToPoint: NSMakePoint(100,100) 625 controlPoint1: NSMakePoint(100,200) 626 controlPoint2: NSMakePoint(200,100)]; 627 if (i==2) 628 [p lineToPoint: NSMakePoint(100,100)]; 629 if (i>=1) 630 [p closePath]; 631 632 633 DRAWPATH 634 635 if (i==0) 636 str="(u) curve 3"; 637 else if (i==1) 638 str="(c) curve 3"; 639 else 640 str="(d) curve 3"; 641 642 /* Obvious stuff. */ 643 T(0,0,0) 644 T(1,105,105) 645 646 CHECK_AROUND(100,100, 647 0,0,1, 648 0,X,0, 649 0,0,0) 650 651 PAUSE 652 } 653#endif 654 655 for (i=0;i<3;i++) 656 { 657 CLEAR 658 659 /* 660 661 +-+ 662 | | 663 +-* | 664 | | 665 +---+ 666 667 */ 668 669 [p removeAllPoints]; 670 [p moveToPoint: NSMakePoint(0,0)]; 671 [p lineToPoint: NSMakePoint(0,100)]; 672 [p lineToPoint: NSMakePoint(100,100)]; 673 [p lineToPoint: NSMakePoint(100,-100)]; 674 [p lineToPoint: NSMakePoint(-100,-100)]; 675 [p lineToPoint: NSMakePoint(-100,0)]; 676 if (i==2) 677 [p lineToPoint: NSMakePoint(0,0)]; 678 if (i>=1) 679 [p closePath]; 680 681 682 DRAWPATH 683 684 if (i==0) 685 str="(u) curve 3"; 686 else if (i==1) 687 str="(c) curve 3"; 688 else 689 str="(d) curve 3"; 690 691 /* Obvious stuff. */ 692 T(0,-5,5) 693 T(1,5,-5) 694 695 CHECK_AROUND(0,0, 696 0,X,1, 697 X,X,1, 698 1,1,1) 699 700 PAUSE 701 } 702 703 DESTROY(arp); 704 705 return 0; 706} 707 708