├── BezierArcTest.scad ├── BezierArcTest.stl ├── BezierScad.coffee ├── BezierScad.scad ├── BezierTest.scad ├── BezierTest.stl └── README.md /BezierArcTest.scad: -------------------------------------------------------------------------------- 1 | use ; 2 | 3 | BezArc([ 4 | [-10,-1], 5 | [-10, -6], 6 | [-1, -1], 7 | [-5, -10], 8 | [-1,-10] 9 | ], [-1,-1], steps = 16, heightCtls = [1,2,10,2,1]); 10 | 11 | translate([25,0,0]) 12 | BezArc([ 13 | [-10, 0], 14 | [-10, -6], 15 | [-1, -1], 16 | [-5, -10], 17 | [0,-10] 18 | ], focalPoint = [0,0], steps = 30, height = 10); -------------------------------------------------------------------------------- /BezierArcTest.stl: -------------------------------------------------------------------------------- 1 | solid OpenSCAD_Model 2 | facet normal 0 1 0 3 | outer loop 4 | vertex -10 -1 0 5 | vertex -10 -1 1 6 | vertex -1 -1 0 7 | endloop 8 | endfacet 9 | facet normal 0 1 0 10 | outer loop 11 | vertex -1 -1 0 12 | vertex -10 -1 1 13 | vertex -1 -1 1 14 | endloop 15 | endfacet 16 | facet normal -0.99589 -0.0905704 0 17 | outer loop 18 | vertex -10 -1 0 19 | vertex -9.94672 -1.5859 0 20 | vertex -10 -1 1 21 | endloop 22 | endfacet 23 | facet normal -0.99589 -0.0905704 0 24 | outer loop 25 | vertex -10 -1 1 26 | vertex -9.94672 -1.5859 0 27 | vertex -9.94672 -1.5859 1.1697 28 | endloop 29 | endfacet 30 | facet normal 0 0 -1 31 | outer loop 32 | vertex -10 -1 0 33 | vertex -1 -1 0 34 | vertex -9.94672 -1.5859 0 35 | endloop 36 | endfacet 37 | facet normal 0 0 -1 38 | outer loop 39 | vertex -3.18531 -7.77644 0 40 | vertex -1 -1 0 41 | vertex -1 -10 0 42 | endloop 43 | endfacet 44 | facet normal 0 0 -1 45 | outer loop 46 | vertex -2.84735 -8.5782 0 47 | vertex -1 -10 0 48 | vertex -1.46895 -9.94685 0 49 | endloop 50 | endfacet 51 | facet normal 0 0 -1 52 | outer loop 53 | vertex -2.6553 -8.94943 0 54 | vertex -1.46895 -9.94685 0 55 | vertex -1.85428 -9.79913 0 56 | endloop 57 | endfacet 58 | facet normal 0 0 -1 59 | outer loop 60 | vertex -2.43389 -9.28555 0 61 | vertex -1.85428 -9.79913 0 62 | vertex -2.17121 -9.57353 0 63 | endloop 64 | endfacet 65 | facet normal 0 0 -1 66 | outer loop 67 | vertex -2.84735 -8.5782 0 68 | vertex -1.46895 -9.94685 0 69 | vertex -2.6553 -8.94943 0 70 | endloop 71 | endfacet 72 | facet normal 0 0 -1 73 | outer loop 74 | vertex -3.0208 -8.18367 0 75 | vertex -1 -10 0 76 | vertex -2.84735 -8.5782 0 77 | endloop 78 | endfacet 79 | facet normal 0 0 -1 80 | outer loop 81 | vertex -3.18531 -7.77644 0 82 | vertex -1 -10 0 83 | vertex -3.0208 -8.18367 0 84 | endloop 85 | endfacet 86 | facet normal 0 0 -1 87 | outer loop 88 | vertex -3.34941 -7.36587 0 89 | vertex -1 -1 0 90 | vertex -3.18531 -7.77644 0 91 | endloop 92 | endfacet 93 | facet normal 0 0 -1 94 | outer loop 95 | vertex -6.0473 -4.26439 0 96 | vertex -9.94672 -1.5859 0 97 | vertex -5.66356 -4.46178 0 98 | endloop 99 | endfacet 100 | facet normal 0 0 -1 101 | outer loop 102 | vertex -3.52053 -6.96011 0 103 | vertex -1 -1 0 104 | vertex -3.34941 -7.36587 0 105 | endloop 106 | endfacet 107 | facet normal 0 0 -1 108 | outer loop 109 | vertex -3.70496 -6.56609 0 110 | vertex -1 -1 0 111 | vertex -3.52053 -6.96011 0 112 | endloop 113 | endfacet 114 | facet normal 0 0 -1 115 | outer loop 116 | vertex -3.9079 -6.1895 0 117 | vertex -1 -1 0 118 | vertex -3.70496 -6.56609 0 119 | endloop 120 | endfacet 121 | facet normal 0 0 -1 122 | outer loop 123 | vertex -4.1334 -5.83484 0 124 | vertex -1 -1 0 125 | vertex -3.9079 -6.1895 0 126 | endloop 127 | endfacet 128 | facet normal 0 0 -1 129 | outer loop 130 | vertex -4.38442 -5.50537 0 131 | vertex -1 -1 0 132 | vertex -4.1334 -5.83484 0 133 | endloop 134 | endfacet 135 | facet normal 0 0 -1 136 | outer loop 137 | vertex -4.66279 -5.20311 0 138 | vertex -1 -1 0 139 | vertex -4.38442 -5.50537 0 140 | endloop 141 | endfacet 142 | facet normal 0 0 -1 143 | outer loop 144 | vertex -4.96923 -4.9289 0 145 | vertex -1 -1 0 146 | vertex -4.66279 -5.20311 0 147 | endloop 148 | endfacet 149 | facet normal 0 0 -1 150 | outer loop 151 | vertex -5.30332 -4.68233 0 152 | vertex -1 -1 0 153 | vertex -4.96923 -4.9289 0 154 | endloop 155 | endfacet 156 | facet normal 0 0 -1 157 | outer loop 158 | vertex -9.94672 -1.5859 0 159 | vertex -1 -1 0 160 | vertex -5.30332 -4.68233 0 161 | endloop 162 | endfacet 163 | facet normal 0 0 -1 164 | outer loop 165 | vertex -9.94672 -1.5859 0 166 | vertex -5.30332 -4.68233 0 167 | vertex -5.66356 -4.46178 0 168 | endloop 169 | endfacet 170 | facet normal 0 0 -1 171 | outer loop 172 | vertex -6.45079 -4.08611 0 173 | vertex -9.94672 -1.5859 0 174 | vertex -6.0473 -4.26439 0 175 | endloop 176 | endfacet 177 | facet normal 0 0 -1 178 | outer loop 179 | vertex -6.86916 -3.92164 0 180 | vertex -9.94672 -1.5859 0 181 | vertex -6.45079 -4.08611 0 182 | endloop 183 | endfacet 184 | facet normal 0 0 -1 185 | outer loop 186 | vertex -7.29641 -3.76448 0 187 | vertex -9.94672 -1.5859 0 188 | vertex -6.86916 -3.92164 0 189 | endloop 190 | endfacet 191 | facet normal 0 0 -1 192 | outer loop 193 | vertex -7.72544 -3.60689 0 194 | vertex -9.94672 -1.5859 0 195 | vertex -7.29641 -3.76448 0 196 | endloop 197 | endfacet 198 | facet normal 0 0 -1 199 | outer loop 200 | vertex -8.14802 -3.43992 0 201 | vertex -9.94672 -1.5859 0 202 | vertex -7.72544 -3.60689 0 203 | endloop 204 | endfacet 205 | facet normal 0 0 -1 206 | outer loop 207 | vertex -9.94672 -1.5859 0 208 | vertex -8.14802 -3.43992 0 209 | vertex -8.55481 -3.2534 0 210 | endloop 211 | endfacet 212 | facet normal 0 0 -1 213 | outer loop 214 | vertex -9.94672 -1.5859 0 215 | vertex -8.55481 -3.2534 0 216 | vertex -8.93535 -3.03593 0 217 | endloop 218 | endfacet 219 | facet normal 0 0 -1 220 | outer loop 221 | vertex -9.94672 -1.5859 0 222 | vertex -8.93535 -3.03593 0 223 | vertex -9.27807 -2.77489 0 224 | endloop 225 | endfacet 226 | facet normal 0 0 -1 227 | outer loop 228 | vertex -9.94672 -1.5859 0 229 | vertex -9.27807 -2.77489 0 230 | vertex -9.57026 -2.45645 0 231 | endloop 232 | endfacet 233 | facet normal 0 0 -1 234 | outer loop 235 | vertex -9.94672 -1.5859 0 236 | vertex -9.57026 -2.45645 0 237 | vertex -9.79812 -2.06555 0 238 | endloop 239 | endfacet 240 | facet normal 0 0 -1 241 | outer loop 242 | vertex -2.6553 -8.94943 0 243 | vertex -1.85428 -9.79913 0 244 | vertex -2.43389 -9.28555 0 245 | endloop 246 | endfacet 247 | facet normal 1 0 0 248 | outer loop 249 | vertex -1 -10 1 250 | vertex -1 -10 0 251 | vertex -1 -1 0 252 | endloop 253 | endfacet 254 | facet normal 1 0 0 255 | outer loop 256 | vertex -1 -1 1.1697 257 | vertex -1 -10 1 258 | vertex -1 -1 1 259 | endloop 260 | endfacet 261 | facet normal 1 0 0 262 | outer loop 263 | vertex -1 -1 1 264 | vertex -1 -10 1 265 | vertex -1 -1 0 266 | endloop 267 | endfacet 268 | facet normal -0.0653475 0.997863 0 269 | outer loop 270 | vertex -1 -1 1.1697 271 | vertex -1 -1 1 272 | vertex -9.94672 -1.5859 1.1697 273 | endloop 274 | endfacet 275 | facet normal 0 0.278203 0.960522 276 | outer loop 277 | vertex -1 -1 1 278 | vertex -10 -1 1 279 | vertex -9.94672 -1.5859 1.1697 280 | endloop 281 | endfacet 282 | facet normal -0.0287531 0.439063 0.897996 283 | outer loop 284 | vertex -1 -1 1.1697 285 | vertex -9.94672 -1.5859 1.1697 286 | vertex -9.79812 -2.06555 1.40897 287 | endloop 288 | endfacet 289 | facet normal -0.955211 -0.295925 0 290 | outer loop 291 | vertex -9.94672 -1.5859 0 292 | vertex -9.79812 -2.06555 0 293 | vertex -9.94672 -1.5859 1.1697 294 | endloop 295 | endfacet 296 | facet normal -0.955211 -0.295925 0 297 | outer loop 298 | vertex -9.94672 -1.5859 1.1697 299 | vertex -9.79812 -2.06555 0 300 | vertex -9.79812 -2.06555 1.40897 301 | endloop 302 | endfacet 303 | facet normal -0.863941 -0.503592 0 304 | outer loop 305 | vertex -9.79812 -2.06555 0 306 | vertex -9.57026 -2.45645 0 307 | vertex -9.79812 -2.06555 1.40897 308 | endloop 309 | endfacet 310 | facet normal -0.863941 -0.503592 0 311 | outer loop 312 | vertex -9.79812 -2.06555 1.40897 313 | vertex -9.57026 -2.45645 0 314 | vertex -9.57026 -2.45645 1.70109 315 | endloop 316 | endfacet 317 | facet normal -0.73682 -0.676089 0 318 | outer loop 319 | vertex -9.57026 -2.45645 0 320 | vertex -9.27807 -2.77489 0 321 | vertex -9.57026 -2.45645 1.70109 322 | endloop 323 | endfacet 324 | facet normal -0.73682 -0.676089 0 325 | outer loop 326 | vertex -9.57026 -2.45645 1.70109 327 | vertex -9.27807 -2.77489 0 328 | vertex -9.27807 -2.77489 2.03051 329 | endloop 330 | endfacet 331 | facet normal -0.605927 -0.79552 0 332 | outer loop 333 | vertex -9.27807 -2.77489 2.03051 334 | vertex -9.27807 -2.77489 0 335 | vertex -8.93535 -3.03593 0 336 | endloop 337 | endfacet 338 | facet normal -0.605927 -0.79552 0 339 | outer loop 340 | vertex -8.93535 -3.03593 2.38288 341 | vertex -9.27807 -2.77489 2.03051 342 | vertex -8.93535 -3.03593 0 343 | endloop 344 | endfacet 345 | facet normal -0.49617 -0.868226 0 346 | outer loop 347 | vertex -8.93535 -3.03593 2.38288 348 | vertex -8.93535 -3.03593 0 349 | vertex -8.55481 -3.2534 0 350 | endloop 351 | endfacet 352 | facet normal -0.49617 -0.868226 0 353 | outer loop 354 | vertex -8.55481 -3.2534 2.74506 355 | vertex -8.93535 -3.03593 2.38288 356 | vertex -8.55481 -3.2534 0 357 | endloop 358 | endfacet 359 | facet normal -0.416794 -0.909001 0 360 | outer loop 361 | vertex -8.55481 -3.2534 2.74506 362 | vertex -8.55481 -3.2534 0 363 | vertex -8.14802 -3.43992 0 364 | endloop 365 | endfacet 366 | facet normal -0.416794 -0.909001 0 367 | outer loop 368 | vertex -8.14802 -3.43992 3.10509 369 | vertex -8.55481 -3.2534 2.74506 370 | vertex -8.14802 -3.43992 0 371 | endloop 372 | endfacet 373 | facet normal -0.367473 -0.930034 0 374 | outer loop 375 | vertex -8.14802 -3.43992 3.10509 376 | vertex -8.14802 -3.43992 0 377 | vertex -7.72544 -3.60689 0 378 | endloop 379 | endfacet 380 | facet normal -0.367473 -0.930034 0 381 | outer loop 382 | vertex -7.72544 -3.60689 3.45221 383 | vertex -8.14802 -3.43992 3.10509 384 | vertex -7.72544 -3.60689 0 385 | endloop 386 | endfacet 387 | facet normal -0.344791 -0.938679 0 388 | outer loop 389 | vertex -7.72544 -3.60689 3.45221 390 | vertex -7.72544 -3.60689 0 391 | vertex -7.29641 -3.76448 0 392 | endloop 393 | endfacet 394 | facet normal -0.344791 -0.938679 0 395 | outer loop 396 | vertex -7.29641 -3.76448 3.77687 397 | vertex -7.72544 -3.60689 3.45221 398 | vertex -7.29641 -3.76448 0 399 | endloop 400 | endfacet 401 | facet normal -0.345229 -0.938518 0 402 | outer loop 403 | vertex -7.29641 -3.76448 3.77687 404 | vertex -7.29641 -3.76448 0 405 | vertex -6.86916 -3.92164 0 406 | endloop 407 | endfacet 408 | facet normal -0.345229 -0.938518 0 409 | outer loop 410 | vertex -6.86916 -3.92164 4.07068 411 | vertex -7.29641 -3.76448 3.77687 412 | vertex -6.86916 -3.92164 0 413 | endloop 414 | endfacet 415 | facet normal -0.365865 -0.930668 0 416 | outer loop 417 | vertex -6.86916 -3.92164 4.07068 418 | vertex -6.86916 -3.92164 0 419 | vertex -6.45079 -4.08611 0 420 | endloop 421 | endfacet 422 | facet normal -0.365865 -0.930668 0 423 | outer loop 424 | vertex -6.45079 -4.08611 4.32649 425 | vertex -6.86916 -3.92164 4.07068 426 | vertex -6.45079 -4.08611 0 427 | endloop 428 | endfacet 429 | facet normal -0.404157 -0.91469 0 430 | outer loop 431 | vertex -6.45079 -4.08611 4.32649 432 | vertex -6.45079 -4.08611 0 433 | vertex -6.0473 -4.26439 0 434 | endloop 435 | endfacet 436 | facet normal -0.404157 -0.91469 0 437 | outer loop 438 | vertex -6.0473 -4.26439 4.5383 439 | vertex -6.45079 -4.08611 4.32649 440 | vertex -6.0473 -4.26439 0 441 | endloop 442 | endfacet 443 | facet normal -0.457405 -0.889259 0 444 | outer loop 445 | vertex -6.0473 -4.26439 4.5383 446 | vertex -6.0473 -4.26439 0 447 | vertex -5.66356 -4.46178 0 448 | endloop 449 | endfacet 450 | facet normal -0.457405 -0.889259 0 451 | outer loop 452 | vertex -5.66356 -4.46178 4.70135 453 | vertex -6.0473 -4.26439 4.5383 454 | vertex -5.66356 -4.46178 0 455 | endloop 456 | endfacet 457 | facet normal -0.522157 -0.852849 0 458 | outer loop 459 | vertex -5.66356 -4.46178 4.70135 460 | vertex -5.66356 -4.46178 0 461 | vertex -5.30332 -4.68233 0 462 | endloop 463 | endfacet 464 | facet normal -0.522157 -0.852849 0 465 | outer loop 466 | vertex -5.30332 -4.68233 4.81204 467 | vertex -5.66356 -4.46178 4.70135 468 | vertex -5.30332 -4.68233 0 469 | endloop 470 | endfacet 471 | facet normal -0.593814 -0.804602 0 472 | outer loop 473 | vertex -5.30332 -4.68233 4.81204 474 | vertex -5.30332 -4.68233 0 475 | vertex -4.96923 -4.9289 0 476 | endloop 477 | endfacet 478 | facet normal -0.593814 -0.804602 0 479 | outer loop 480 | vertex -4.96923 -4.9289 4.86798 481 | vertex -5.30332 -4.68233 4.81204 482 | vertex -4.96923 -4.9289 0 483 | endloop 484 | endfacet 485 | facet normal -0.666838 -0.745202 0 486 | outer loop 487 | vertex -4.96923 -4.9289 4.86798 488 | vertex -4.96923 -4.9289 0 489 | vertex -4.66279 -5.20311 0 490 | endloop 491 | endfacet 492 | facet normal -0.666838 -0.745202 0 493 | outer loop 494 | vertex -4.66279 -5.20311 4.86798 495 | vertex -4.96923 -4.9289 4.86798 496 | vertex -4.66279 -5.20311 0 497 | endloop 498 | endfacet 499 | facet normal -0.735569 -0.67745 0 500 | outer loop 501 | vertex -4.66279 -5.20311 0 502 | vertex -4.38442 -5.50537 0 503 | vertex -4.66279 -5.20311 4.86798 504 | endloop 505 | endfacet 506 | facet normal -0.735569 -0.67745 0 507 | outer loop 508 | vertex -4.66279 -5.20311 4.86798 509 | vertex -4.38442 -5.50537 0 510 | vertex -4.38442 -5.50537 4.81204 511 | endloop 512 | endfacet 513 | facet normal -0.795442 -0.606029 0 514 | outer loop 515 | vertex -4.38442 -5.50537 0 516 | vertex -4.1334 -5.83484 0 517 | vertex -4.38442 -5.50537 4.81204 518 | endloop 519 | endfacet 520 | facet normal -0.795442 -0.606029 0 521 | outer loop 522 | vertex -4.38442 -5.50537 4.81204 523 | vertex -4.1334 -5.83484 0 524 | vertex -4.1334 -5.83484 4.70135 525 | endloop 526 | endfacet 527 | facet normal -0.843867 -0.536553 0 528 | outer loop 529 | vertex -4.1334 -5.83484 0 530 | vertex -3.9079 -6.1895 0 531 | vertex -4.1334 -5.83484 4.70135 532 | endloop 533 | endfacet 534 | facet normal -0.843867 -0.536553 0 535 | outer loop 536 | vertex -4.1334 -5.83484 4.70135 537 | vertex -3.9079 -6.1895 0 538 | vertex -3.9079 -6.1895 4.5383 539 | endloop 540 | endfacet 541 | facet normal -0.880316 -0.474388 0 542 | outer loop 543 | vertex -3.9079 -6.1895 0 544 | vertex -3.70496 -6.56609 0 545 | vertex -3.9079 -6.1895 4.5383 546 | endloop 547 | endfacet 548 | facet normal -0.880316 -0.474388 0 549 | outer loop 550 | vertex -3.9079 -6.1895 4.5383 551 | vertex -3.70496 -6.56609 0 552 | vertex -3.70496 -6.56609 4.32649 553 | endloop 554 | endfacet 555 | facet normal -0.905691 -0.423938 0 556 | outer loop 557 | vertex -3.70496 -6.56609 0 558 | vertex -3.52053 -6.96011 0 559 | vertex -3.70496 -6.56609 4.32649 560 | endloop 561 | endfacet 562 | facet normal -0.905691 -0.423938 0 563 | outer loop 564 | vertex -3.70496 -6.56609 4.32649 565 | vertex -3.52053 -6.96011 0 566 | vertex -3.52053 -6.96011 4.07068 567 | endloop 568 | endfacet 569 | facet normal -0.921414 -0.388582 0 570 | outer loop 571 | vertex -3.52053 -6.96011 0 572 | vertex -3.34941 -7.36587 0 573 | vertex -3.52053 -6.96011 4.07068 574 | endloop 575 | endfacet 576 | facet normal -0.921414 -0.388582 0 577 | outer loop 578 | vertex -3.52053 -6.96011 4.07068 579 | vertex -3.34941 -7.36587 0 580 | vertex -3.34941 -7.36587 3.77687 581 | endloop 582 | endfacet 583 | facet normal -0.928574 -0.371148 0 584 | outer loop 585 | vertex -3.34941 -7.36587 0 586 | vertex -3.18531 -7.77644 0 587 | vertex -3.34941 -7.36587 3.77687 588 | endloop 589 | endfacet 590 | facet normal -0.928574 -0.371148 0 591 | outer loop 592 | vertex -3.34941 -7.36587 3.77687 593 | vertex -3.18531 -7.77644 0 594 | vertex -3.18531 -7.77644 3.45221 595 | endloop 596 | endfacet 597 | facet normal -0.927203 -0.374559 0 598 | outer loop 599 | vertex -3.18531 -7.77644 0 600 | vertex -3.0208 -8.18367 0 601 | vertex -3.18531 -7.77644 3.45221 602 | endloop 603 | endfacet 604 | facet normal -0.927203 -0.374559 0 605 | outer loop 606 | vertex -3.18531 -7.77644 3.45221 607 | vertex -3.0208 -8.18367 0 608 | vertex -3.0208 -8.18367 3.10509 609 | endloop 610 | endfacet 611 | facet normal -0.915435 -0.402466 0 612 | outer loop 613 | vertex -3.0208 -8.18367 0 614 | vertex -2.84735 -8.5782 0 615 | vertex -3.0208 -8.18367 3.10509 616 | endloop 617 | endfacet 618 | facet normal -0.915435 -0.402466 0 619 | outer loop 620 | vertex -3.0208 -8.18367 3.10509 621 | vertex -2.84735 -8.5782 0 622 | vertex -2.84735 -8.5782 2.74506 623 | endloop 624 | endfacet 625 | facet normal -0.888188 -0.45948 0 626 | outer loop 627 | vertex -2.84735 -8.5782 0 628 | vertex -2.6553 -8.94943 0 629 | vertex -2.84735 -8.5782 2.74506 630 | endloop 631 | endfacet 632 | facet normal -0.888188 -0.45948 0 633 | outer loop 634 | vertex -2.84735 -8.5782 2.74506 635 | vertex -2.6553 -8.94943 0 636 | vertex -2.6553 -8.94943 2.38288 637 | endloop 638 | endfacet 639 | facet normal -0.835097 -0.550103 0 640 | outer loop 641 | vertex -2.6553 -8.94943 0 642 | vertex -2.43389 -9.28555 0 643 | vertex -2.6553 -8.94943 2.38288 644 | endloop 645 | endfacet 646 | facet normal -0.835097 -0.550103 0 647 | outer loop 648 | vertex -2.6553 -8.94943 2.38288 649 | vertex -2.43389 -9.28555 0 650 | vertex -2.43389 -9.28555 2.03051 651 | endloop 652 | endfacet 653 | facet normal -0.738829 -0.673893 0 654 | outer loop 655 | vertex -2.43389 -9.28555 0 656 | vertex -2.17121 -9.57353 0 657 | vertex -2.43389 -9.28555 2.03051 658 | endloop 659 | endfacet 660 | facet normal -0.738829 -0.673893 0 661 | outer loop 662 | vertex -2.43389 -9.28555 2.03051 663 | vertex -2.17121 -9.57353 0 664 | vertex -2.17121 -9.57353 1.70109 665 | endloop 666 | endfacet 667 | facet normal -0.579888 -0.814696 0 668 | outer loop 669 | vertex -2.17121 -9.57353 1.70109 670 | vertex -2.17121 -9.57353 0 671 | vertex -1.85428 -9.79913 0 672 | endloop 673 | endfacet 674 | facet normal -0.579888 -0.814696 0 675 | outer loop 676 | vertex -1.85428 -9.79913 1.40897 677 | vertex -2.17121 -9.57353 1.70109 678 | vertex -1.85428 -9.79913 0 679 | endloop 680 | endfacet 681 | facet normal -0.357964 -0.933735 0 682 | outer loop 683 | vertex -1.85428 -9.79913 1.40897 684 | vertex -1.85428 -9.79913 0 685 | vertex -1.46895 -9.94685 0 686 | endloop 687 | endfacet 688 | facet normal -0.357964 -0.933735 0 689 | outer loop 690 | vertex -1.46895 -9.94685 1.1697 691 | vertex -1.85428 -9.79913 1.40897 692 | vertex -1.46895 -9.94685 0 693 | endloop 694 | endfacet 695 | facet normal -0.112625 -0.993638 0 696 | outer loop 697 | vertex -1.46895 -9.94685 1.1697 698 | vertex -1.46895 -9.94685 0 699 | vertex -1 -10 0 700 | endloop 701 | endfacet 702 | facet normal -0.112625 -0.993638 0 703 | outer loop 704 | vertex -1 -10 1 705 | vertex -1.46895 -9.94685 1.1697 706 | vertex -1 -10 0 707 | endloop 708 | endfacet 709 | facet normal 0.338439 -0.0177395 0.940821 710 | outer loop 711 | vertex -1 -1 1.1697 712 | vertex -1.46895 -9.94685 1.1697 713 | vertex -1 -10 1 714 | endloop 715 | endfacet 716 | facet normal 0.998629 -0.0523437 0 717 | outer loop 718 | vertex -1 -1 1.40897 719 | vertex -1.46895 -9.94685 1.1697 720 | vertex -1 -1 1.1697 721 | endloop 722 | endfacet 723 | facet normal -0.120232 0.992746 0 724 | outer loop 725 | vertex -1 -1 1.40897 726 | vertex -1 -1 1.1697 727 | vertex -9.79812 -2.06555 1.40897 728 | endloop 729 | endfacet 730 | facet normal -0.0691537 0.570995 0.818036 731 | outer loop 732 | vertex -1 -1 1.40897 733 | vertex -9.79812 -2.06555 1.40897 734 | vertex -9.57026 -2.45645 1.70109 735 | endloop 736 | endfacet 737 | facet normal -0.112609 0.662628 0.740434 738 | outer loop 739 | vertex -1 -1 1.70109 740 | vertex -9.57026 -2.45645 1.70109 741 | vertex -9.27807 -2.77489 2.03051 742 | endloop 743 | endfacet 744 | facet normal -0.167541 0.985865 0 745 | outer loop 746 | vertex -1 -1 1.70109 747 | vertex -1 -1 1.40897 748 | vertex -9.57026 -2.45645 1.70109 749 | endloop 750 | endfacet 751 | facet normal -0.153652 0.71663 0.680318 752 | outer loop 753 | vertex -1 -1 2.03051 754 | vertex -9.27807 -2.77489 2.03051 755 | vertex -8.93535 -3.03593 2.38288 756 | endloop 757 | endfacet 758 | facet normal -0.209645 0.977778 0 759 | outer loop 760 | vertex -1 -1 2.03051 761 | vertex -1 -1 1.70109 762 | vertex -9.27807 -2.77489 2.03051 763 | endloop 764 | endfacet 765 | facet normal -0.190034 0.740686 0.644416 766 | outer loop 767 | vertex -1 -1 2.38288 768 | vertex -8.93535 -3.03593 2.38288 769 | vertex -8.55481 -3.2534 2.74506 770 | endloop 771 | endfacet 772 | facet normal -0.248516 0.968628 0 773 | outer loop 774 | vertex -1 -1 2.38288 775 | vertex -1 -1 2.03051 776 | vertex -8.93535 -3.03593 2.38288 777 | endloop 778 | endfacet 779 | facet normal -0.221087 0.741221 0.633808 780 | outer loop 781 | vertex -1 -1 2.74506 782 | vertex -8.55481 -3.2534 2.74506 783 | vertex -8.14802 -3.43992 3.10509 784 | endloop 785 | endfacet 786 | facet normal -0.28583 0.95828 0 787 | outer loop 788 | vertex -1 -1 2.74506 789 | vertex -1 -1 2.38288 790 | vertex -8.55481 -3.2534 2.74506 791 | endloop 792 | endfacet 793 | facet normal -0.246323 0.721628 0.646976 794 | outer loop 795 | vertex -1 -1 3.10509 796 | vertex -8.14802 -3.43992 3.10509 797 | vertex -7.72544 -3.60689 3.45221 798 | endloop 799 | endfacet 800 | facet normal -0.323042 0.946385 0 801 | outer loop 802 | vertex -1 -1 3.10509 803 | vertex -1 -1 2.74506 804 | vertex -8.14802 -3.43992 3.10509 805 | endloop 806 | endfacet 807 | facet normal -0.264627 0.682703 0.681094 808 | outer loop 809 | vertex -1 -1 3.45221 810 | vertex -7.72544 -3.60689 3.45221 811 | vertex -7.29641 -3.76448 3.77687 812 | endloop 813 | endfacet 814 | facet normal -0.361416 0.932405 0 815 | outer loop 816 | vertex -1 -1 3.45221 817 | vertex -1 -1 3.10509 818 | vertex -7.72544 -3.60689 3.45221 819 | endloop 820 | endfacet 821 | facet normal -0.273901 0.623839 0.731986 822 | outer loop 823 | vertex -1 -1 3.77687 824 | vertex -7.29641 -3.76448 3.77687 825 | vertex -6.86916 -3.92164 4.07068 826 | endloop 827 | endfacet 828 | facet normal -0.402015 0.915633 0 829 | outer loop 830 | vertex -1 -1 3.77687 831 | vertex -1 -1 3.45221 832 | vertex -7.29641 -3.76448 3.77687 833 | endloop 834 | endfacet 835 | facet normal -0.27113 0.54466 0.793621 836 | outer loop 837 | vertex -1 -1 4.07068 838 | vertex -6.86916 -3.92164 4.07068 839 | vertex -6.45079 -4.08611 4.32649 840 | endloop 841 | endfacet 842 | facet normal -0.445635 0.895215 0 843 | outer loop 844 | vertex -1 -1 4.07068 845 | vertex -1 -1 3.77687 846 | vertex -6.86916 -3.92164 4.07068 847 | endloop 848 | endfacet 849 | facet normal -0.253007 0.446869 0.858076 850 | outer loop 851 | vertex -1 -1 4.32649 852 | vertex -6.45079 -4.08611 4.32649 853 | vertex -6.0473 -4.26439 4.5383 854 | endloop 855 | endfacet 856 | facet normal -0.49269 0.870205 0 857 | outer loop 858 | vertex -1 -1 4.32649 859 | vertex -1 -1 4.07068 860 | vertex -6.45079 -4.08611 4.32649 861 | endloop 862 | endfacet 863 | facet normal -0.216958 0.335453 0.916734 864 | outer loop 865 | vertex -1 -1 4.5383 866 | vertex -6.0473 -4.26439 4.5383 867 | vertex -5.66356 -4.46178 4.70135 868 | endloop 869 | endfacet 870 | facet normal -0.543075 0.839685 0 871 | outer loop 872 | vertex -1 -1 4.5383 873 | vertex -1 -1 4.32649 874 | vertex -6.0473 -4.26439 4.5383 875 | endloop 876 | endfacet 877 | facet normal -0.162044 0.218298 0.962335 878 | outer loop 879 | vertex -1 -1 4.70135 880 | vertex -5.66356 -4.46178 4.70135 881 | vertex -5.30332 -4.68233 4.81204 882 | endloop 883 | endfacet 884 | facet normal -0.596038 0.802957 0 885 | outer loop 886 | vertex -1 -1 4.70135 887 | vertex -1 -1 4.5383 888 | vertex -5.66356 -4.46178 4.70135 889 | endloop 890 | endfacet 891 | facet normal -0.0890554 0.104074 0.990574 892 | outer loop 893 | vertex -1 -1 4.81204 894 | vertex -5.30332 -4.68233 4.81204 895 | vertex -4.96923 -4.9289 4.86798 896 | endloop 897 | endfacet 898 | facet normal -0.650157 0.7598 0 899 | outer loop 900 | vertex -1 -1 4.81204 901 | vertex -1 -1 4.70135 902 | vertex -5.30332 -4.68233 4.81204 903 | endloop 904 | endfacet 905 | facet normal 0 0 1 906 | outer loop 907 | vertex -1 -1 4.86798 908 | vertex -4.96923 -4.9289 4.86798 909 | vertex -4.66279 -5.20311 4.86798 910 | endloop 911 | endfacet 912 | facet normal -0.703488 0.710707 0 913 | outer loop 914 | vertex -1 -1 4.86798 915 | vertex -1 -1 4.81204 916 | vertex -4.96923 -4.9289 4.86798 917 | endloop 918 | endfacet 919 | facet normal 0.102303 -0.0891517 0.99075 920 | outer loop 921 | vertex -1 -1 4.86798 922 | vertex -4.66279 -5.20311 4.86798 923 | vertex -4.38442 -5.50537 4.81204 924 | endloop 925 | endfacet 926 | facet normal 0.79954 -0.600613 0 927 | outer loop 928 | vertex -1 -1 4.86798 929 | vertex -4.38442 -5.50537 4.81204 930 | vertex -1 -1 4.81204 931 | endloop 932 | endfacet 933 | facet normal 0.213939 -0.160711 0.963536 934 | outer loop 935 | vertex -1 -1 4.81204 936 | vertex -4.38442 -5.50537 4.81204 937 | vertex -4.1334 -5.83484 4.70135 938 | endloop 939 | endfacet 940 | facet normal 0.839176 -0.543859 0 941 | outer loop 942 | vertex -1 -1 4.81204 943 | vertex -4.1334 -5.83484 4.70135 944 | vertex -1 -1 4.70135 945 | endloop 946 | endfacet 947 | facet normal 0.329336 -0.213438 0.919773 948 | outer loop 949 | vertex -1 -1 4.70135 950 | vertex -4.1334 -5.83484 4.70135 951 | vertex -3.9079 -6.1895 4.5383 952 | endloop 953 | endfacet 954 | facet normal 0.872379 -0.48883 0 955 | outer loop 956 | vertex -1 -1 4.70135 957 | vertex -3.9079 -6.1895 4.5383 958 | vertex -1 -1 4.5383 959 | endloop 960 | endfacet 961 | facet normal 0.441371 -0.247319 0.862569 962 | outer loop 963 | vertex -1 -1 4.5383 964 | vertex -3.9079 -6.1895 4.5383 965 | vertex -3.70496 -6.56609 4.32649 966 | endloop 967 | endfacet 968 | facet normal 0.899417 -0.437091 0 969 | outer loop 970 | vertex -1 -1 4.5383 971 | vertex -3.70496 -6.56609 4.32649 972 | vertex -1 -1 4.32649 973 | endloop 974 | endfacet 975 | facet normal 0.542662 -0.263719 0.797477 976 | outer loop 977 | vertex -1 -1 4.32649 978 | vertex -3.70496 -6.56609 4.32649 979 | vertex -3.52053 -6.96011 4.07068 980 | endloop 981 | endfacet 982 | facet normal 0.921026 -0.389501 0 983 | outer loop 984 | vertex -1 -1 4.32649 985 | vertex -3.52053 -6.96011 4.07068 986 | vertex -1 -1 4.07068 987 | endloop 988 | endfacet 989 | facet normal 0.627531 -0.265382 0.731968 990 | outer loop 991 | vertex -1 -1 4.07068 992 | vertex -3.52053 -6.96011 4.07068 993 | vertex -3.34941 -7.36587 3.77687 994 | endloop 995 | endfacet 996 | facet normal 0.938148 -0.346236 0 997 | outer loop 998 | vertex -1 -1 4.07068 999 | vertex -3.34941 -7.36587 3.77687 1000 | vertex -1 -1 3.77687 1001 | endloop 1002 | endfacet 1003 | facet normal 0.693144 -0.255814 0.673877 1004 | outer loop 1005 | vertex -1 -1 3.77687 1006 | vertex -3.34941 -7.36587 3.77687 1007 | vertex -3.18531 -7.77644 3.45221 1008 | endloop 1009 | endfacet 1010 | facet normal 0.951735 -0.306921 0 1011 | outer loop 1012 | vertex -1 -1 3.77687 1013 | vertex -3.18531 -7.77644 3.45221 1014 | vertex -1 -1 3.45221 1015 | endloop 1016 | endfacet 1017 | facet normal 0.739157 -0.238368 0.629943 1018 | outer loop 1019 | vertex -1 -1 3.45221 1020 | vertex -3.18531 -7.77644 3.45221 1021 | vertex -3.0208 -8.18367 3.10509 1022 | endloop 1023 | endfacet 1024 | facet normal 0.962637 -0.270794 0 1025 | outer loop 1026 | vertex -1 -1 3.45221 1027 | vertex -3.0208 -8.18367 3.10509 1028 | vertex -1 -1 3.10509 1029 | endloop 1030 | endfacet 1031 | facet normal 0.766229 -0.215543 0.605338 1032 | outer loop 1033 | vertex -1 -1 3.10509 1034 | vertex -3.0208 -8.18367 3.10509 1035 | vertex -2.84735 -8.5782 2.74506 1036 | endloop 1037 | endfacet 1038 | facet normal 0.97155 -0.236836 0 1039 | outer loop 1040 | vertex -1 -1 3.10509 1041 | vertex -2.84735 -8.5782 2.74506 1042 | vertex -1 -1 2.74506 1043 | endloop 1044 | endfacet 1045 | facet normal 0.774286 -0.188749 0.604032 1046 | outer loop 1047 | vertex -1 -1 2.74506 1048 | vertex -2.84735 -8.5782 2.74506 1049 | vertex -2.6553 -8.94943 2.38288 1050 | endloop 1051 | endfacet 1052 | facet normal 0.979001 -0.203856 0 1053 | outer loop 1054 | vertex -1 -1 2.74506 1055 | vertex -2.6553 -8.94943 2.38288 1056 | vertex -1 -1 2.38288 1057 | endloop 1058 | endfacet 1059 | facet normal 0.760889 -0.158439 0.629241 1060 | outer loop 1061 | vertex -1 -1 2.38288 1062 | vertex -2.6553 -8.94943 2.38288 1063 | vertex -2.43389 -9.28555 2.03051 1064 | endloop 1065 | endfacet 1066 | facet normal 0.985354 -0.170524 0 1067 | outer loop 1068 | vertex -1 -1 2.38288 1069 | vertex -2.43389 -9.28555 2.03051 1070 | vertex -1 -1 2.03051 1071 | endloop 1072 | endfacet 1073 | facet normal 0.719828 -0.124572 0.682883 1074 | outer loop 1075 | vertex -1 -1 2.03051 1076 | vertex -2.43389 -9.28555 2.03051 1077 | vertex -2.17121 -9.57353 1.70109 1078 | endloop 1079 | endfacet 1080 | facet normal 0.990798 -0.135351 0 1081 | outer loop 1082 | vertex -1 -1 2.03051 1083 | vertex -2.17121 -9.57353 1.70109 1084 | vertex -1 -1 1.70109 1085 | endloop 1086 | endfacet 1087 | facet normal 0.640729 -0.0875287 0.762762 1088 | outer loop 1089 | vertex -1 -1 1.70109 1090 | vertex -2.17121 -9.57353 1.70109 1091 | vertex -1.85428 -9.79913 1.40897 1092 | endloop 1093 | endfacet 1094 | facet normal 0.99532 -0.0966323 0 1095 | outer loop 1096 | vertex -1 -1 1.70109 1097 | vertex -1.85428 -9.79913 1.40897 1098 | vertex -1 -1 1.40897 1099 | endloop 1100 | endfacet 1101 | facet normal 0.513032 -0.0498086 0.856923 1102 | outer loop 1103 | vertex -1 -1 1.40897 1104 | vertex -1.85428 -9.79913 1.40897 1105 | vertex -1.46895 -9.94685 1.1697 1106 | endloop 1107 | endfacet 1108 | endsolid OpenSCAD_Model 1109 | -------------------------------------------------------------------------------- /BezierScad.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | Coffeescript generator for Bezier functions for OpenScad 3 | Sources/Inspirations: 4 | http://en.wikipedia.org/wiki/Bézier_curve 5 | http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html 6 | http://www.thingiverse.com/thing:8443 7 | 8 | Copyright (c) 2013 Chad Kirby 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. 27 | ### 28 | 29 | binomialCoeffs = (n) -> 30 | cfs = [1] 31 | for k in [0...n] 32 | cfs.push (cfs[k] * (n-k)) / (k+1) 33 | cfs 34 | 35 | ptFn = (order, indent = ' ') -> 36 | coeffs = binomialCoeffs(order-1) 37 | # console.log coeffs 38 | args = ["t", "ctls"] 39 | scad = for cf, i in coeffs 40 | itpow = coeffs.length - i - 1 41 | s = "(" 42 | s += "#{cf} * " if cf > 1 43 | s += "pow(t, #{i}) * " if i > 1 44 | s += "t * " if i is 1 45 | s += "pow(1-t, #{itpow}) * " if itpow > 1 46 | s += "(1-t) * " if itpow is 1 47 | # s += "p[#{i}][n])" 48 | s += "ctls[#{i}]" 49 | s += ")" 50 | # s += "p#{i})" 51 | # args.push "p#{i}" 52 | s 53 | 54 | """ 55 | function BezI#{order}(#{args.join ', '}) = 56 | #{scad.join( " +\n#{indent}") + "\n#{indent};\n"} 57 | """ 58 | 59 | orderMax = 8 60 | maxLineResolution = 6 61 | 62 | bezScad = """ 63 | /* 64 | Bezier functions for OpenScad 65 | Generated from #{require('path').basename(process.argv[1])} from #{process.platform} at #{new Date()} 66 | Supports Bezier interpolation with 1-#{orderMax} controls 67 | Sources/Inspirations: 68 | http://en.wikipedia.org/wiki/Bézier_curve 69 | http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html 70 | http://www.thingiverse.com/thing:8443 71 | 72 | Copyright (c) 2013 Chad Kirby 73 | 74 | Permission is hereby granted, free of charge, to any person obtaining a copy 75 | of this software and associated documentation files (the "Software"), to deal 76 | in the Software without restriction, including without limitation the rights 77 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 78 | copies of the Software, and to permit persons to whom the Software is 79 | furnished to do so, subject to the following conditions: 80 | 81 | The above copyright notice and this permission notice shall be included in 82 | all copies or substantial portions of the Software. 83 | 84 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 85 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 86 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 87 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 88 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 89 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 90 | THE SOFTWARE. 91 | */ 92 | 93 | 94 | """ 95 | 96 | 97 | bezScad += """ 98 | 99 | module BezLine(ctlPts, width = [1], resolution = 4, centered = false, showCtls = true) { 100 | hodoPts = hodograph(ctlPts); 101 | if (showCtls) { 102 | for (pt = ctlPts) { 103 | % translate([pt[0], pt[1], 0]) circle(1); 104 | } 105 | } 106 | 107 | """ + ( 108 | for resolution in [2..maxLineResolution] 109 | steps = Math.pow(2, resolution) 110 | pts = for i in [0...steps] 111 | "PointAlongBez(#{i}/#{steps-1}, ctlPts)" 112 | 113 | for i in [steps-1..0] 114 | pts.push "PerpAlongBez(#{i}/#{steps-1}, ctlPts, dist = BezI(#{i}/#{steps-1}, width), hodograph = hodoPts)" 115 | 116 | cpts = for i in [0...steps] 117 | "PerpAlongBez(#{i}/#{steps-1}, ctlPts, dist = BezI(#{i}/#{steps-1}, width)/2, hodograph = hodoPts)" 118 | 119 | for i in [steps-1..0] 120 | cpts.push "PerpAlongBez(#{i}/#{steps-1}, ctlPts, dist = BezI(#{i}/#{steps-1}, width)/-2, hodograph = hodoPts)" 121 | 122 | """ 123 | if (resolution == #{resolution}) { 124 | if (centered) { 125 | polygon([ 126 | #{cpts.join(', ')} 127 | ]); 128 | } else { 129 | polygon([ 130 | #{pts.join(', ')} 131 | ]); 132 | } 133 | } 134 | """ 135 | ).join(' else ').replace(/^/gm,' ') + """ 136 | 137 | } 138 | """ 139 | 140 | 141 | bezScad += """ 142 | 143 | module BezWall( 144 | ctlPts, 145 | width = 1, 146 | height = 1, 147 | steps = 16, 148 | widthCtls = [], 149 | heightCtls = [], 150 | centered = false, 151 | showCtlR = 1 152 | ) { 153 | hodoPts = hodograph(ctlPts); 154 | if (showCtlR > 0) { 155 | for (pt = ctlPts) { 156 | % translate([pt[0], pt[1], 0]) circle(showCtlR); 157 | } 158 | } 159 | triangles = [ [0,2,1], [0,3,2], [0,4,5], [0,1,4], [0,6,3], [0,5,6], [4,6,5], [4,7,6], [1,2,7], [1,7,4], [2,3,6], [2,6,7], ]; 160 | for(step = [steps-1 : 1]) 161 | { 162 | assign( 163 | t1 = step/(steps-1), 164 | t0 = (step-1)/(steps-1) 165 | ) { 166 | assign( 167 | hgt0 = len(heightCtls) > 0 ? BezI(t0, heightCtls) : height, 168 | hgt1 = len(heightCtls) > 0 ? BezI(t1, heightCtls) : height, 169 | wid0 = len(widthCtls) > 0 ? BezI(t0, widthCtls) : width, 170 | wid1 = len(widthCtls) > 0 ? BezI(t1, widthCtls) : width 171 | ) { 172 | if (centered) { 173 | assign( 174 | p0 = PerpAlongBez(t0, ctlPts, dist = -wid0/2, hodograph = hodoPts), 175 | p1 = PerpAlongBez(t0, ctlPts, dist = wid0/2, hodograph = hodoPts), 176 | p4 = PerpAlongBez(t1, ctlPts, dist = wid1/2, hodograph = hodoPts), 177 | p5 = PerpAlongBez(t1, ctlPts, dist = -wid1/2, hodograph = hodoPts) 178 | ) { 179 | if (hgt0 == 0 && hgt1 == 0 ) { 180 | polygon([ p5, p0, p1, p4 ]); 181 | } else if (hgt0 == hgt1) { 182 | linear_extrude(height = hgt0, convexity = 2) polygon([ p5, p0, p1, p4 ]); 183 | } else { 184 | polyhedron( 185 | points =[ 186 | [p0[0],p0[1],0], // 0 187 | [p1[0],p1[1],0], // 1 188 | [p1[0],p1[1],hgt0], // 2 189 | [p0[0],p0[1],hgt0], // 3 190 | [p4[0],p4[1],0], // 4 191 | [p5[0],p5[1],0], // 5 192 | [p5[0],p5[1],hgt1], // 6 193 | [p4[0],p4[1],hgt1], // 7 194 | ], 195 | triangles = triangles, 196 | convexity = 2 197 | ); 198 | } 199 | } 200 | } else { 201 | assign( 202 | p0 = PointAlongBez(t0, ctlPts), 203 | p1 = PerpAlongBez(t0, ctlPts, dist = wid0, hodograph = hodoPts), 204 | p4 = PerpAlongBez(t1, ctlPts, dist = wid1, hodograph = hodoPts), 205 | p5 = PointAlongBez(t1, ctlPts) 206 | ) { 207 | if (hgt0 == 0 && hgt1 == 0 ) { 208 | polygon([ p5, p0, p1, p4 ]); 209 | } else if (hgt0 == hgt1) { 210 | linear_extrude(height = hgt0, convexity = 2) polygon([ p5, p0, p1, p4 ]); 211 | } else { 212 | polyhedron( 213 | points =[ 214 | [p0[0],p0[1],0], // 0 215 | [p1[0],p1[1],0], // 1 216 | [p1[0],p1[1],hgt0], // 2 217 | [p0[0],p0[1],hgt0], // 3 218 | [p4[0],p4[1],0], // 4 219 | [p5[0],p5[1],0], // 5 220 | [p5[0],p5[1],hgt1], // 6 221 | [p4[0],p4[1],hgt1], // 7 222 | ], 223 | triangles = triangles, 224 | convexity = 2 225 | ); 226 | } 227 | } 228 | } 229 | } } 230 | } 231 | } 232 | 233 | module BezArc(ctlPts, focalPoint, steps=12, height = 1, heightCtls = [], showCtlR = 1) 234 | { 235 | if (showCtlR > 0) { 236 | for (pt = ctlPts) { 237 | % translate([pt[0], pt[1], 0]) circle(showCtlR); 238 | } 239 | } 240 | triangles = [ 241 | [0,2,1], 242 | [3,4,5], 243 | [1,5,4], 244 | [2,5,1], 245 | [0,1,4], 246 | [0,4,3], 247 | [0,5,2], 248 | [0,3,5], 249 | ]; 250 | for(step = [steps-1 : 1]) 251 | { 252 | assign( 253 | t1 = step/(steps-1), 254 | t0 = (step-1)/(steps-1), 255 | fp = [focalPoint[0], focalPoint[1], len(heightCtls) > 0 ? BezI(0, heightCtls) : height] 256 | ) { 257 | assign( 258 | hgt0 = len(heightCtls) > 0 ? BezI(t0, heightCtls) : height, 259 | hgt1 = len(heightCtls) > 0 ? BezI(t1, heightCtls) : height, 260 | p0 = PointAlongBez(t0, ctlPts), 261 | p1 = PointAlongBez(t1, ctlPts) 262 | ) { 263 | if (hgt0 == 0 && hgt1 == 0 ) { 264 | polygon([ focalPoint, p0, p1 ]); 265 | } else if (hgt0 == hgt1) { 266 | linear_extrude(height = hgt0, convexity = 2) polygon([ focalPoint, p0, p1 ]); 267 | } else { 268 | polyhedron( // not manifold 269 | points = [ 270 | [focalPoint[0], focalPoint[1], 0], // 0 271 | [p1[0], p1[1], 0], // 1 272 | [p0[0], p0[1], 0], // 2 273 | [focalPoint[0], focalPoint[1], hgt0], // 3 274 | [p1[0], p1[1], hgt1], // 4 275 | [p0[0], p0[1], hgt0], // 5 276 | [focalPoint[0], focalPoint[1], hgt1], // 6 277 | ], 278 | triangles = triangles, 279 | convexity = 2 280 | ); 281 | } 282 | } } 283 | } 284 | } 285 | 286 | """ 287 | 288 | bezScad += """ 289 | function PointAlongBez(t, ctlPts) = 290 | 291 | """ + ( 292 | for order in [1..orderMax] 293 | """ 294 | len(ctlPts) == #{order} ? PointAlongBez#{order}(t, ctlPts) : 295 | """ 296 | ).join(' \n ') + '\n [];\n\n' 297 | 298 | bezScad += """ 299 | function BezI(t, ctls) = 300 | 301 | """ + ( 302 | for order in [1..orderMax] 303 | """ 304 | len(ctls) == #{order} ? BezI#{order}(t, ctls) : 305 | """ 306 | ).join(' \n ') + '\n [];\n\n' 307 | 308 | for order in [1..orderMax] 309 | argsx = ("ctlPts[#{i}][0]" for i in [0...order]).join ', ' 310 | argsy = ("ctlPts[#{i}][1]" for i in [0...order]).join ', ' 311 | bezScad += """ 312 | function PointAlongBez#{order}(t, ctlPts) = [ 313 | BezI#{order}(t, [#{argsx}]), 314 | BezI#{order}(t, [#{argsy}]) 315 | ];\n 316 | """ 317 | 318 | bezScad += """ 319 | 320 | function PerpAlongBez(t, ctlPts, dist = 1, hodograph = []) = 321 | 322 | """ + ( 323 | for order in [2..orderMax] 324 | """ 325 | len(ctlPts) == #{order} ? PerpAlongBez#{order}(t, ctlPts, dist, hodograph) : 326 | """ 327 | ).join(' \n ') + '\n [];\n\n' 328 | 329 | for order in [2..orderMax] 330 | bezScad += """ 331 | function PerpAlongBez#{order}(t, ctlPts, dist = 1, hodograph = []) = 332 | pSum( 333 | PointAlongBez#{order}(t, ctlPts), 334 | rot90cw( 335 | normalize( 336 | PointAlongBez#{order-1}( t, (len(hodograph) > 1) ? hodograph : hodograph(ctlPts) ), 337 | dist 338 | ) 339 | ) 340 | ); 341 | 342 | 343 | """ 344 | 345 | hodographs = for order in [2..orderMax] 346 | pts = for i in [0...order-1] 347 | "pDiff(p[#{i+1}], p[#{i}])" 348 | """ 349 | len(p) == #{order} ? 350 | [ #{pts.join(', ')} ] : 351 | """ 352 | 353 | bezScad += """ 354 | 355 | function hodograph(p) = 356 | 357 | """ + hodographs.join(' \n ') + '\n [];' 358 | 359 | 360 | bezScad += '\n\n' + (ptFn(order) for order in [1..orderMax]).join('\n') + """ 361 | 362 | function x(p) = p[0]; 363 | function y(p) = p[1]; 364 | function dx(p1, p2) = x(p1) - x(p2); 365 | function dy(p1, p2) = y(p1) - y(p2); 366 | function sx(p1, p2) = x(p1) + x(p2); 367 | function sy(p1, p2) = y(p1) + y(p2); 368 | 369 | function dist(p1, p2 = [0,0]) = sqrt( pow( dx(p1,p2), 2) + pow( dy(p1,p2), 2) ); 370 | function normalize(p, n = 1) = pScale( p, n / dist( p ) ); 371 | 372 | function pSum(p1, p2) = [sx(p1, p2), sy(p1, p2)]; 373 | function pDiff(p1, p2) = [dx(p1, p2), dy(p1, p2)]; 374 | function pScale(p, v) = [x(p)*v, y(p)*v]; 375 | 376 | function rot90cw(p) = [y(p), -x(p)]; 377 | function rot90ccw(p) = [-y(p), x(p)]; 378 | function rot(p, a) = [ 379 | x(p) * cos(a) - y(p) * sin(a), 380 | x(p) * sin(a) - y(p) * cos(a), 381 | ]; 382 | function rotAbout(p1, p2, a) = pSum(rot(pDiff(p1, p2), a), p2); // rotate p1 about p2 383 | 384 | """ 385 | 386 | filename = "BezierScad.scad" 387 | require('fs').writeFile "./#{filename}", bezScad 388 | 389 | bezTest = """ 390 | use <#{filename}>; 391 | x = 25; 392 | 393 | """ + (for order in [2...orderMax] 394 | """ 395 | 396 | translate([#{30*(order-1.75)},0,0]) 397 | BezWall( [ 398 | [0,0], 399 | #{("[#{ 400 | switch 401 | when i is order/2 then "x/2" 402 | when i < order/2 then "0" 403 | else "x" 404 | }, x]" for i in [1...order]).join(", ")}, 405 | [x,0], 406 | ] , width = 1.5, height = 10, steps = #{order*2}, centered = true ); 407 | """ 408 | ).join('\n') + """ 409 | 410 | 411 | BezWall([ 412 | [-0.1,0], 413 | [-20, 0], 414 | [-25,25] 415 | ], widthCtls = [10, 1], 416 | heightCtls = [1, 5, 6, 35], 417 | steps = 32, 418 | centered = true 419 | ); 420 | translate([0,30,0]) 421 | BezWall([ 422 | [-0.1,0], 423 | [-15, 0], 424 | [-15, 25], 425 | [-25,25] 426 | ], 427 | width = 2, 428 | heightCtls = [1, 35, 1], 429 | steps = 16, 430 | centered = false 431 | ); 432 | 433 | translate([-30,30,0]) 434 | BezWall([ 435 | [-0.1,0], 436 | [-15, 0], 437 | [-15, 25], 438 | [-25,25] 439 | ], 440 | widthCtls = [2, 10], 441 | height = 5, 442 | steps = 16, 443 | centered = true 444 | ); 445 | 446 | linear_extrude(height = 5) 447 | BezLine([ 448 | [0,-10], [5, -20], [0,-30] 449 | ], width = [5, 10], resolution = 2, centered = true); 450 | 451 | linear_extrude(height = 5) 452 | BezLine([ 453 | [0,10], [5, 20], [0,30] 454 | ], width = [5, 10], resolution = 3, centered = false); 455 | 456 | translate([-10, -10,0]) 457 | BezArc([ 458 | [-10,-1], 459 | [-10, -10], 460 | [-1,-10] 461 | ], [-1,-1], steps = 16, heightCtls = [1,10]); 462 | """ 463 | 464 | require('fs').writeFile "./BezierTest.scad", bezTest 465 | 466 | 467 | ### 468 | bezScad += """ 469 | function BezArr(p, resolution = 4) = 470 | 471 | """ + ( 472 | for order in [1..orderMax] 473 | """ 474 | len(p) == #{order} ? BezArr#{order}(p, resolution) : 475 | """ 476 | ).join(' \n ') + '\n [];\n\n' 477 | 478 | for order in [1..orderMax] 479 | ps = ("p[#{i}]" for i in [0...order]).join ', ' 480 | bezScad += """ 481 | 482 | function BezArr#{order}(p, resolution) = 483 | 484 | """ + ( 485 | for res in [2..maxLineResolution] 486 | steps = Math.pow(2, res) 487 | arr = ("BezI#{order}(#{i}/#{(steps-1)}, #{ps})" for i in [0...steps]) 488 | """ 489 | resolution == #{res} ? [#{arr.join ', '}] : 490 | """ 491 | ).join(' \n ') + '\n [];\n' 492 | ### 493 | 494 | -------------------------------------------------------------------------------- /BezierScad.scad: -------------------------------------------------------------------------------- 1 | /* 2 | Bezier functions for OpenScad 3 | Generated from BezierScad.coffee from darwin at Fri May 10 2013 22:59:02 GMT-0700 (PDT) 4 | Supports Bezier interpolation with 1-8 controls 5 | Sources/Inspirations: 6 | http://en.wikipedia.org/wiki/Bézier_curve 7 | http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html 8 | http://www.thingiverse.com/thing:8443 9 | 10 | Copyright (c) 2013 Chad Kirby 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | THE SOFTWARE. 29 | */ 30 | 31 | 32 | module BezLine(ctlPts, width = [1], resolution = 4, centered = false, showCtls = true) { 33 | hodoPts = hodograph(ctlPts); 34 | if (showCtls) { 35 | for (pt = ctlPts) { 36 | % translate([pt[0], pt[1], 0]) circle(1); 37 | } 38 | } 39 | if (resolution == 2) { 40 | if (centered) { 41 | polygon([ 42 | PerpAlongBez(0/3, ctlPts, dist = BezI(0/3, width)/2, hodograph = hodoPts), PerpAlongBez(1/3, ctlPts, dist = BezI(1/3, width)/2, hodograph = hodoPts), PerpAlongBez(2/3, ctlPts, dist = BezI(2/3, width)/2, hodograph = hodoPts), PerpAlongBez(3/3, ctlPts, dist = BezI(3/3, width)/2, hodograph = hodoPts), PerpAlongBez(3/3, ctlPts, dist = BezI(3/3, width)/-2, hodograph = hodoPts), PerpAlongBez(2/3, ctlPts, dist = BezI(2/3, width)/-2, hodograph = hodoPts), PerpAlongBez(1/3, ctlPts, dist = BezI(1/3, width)/-2, hodograph = hodoPts), PerpAlongBez(0/3, ctlPts, dist = BezI(0/3, width)/-2, hodograph = hodoPts) 43 | ]); 44 | } else { 45 | polygon([ 46 | PointAlongBez(0/3, ctlPts), PointAlongBez(1/3, ctlPts), PointAlongBez(2/3, ctlPts), PointAlongBez(3/3, ctlPts), PerpAlongBez(3/3, ctlPts, dist = BezI(3/3, width), hodograph = hodoPts), PerpAlongBez(2/3, ctlPts, dist = BezI(2/3, width), hodograph = hodoPts), PerpAlongBez(1/3, ctlPts, dist = BezI(1/3, width), hodograph = hodoPts), PerpAlongBez(0/3, ctlPts, dist = BezI(0/3, width), hodograph = hodoPts) 47 | ]); 48 | } 49 | } else if (resolution == 3) { 50 | if (centered) { 51 | polygon([ 52 | PerpAlongBez(0/7, ctlPts, dist = BezI(0/7, width)/2, hodograph = hodoPts), PerpAlongBez(1/7, ctlPts, dist = BezI(1/7, width)/2, hodograph = hodoPts), PerpAlongBez(2/7, ctlPts, dist = BezI(2/7, width)/2, hodograph = hodoPts), PerpAlongBez(3/7, ctlPts, dist = BezI(3/7, width)/2, hodograph = hodoPts), PerpAlongBez(4/7, ctlPts, dist = BezI(4/7, width)/2, hodograph = hodoPts), PerpAlongBez(5/7, ctlPts, dist = BezI(5/7, width)/2, hodograph = hodoPts), PerpAlongBez(6/7, ctlPts, dist = BezI(6/7, width)/2, hodograph = hodoPts), PerpAlongBez(7/7, ctlPts, dist = BezI(7/7, width)/2, hodograph = hodoPts), PerpAlongBez(7/7, ctlPts, dist = BezI(7/7, width)/-2, hodograph = hodoPts), PerpAlongBez(6/7, ctlPts, dist = BezI(6/7, width)/-2, hodograph = hodoPts), PerpAlongBez(5/7, ctlPts, dist = BezI(5/7, width)/-2, hodograph = hodoPts), PerpAlongBez(4/7, ctlPts, dist = BezI(4/7, width)/-2, hodograph = hodoPts), PerpAlongBez(3/7, ctlPts, dist = BezI(3/7, width)/-2, hodograph = hodoPts), PerpAlongBez(2/7, ctlPts, dist = BezI(2/7, width)/-2, hodograph = hodoPts), PerpAlongBez(1/7, ctlPts, dist = BezI(1/7, width)/-2, hodograph = hodoPts), PerpAlongBez(0/7, ctlPts, dist = BezI(0/7, width)/-2, hodograph = hodoPts) 53 | ]); 54 | } else { 55 | polygon([ 56 | PointAlongBez(0/7, ctlPts), PointAlongBez(1/7, ctlPts), PointAlongBez(2/7, ctlPts), PointAlongBez(3/7, ctlPts), PointAlongBez(4/7, ctlPts), PointAlongBez(5/7, ctlPts), PointAlongBez(6/7, ctlPts), PointAlongBez(7/7, ctlPts), PerpAlongBez(7/7, ctlPts, dist = BezI(7/7, width), hodograph = hodoPts), PerpAlongBez(6/7, ctlPts, dist = BezI(6/7, width), hodograph = hodoPts), PerpAlongBez(5/7, ctlPts, dist = BezI(5/7, width), hodograph = hodoPts), PerpAlongBez(4/7, ctlPts, dist = BezI(4/7, width), hodograph = hodoPts), PerpAlongBez(3/7, ctlPts, dist = BezI(3/7, width), hodograph = hodoPts), PerpAlongBez(2/7, ctlPts, dist = BezI(2/7, width), hodograph = hodoPts), PerpAlongBez(1/7, ctlPts, dist = BezI(1/7, width), hodograph = hodoPts), PerpAlongBez(0/7, ctlPts, dist = BezI(0/7, width), hodograph = hodoPts) 57 | ]); 58 | } 59 | } else if (resolution == 4) { 60 | if (centered) { 61 | polygon([ 62 | PerpAlongBez(0/15, ctlPts, dist = BezI(0/15, width)/2, hodograph = hodoPts), PerpAlongBez(1/15, ctlPts, dist = BezI(1/15, width)/2, hodograph = hodoPts), PerpAlongBez(2/15, ctlPts, dist = BezI(2/15, width)/2, hodograph = hodoPts), PerpAlongBez(3/15, ctlPts, dist = BezI(3/15, width)/2, hodograph = hodoPts), PerpAlongBez(4/15, ctlPts, dist = BezI(4/15, width)/2, hodograph = hodoPts), PerpAlongBez(5/15, ctlPts, dist = BezI(5/15, width)/2, hodograph = hodoPts), PerpAlongBez(6/15, ctlPts, dist = BezI(6/15, width)/2, hodograph = hodoPts), PerpAlongBez(7/15, ctlPts, dist = BezI(7/15, width)/2, hodograph = hodoPts), PerpAlongBez(8/15, ctlPts, dist = BezI(8/15, width)/2, hodograph = hodoPts), PerpAlongBez(9/15, ctlPts, dist = BezI(9/15, width)/2, hodograph = hodoPts), PerpAlongBez(10/15, ctlPts, dist = BezI(10/15, width)/2, hodograph = hodoPts), PerpAlongBez(11/15, ctlPts, dist = BezI(11/15, width)/2, hodograph = hodoPts), PerpAlongBez(12/15, ctlPts, dist = BezI(12/15, width)/2, hodograph = hodoPts), PerpAlongBez(13/15, ctlPts, dist = BezI(13/15, width)/2, hodograph = hodoPts), PerpAlongBez(14/15, ctlPts, dist = BezI(14/15, width)/2, hodograph = hodoPts), PerpAlongBez(15/15, ctlPts, dist = BezI(15/15, width)/2, hodograph = hodoPts), PerpAlongBez(15/15, ctlPts, dist = BezI(15/15, width)/-2, hodograph = hodoPts), PerpAlongBez(14/15, ctlPts, dist = BezI(14/15, width)/-2, hodograph = hodoPts), PerpAlongBez(13/15, ctlPts, dist = BezI(13/15, width)/-2, hodograph = hodoPts), PerpAlongBez(12/15, ctlPts, dist = BezI(12/15, width)/-2, hodograph = hodoPts), PerpAlongBez(11/15, ctlPts, dist = BezI(11/15, width)/-2, hodograph = hodoPts), PerpAlongBez(10/15, ctlPts, dist = BezI(10/15, width)/-2, hodograph = hodoPts), PerpAlongBez(9/15, ctlPts, dist = BezI(9/15, width)/-2, hodograph = hodoPts), PerpAlongBez(8/15, ctlPts, dist = BezI(8/15, width)/-2, hodograph = hodoPts), PerpAlongBez(7/15, ctlPts, dist = BezI(7/15, width)/-2, hodograph = hodoPts), PerpAlongBez(6/15, ctlPts, dist = BezI(6/15, width)/-2, hodograph = hodoPts), PerpAlongBez(5/15, ctlPts, dist = BezI(5/15, width)/-2, hodograph = hodoPts), PerpAlongBez(4/15, ctlPts, dist = BezI(4/15, width)/-2, hodograph = hodoPts), PerpAlongBez(3/15, ctlPts, dist = BezI(3/15, width)/-2, hodograph = hodoPts), PerpAlongBez(2/15, ctlPts, dist = BezI(2/15, width)/-2, hodograph = hodoPts), PerpAlongBez(1/15, ctlPts, dist = BezI(1/15, width)/-2, hodograph = hodoPts), PerpAlongBez(0/15, ctlPts, dist = BezI(0/15, width)/-2, hodograph = hodoPts) 63 | ]); 64 | } else { 65 | polygon([ 66 | PointAlongBez(0/15, ctlPts), PointAlongBez(1/15, ctlPts), PointAlongBez(2/15, ctlPts), PointAlongBez(3/15, ctlPts), PointAlongBez(4/15, ctlPts), PointAlongBez(5/15, ctlPts), PointAlongBez(6/15, ctlPts), PointAlongBez(7/15, ctlPts), PointAlongBez(8/15, ctlPts), PointAlongBez(9/15, ctlPts), PointAlongBez(10/15, ctlPts), PointAlongBez(11/15, ctlPts), PointAlongBez(12/15, ctlPts), PointAlongBez(13/15, ctlPts), PointAlongBez(14/15, ctlPts), PointAlongBez(15/15, ctlPts), PerpAlongBez(15/15, ctlPts, dist = BezI(15/15, width), hodograph = hodoPts), PerpAlongBez(14/15, ctlPts, dist = BezI(14/15, width), hodograph = hodoPts), PerpAlongBez(13/15, ctlPts, dist = BezI(13/15, width), hodograph = hodoPts), PerpAlongBez(12/15, ctlPts, dist = BezI(12/15, width), hodograph = hodoPts), PerpAlongBez(11/15, ctlPts, dist = BezI(11/15, width), hodograph = hodoPts), PerpAlongBez(10/15, ctlPts, dist = BezI(10/15, width), hodograph = hodoPts), PerpAlongBez(9/15, ctlPts, dist = BezI(9/15, width), hodograph = hodoPts), PerpAlongBez(8/15, ctlPts, dist = BezI(8/15, width), hodograph = hodoPts), PerpAlongBez(7/15, ctlPts, dist = BezI(7/15, width), hodograph = hodoPts), PerpAlongBez(6/15, ctlPts, dist = BezI(6/15, width), hodograph = hodoPts), PerpAlongBez(5/15, ctlPts, dist = BezI(5/15, width), hodograph = hodoPts), PerpAlongBez(4/15, ctlPts, dist = BezI(4/15, width), hodograph = hodoPts), PerpAlongBez(3/15, ctlPts, dist = BezI(3/15, width), hodograph = hodoPts), PerpAlongBez(2/15, ctlPts, dist = BezI(2/15, width), hodograph = hodoPts), PerpAlongBez(1/15, ctlPts, dist = BezI(1/15, width), hodograph = hodoPts), PerpAlongBez(0/15, ctlPts, dist = BezI(0/15, width), hodograph = hodoPts) 67 | ]); 68 | } 69 | } else if (resolution == 5) { 70 | if (centered) { 71 | polygon([ 72 | PerpAlongBez(0/31, ctlPts, dist = BezI(0/31, width)/2, hodograph = hodoPts), PerpAlongBez(1/31, ctlPts, dist = BezI(1/31, width)/2, hodograph = hodoPts), PerpAlongBez(2/31, ctlPts, dist = BezI(2/31, width)/2, hodograph = hodoPts), PerpAlongBez(3/31, ctlPts, dist = BezI(3/31, width)/2, hodograph = hodoPts), PerpAlongBez(4/31, ctlPts, dist = BezI(4/31, width)/2, hodograph = hodoPts), PerpAlongBez(5/31, ctlPts, dist = BezI(5/31, width)/2, hodograph = hodoPts), PerpAlongBez(6/31, ctlPts, dist = BezI(6/31, width)/2, hodograph = hodoPts), PerpAlongBez(7/31, ctlPts, dist = BezI(7/31, width)/2, hodograph = hodoPts), PerpAlongBez(8/31, ctlPts, dist = BezI(8/31, width)/2, hodograph = hodoPts), PerpAlongBez(9/31, ctlPts, dist = BezI(9/31, width)/2, hodograph = hodoPts), PerpAlongBez(10/31, ctlPts, dist = BezI(10/31, width)/2, hodograph = hodoPts), PerpAlongBez(11/31, ctlPts, dist = BezI(11/31, width)/2, hodograph = hodoPts), PerpAlongBez(12/31, ctlPts, dist = BezI(12/31, width)/2, hodograph = hodoPts), PerpAlongBez(13/31, ctlPts, dist = BezI(13/31, width)/2, hodograph = hodoPts), PerpAlongBez(14/31, ctlPts, dist = BezI(14/31, width)/2, hodograph = hodoPts), PerpAlongBez(15/31, ctlPts, dist = BezI(15/31, width)/2, hodograph = hodoPts), PerpAlongBez(16/31, ctlPts, dist = BezI(16/31, width)/2, hodograph = hodoPts), PerpAlongBez(17/31, ctlPts, dist = BezI(17/31, width)/2, hodograph = hodoPts), PerpAlongBez(18/31, ctlPts, dist = BezI(18/31, width)/2, hodograph = hodoPts), PerpAlongBez(19/31, ctlPts, dist = BezI(19/31, width)/2, hodograph = hodoPts), PerpAlongBez(20/31, ctlPts, dist = BezI(20/31, width)/2, hodograph = hodoPts), PerpAlongBez(21/31, ctlPts, dist = BezI(21/31, width)/2, hodograph = hodoPts), PerpAlongBez(22/31, ctlPts, dist = BezI(22/31, width)/2, hodograph = hodoPts), PerpAlongBez(23/31, ctlPts, dist = BezI(23/31, width)/2, hodograph = hodoPts), PerpAlongBez(24/31, ctlPts, dist = BezI(24/31, width)/2, hodograph = hodoPts), PerpAlongBez(25/31, ctlPts, dist = BezI(25/31, width)/2, hodograph = hodoPts), PerpAlongBez(26/31, ctlPts, dist = BezI(26/31, width)/2, hodograph = hodoPts), PerpAlongBez(27/31, ctlPts, dist = BezI(27/31, width)/2, hodograph = hodoPts), PerpAlongBez(28/31, ctlPts, dist = BezI(28/31, width)/2, hodograph = hodoPts), PerpAlongBez(29/31, ctlPts, dist = BezI(29/31, width)/2, hodograph = hodoPts), PerpAlongBez(30/31, ctlPts, dist = BezI(30/31, width)/2, hodograph = hodoPts), PerpAlongBez(31/31, ctlPts, dist = BezI(31/31, width)/2, hodograph = hodoPts), PerpAlongBez(31/31, ctlPts, dist = BezI(31/31, width)/-2, hodograph = hodoPts), PerpAlongBez(30/31, ctlPts, dist = BezI(30/31, width)/-2, hodograph = hodoPts), PerpAlongBez(29/31, ctlPts, dist = BezI(29/31, width)/-2, hodograph = hodoPts), PerpAlongBez(28/31, ctlPts, dist = BezI(28/31, width)/-2, hodograph = hodoPts), PerpAlongBez(27/31, ctlPts, dist = BezI(27/31, width)/-2, hodograph = hodoPts), PerpAlongBez(26/31, ctlPts, dist = BezI(26/31, width)/-2, hodograph = hodoPts), PerpAlongBez(25/31, ctlPts, dist = BezI(25/31, width)/-2, hodograph = hodoPts), PerpAlongBez(24/31, ctlPts, dist = BezI(24/31, width)/-2, hodograph = hodoPts), PerpAlongBez(23/31, ctlPts, dist = BezI(23/31, width)/-2, hodograph = hodoPts), PerpAlongBez(22/31, ctlPts, dist = BezI(22/31, width)/-2, hodograph = hodoPts), PerpAlongBez(21/31, ctlPts, dist = BezI(21/31, width)/-2, hodograph = hodoPts), PerpAlongBez(20/31, ctlPts, dist = BezI(20/31, width)/-2, hodograph = hodoPts), PerpAlongBez(19/31, ctlPts, dist = BezI(19/31, width)/-2, hodograph = hodoPts), PerpAlongBez(18/31, ctlPts, dist = BezI(18/31, width)/-2, hodograph = hodoPts), PerpAlongBez(17/31, ctlPts, dist = BezI(17/31, width)/-2, hodograph = hodoPts), PerpAlongBez(16/31, ctlPts, dist = BezI(16/31, width)/-2, hodograph = hodoPts), PerpAlongBez(15/31, ctlPts, dist = BezI(15/31, width)/-2, hodograph = hodoPts), PerpAlongBez(14/31, ctlPts, dist = BezI(14/31, width)/-2, hodograph = hodoPts), PerpAlongBez(13/31, ctlPts, dist = BezI(13/31, width)/-2, hodograph = hodoPts), PerpAlongBez(12/31, ctlPts, dist = BezI(12/31, width)/-2, hodograph = hodoPts), PerpAlongBez(11/31, ctlPts, dist = BezI(11/31, width)/-2, hodograph = hodoPts), PerpAlongBez(10/31, ctlPts, dist = BezI(10/31, width)/-2, hodograph = hodoPts), PerpAlongBez(9/31, ctlPts, dist = BezI(9/31, width)/-2, hodograph = hodoPts), PerpAlongBez(8/31, ctlPts, dist = BezI(8/31, width)/-2, hodograph = hodoPts), PerpAlongBez(7/31, ctlPts, dist = BezI(7/31, width)/-2, hodograph = hodoPts), PerpAlongBez(6/31, ctlPts, dist = BezI(6/31, width)/-2, hodograph = hodoPts), PerpAlongBez(5/31, ctlPts, dist = BezI(5/31, width)/-2, hodograph = hodoPts), PerpAlongBez(4/31, ctlPts, dist = BezI(4/31, width)/-2, hodograph = hodoPts), PerpAlongBez(3/31, ctlPts, dist = BezI(3/31, width)/-2, hodograph = hodoPts), PerpAlongBez(2/31, ctlPts, dist = BezI(2/31, width)/-2, hodograph = hodoPts), PerpAlongBez(1/31, ctlPts, dist = BezI(1/31, width)/-2, hodograph = hodoPts), PerpAlongBez(0/31, ctlPts, dist = BezI(0/31, width)/-2, hodograph = hodoPts) 73 | ]); 74 | } else { 75 | polygon([ 76 | PointAlongBez(0/31, ctlPts), PointAlongBez(1/31, ctlPts), PointAlongBez(2/31, ctlPts), PointAlongBez(3/31, ctlPts), PointAlongBez(4/31, ctlPts), PointAlongBez(5/31, ctlPts), PointAlongBez(6/31, ctlPts), PointAlongBez(7/31, ctlPts), PointAlongBez(8/31, ctlPts), PointAlongBez(9/31, ctlPts), PointAlongBez(10/31, ctlPts), PointAlongBez(11/31, ctlPts), PointAlongBez(12/31, ctlPts), PointAlongBez(13/31, ctlPts), PointAlongBez(14/31, ctlPts), PointAlongBez(15/31, ctlPts), PointAlongBez(16/31, ctlPts), PointAlongBez(17/31, ctlPts), PointAlongBez(18/31, ctlPts), PointAlongBez(19/31, ctlPts), PointAlongBez(20/31, ctlPts), PointAlongBez(21/31, ctlPts), PointAlongBez(22/31, ctlPts), PointAlongBez(23/31, ctlPts), PointAlongBez(24/31, ctlPts), PointAlongBez(25/31, ctlPts), PointAlongBez(26/31, ctlPts), PointAlongBez(27/31, ctlPts), PointAlongBez(28/31, ctlPts), PointAlongBez(29/31, ctlPts), PointAlongBez(30/31, ctlPts), PointAlongBez(31/31, ctlPts), PerpAlongBez(31/31, ctlPts, dist = BezI(31/31, width), hodograph = hodoPts), PerpAlongBez(30/31, ctlPts, dist = BezI(30/31, width), hodograph = hodoPts), PerpAlongBez(29/31, ctlPts, dist = BezI(29/31, width), hodograph = hodoPts), PerpAlongBez(28/31, ctlPts, dist = BezI(28/31, width), hodograph = hodoPts), PerpAlongBez(27/31, ctlPts, dist = BezI(27/31, width), hodograph = hodoPts), PerpAlongBez(26/31, ctlPts, dist = BezI(26/31, width), hodograph = hodoPts), PerpAlongBez(25/31, ctlPts, dist = BezI(25/31, width), hodograph = hodoPts), PerpAlongBez(24/31, ctlPts, dist = BezI(24/31, width), hodograph = hodoPts), PerpAlongBez(23/31, ctlPts, dist = BezI(23/31, width), hodograph = hodoPts), PerpAlongBez(22/31, ctlPts, dist = BezI(22/31, width), hodograph = hodoPts), PerpAlongBez(21/31, ctlPts, dist = BezI(21/31, width), hodograph = hodoPts), PerpAlongBez(20/31, ctlPts, dist = BezI(20/31, width), hodograph = hodoPts), PerpAlongBez(19/31, ctlPts, dist = BezI(19/31, width), hodograph = hodoPts), PerpAlongBez(18/31, ctlPts, dist = BezI(18/31, width), hodograph = hodoPts), PerpAlongBez(17/31, ctlPts, dist = BezI(17/31, width), hodograph = hodoPts), PerpAlongBez(16/31, ctlPts, dist = BezI(16/31, width), hodograph = hodoPts), PerpAlongBez(15/31, ctlPts, dist = BezI(15/31, width), hodograph = hodoPts), PerpAlongBez(14/31, ctlPts, dist = BezI(14/31, width), hodograph = hodoPts), PerpAlongBez(13/31, ctlPts, dist = BezI(13/31, width), hodograph = hodoPts), PerpAlongBez(12/31, ctlPts, dist = BezI(12/31, width), hodograph = hodoPts), PerpAlongBez(11/31, ctlPts, dist = BezI(11/31, width), hodograph = hodoPts), PerpAlongBez(10/31, ctlPts, dist = BezI(10/31, width), hodograph = hodoPts), PerpAlongBez(9/31, ctlPts, dist = BezI(9/31, width), hodograph = hodoPts), PerpAlongBez(8/31, ctlPts, dist = BezI(8/31, width), hodograph = hodoPts), PerpAlongBez(7/31, ctlPts, dist = BezI(7/31, width), hodograph = hodoPts), PerpAlongBez(6/31, ctlPts, dist = BezI(6/31, width), hodograph = hodoPts), PerpAlongBez(5/31, ctlPts, dist = BezI(5/31, width), hodograph = hodoPts), PerpAlongBez(4/31, ctlPts, dist = BezI(4/31, width), hodograph = hodoPts), PerpAlongBez(3/31, ctlPts, dist = BezI(3/31, width), hodograph = hodoPts), PerpAlongBez(2/31, ctlPts, dist = BezI(2/31, width), hodograph = hodoPts), PerpAlongBez(1/31, ctlPts, dist = BezI(1/31, width), hodograph = hodoPts), PerpAlongBez(0/31, ctlPts, dist = BezI(0/31, width), hodograph = hodoPts) 77 | ]); 78 | } 79 | } else if (resolution == 6) { 80 | if (centered) { 81 | polygon([ 82 | PerpAlongBez(0/63, ctlPts, dist = BezI(0/63, width)/2, hodograph = hodoPts), PerpAlongBez(1/63, ctlPts, dist = BezI(1/63, width)/2, hodograph = hodoPts), PerpAlongBez(2/63, ctlPts, dist = BezI(2/63, width)/2, hodograph = hodoPts), PerpAlongBez(3/63, ctlPts, dist = BezI(3/63, width)/2, hodograph = hodoPts), PerpAlongBez(4/63, ctlPts, dist = BezI(4/63, width)/2, hodograph = hodoPts), PerpAlongBez(5/63, ctlPts, dist = BezI(5/63, width)/2, hodograph = hodoPts), PerpAlongBez(6/63, ctlPts, dist = BezI(6/63, width)/2, hodograph = hodoPts), PerpAlongBez(7/63, ctlPts, dist = BezI(7/63, width)/2, hodograph = hodoPts), PerpAlongBez(8/63, ctlPts, dist = BezI(8/63, width)/2, hodograph = hodoPts), PerpAlongBez(9/63, ctlPts, dist = BezI(9/63, width)/2, hodograph = hodoPts), PerpAlongBez(10/63, ctlPts, dist = BezI(10/63, width)/2, hodograph = hodoPts), PerpAlongBez(11/63, ctlPts, dist = BezI(11/63, width)/2, hodograph = hodoPts), PerpAlongBez(12/63, ctlPts, dist = BezI(12/63, width)/2, hodograph = hodoPts), PerpAlongBez(13/63, ctlPts, dist = BezI(13/63, width)/2, hodograph = hodoPts), PerpAlongBez(14/63, ctlPts, dist = BezI(14/63, width)/2, hodograph = hodoPts), PerpAlongBez(15/63, ctlPts, dist = BezI(15/63, width)/2, hodograph = hodoPts), PerpAlongBez(16/63, ctlPts, dist = BezI(16/63, width)/2, hodograph = hodoPts), PerpAlongBez(17/63, ctlPts, dist = BezI(17/63, width)/2, hodograph = hodoPts), PerpAlongBez(18/63, ctlPts, dist = BezI(18/63, width)/2, hodograph = hodoPts), PerpAlongBez(19/63, ctlPts, dist = BezI(19/63, width)/2, hodograph = hodoPts), PerpAlongBez(20/63, ctlPts, dist = BezI(20/63, width)/2, hodograph = hodoPts), PerpAlongBez(21/63, ctlPts, dist = BezI(21/63, width)/2, hodograph = hodoPts), PerpAlongBez(22/63, ctlPts, dist = BezI(22/63, width)/2, hodograph = hodoPts), PerpAlongBez(23/63, ctlPts, dist = BezI(23/63, width)/2, hodograph = hodoPts), PerpAlongBez(24/63, ctlPts, dist = BezI(24/63, width)/2, hodograph = hodoPts), PerpAlongBez(25/63, ctlPts, dist = BezI(25/63, width)/2, hodograph = hodoPts), PerpAlongBez(26/63, ctlPts, dist = BezI(26/63, width)/2, hodograph = hodoPts), PerpAlongBez(27/63, ctlPts, dist = BezI(27/63, width)/2, hodograph = hodoPts), PerpAlongBez(28/63, ctlPts, dist = BezI(28/63, width)/2, hodograph = hodoPts), PerpAlongBez(29/63, ctlPts, dist = BezI(29/63, width)/2, hodograph = hodoPts), PerpAlongBez(30/63, ctlPts, dist = BezI(30/63, width)/2, hodograph = hodoPts), PerpAlongBez(31/63, ctlPts, dist = BezI(31/63, width)/2, hodograph = hodoPts), PerpAlongBez(32/63, ctlPts, dist = BezI(32/63, width)/2, hodograph = hodoPts), PerpAlongBez(33/63, ctlPts, dist = BezI(33/63, width)/2, hodograph = hodoPts), PerpAlongBez(34/63, ctlPts, dist = BezI(34/63, width)/2, hodograph = hodoPts), PerpAlongBez(35/63, ctlPts, dist = BezI(35/63, width)/2, hodograph = hodoPts), PerpAlongBez(36/63, ctlPts, dist = BezI(36/63, width)/2, hodograph = hodoPts), PerpAlongBez(37/63, ctlPts, dist = BezI(37/63, width)/2, hodograph = hodoPts), PerpAlongBez(38/63, ctlPts, dist = BezI(38/63, width)/2, hodograph = hodoPts), PerpAlongBez(39/63, ctlPts, dist = BezI(39/63, width)/2, hodograph = hodoPts), PerpAlongBez(40/63, ctlPts, dist = BezI(40/63, width)/2, hodograph = hodoPts), PerpAlongBez(41/63, ctlPts, dist = BezI(41/63, width)/2, hodograph = hodoPts), PerpAlongBez(42/63, ctlPts, dist = BezI(42/63, width)/2, hodograph = hodoPts), PerpAlongBez(43/63, ctlPts, dist = BezI(43/63, width)/2, hodograph = hodoPts), PerpAlongBez(44/63, ctlPts, dist = BezI(44/63, width)/2, hodograph = hodoPts), PerpAlongBez(45/63, ctlPts, dist = BezI(45/63, width)/2, hodograph = hodoPts), PerpAlongBez(46/63, ctlPts, dist = BezI(46/63, width)/2, hodograph = hodoPts), PerpAlongBez(47/63, ctlPts, dist = BezI(47/63, width)/2, hodograph = hodoPts), PerpAlongBez(48/63, ctlPts, dist = BezI(48/63, width)/2, hodograph = hodoPts), PerpAlongBez(49/63, ctlPts, dist = BezI(49/63, width)/2, hodograph = hodoPts), PerpAlongBez(50/63, ctlPts, dist = BezI(50/63, width)/2, hodograph = hodoPts), PerpAlongBez(51/63, ctlPts, dist = BezI(51/63, width)/2, hodograph = hodoPts), PerpAlongBez(52/63, ctlPts, dist = BezI(52/63, width)/2, hodograph = hodoPts), PerpAlongBez(53/63, ctlPts, dist = BezI(53/63, width)/2, hodograph = hodoPts), PerpAlongBez(54/63, ctlPts, dist = BezI(54/63, width)/2, hodograph = hodoPts), PerpAlongBez(55/63, ctlPts, dist = BezI(55/63, width)/2, hodograph = hodoPts), PerpAlongBez(56/63, ctlPts, dist = BezI(56/63, width)/2, hodograph = hodoPts), PerpAlongBez(57/63, ctlPts, dist = BezI(57/63, width)/2, hodograph = hodoPts), PerpAlongBez(58/63, ctlPts, dist = BezI(58/63, width)/2, hodograph = hodoPts), PerpAlongBez(59/63, ctlPts, dist = BezI(59/63, width)/2, hodograph = hodoPts), PerpAlongBez(60/63, ctlPts, dist = BezI(60/63, width)/2, hodograph = hodoPts), PerpAlongBez(61/63, ctlPts, dist = BezI(61/63, width)/2, hodograph = hodoPts), PerpAlongBez(62/63, ctlPts, dist = BezI(62/63, width)/2, hodograph = hodoPts), PerpAlongBez(63/63, ctlPts, dist = BezI(63/63, width)/2, hodograph = hodoPts), PerpAlongBez(63/63, ctlPts, dist = BezI(63/63, width)/-2, hodograph = hodoPts), PerpAlongBez(62/63, ctlPts, dist = BezI(62/63, width)/-2, hodograph = hodoPts), PerpAlongBez(61/63, ctlPts, dist = BezI(61/63, width)/-2, hodograph = hodoPts), PerpAlongBez(60/63, ctlPts, dist = BezI(60/63, width)/-2, hodograph = hodoPts), PerpAlongBez(59/63, ctlPts, dist = BezI(59/63, width)/-2, hodograph = hodoPts), PerpAlongBez(58/63, ctlPts, dist = BezI(58/63, width)/-2, hodograph = hodoPts), PerpAlongBez(57/63, ctlPts, dist = BezI(57/63, width)/-2, hodograph = hodoPts), PerpAlongBez(56/63, ctlPts, dist = BezI(56/63, width)/-2, hodograph = hodoPts), PerpAlongBez(55/63, ctlPts, dist = BezI(55/63, width)/-2, hodograph = hodoPts), PerpAlongBez(54/63, ctlPts, dist = BezI(54/63, width)/-2, hodograph = hodoPts), PerpAlongBez(53/63, ctlPts, dist = BezI(53/63, width)/-2, hodograph = hodoPts), PerpAlongBez(52/63, ctlPts, dist = BezI(52/63, width)/-2, hodograph = hodoPts), PerpAlongBez(51/63, ctlPts, dist = BezI(51/63, width)/-2, hodograph = hodoPts), PerpAlongBez(50/63, ctlPts, dist = BezI(50/63, width)/-2, hodograph = hodoPts), PerpAlongBez(49/63, ctlPts, dist = BezI(49/63, width)/-2, hodograph = hodoPts), PerpAlongBez(48/63, ctlPts, dist = BezI(48/63, width)/-2, hodograph = hodoPts), PerpAlongBez(47/63, ctlPts, dist = BezI(47/63, width)/-2, hodograph = hodoPts), PerpAlongBez(46/63, ctlPts, dist = BezI(46/63, width)/-2, hodograph = hodoPts), PerpAlongBez(45/63, ctlPts, dist = BezI(45/63, width)/-2, hodograph = hodoPts), PerpAlongBez(44/63, ctlPts, dist = BezI(44/63, width)/-2, hodograph = hodoPts), PerpAlongBez(43/63, ctlPts, dist = BezI(43/63, width)/-2, hodograph = hodoPts), PerpAlongBez(42/63, ctlPts, dist = BezI(42/63, width)/-2, hodograph = hodoPts), PerpAlongBez(41/63, ctlPts, dist = BezI(41/63, width)/-2, hodograph = hodoPts), PerpAlongBez(40/63, ctlPts, dist = BezI(40/63, width)/-2, hodograph = hodoPts), PerpAlongBez(39/63, ctlPts, dist = BezI(39/63, width)/-2, hodograph = hodoPts), PerpAlongBez(38/63, ctlPts, dist = BezI(38/63, width)/-2, hodograph = hodoPts), PerpAlongBez(37/63, ctlPts, dist = BezI(37/63, width)/-2, hodograph = hodoPts), PerpAlongBez(36/63, ctlPts, dist = BezI(36/63, width)/-2, hodograph = hodoPts), PerpAlongBez(35/63, ctlPts, dist = BezI(35/63, width)/-2, hodograph = hodoPts), PerpAlongBez(34/63, ctlPts, dist = BezI(34/63, width)/-2, hodograph = hodoPts), PerpAlongBez(33/63, ctlPts, dist = BezI(33/63, width)/-2, hodograph = hodoPts), PerpAlongBez(32/63, ctlPts, dist = BezI(32/63, width)/-2, hodograph = hodoPts), PerpAlongBez(31/63, ctlPts, dist = BezI(31/63, width)/-2, hodograph = hodoPts), PerpAlongBez(30/63, ctlPts, dist = BezI(30/63, width)/-2, hodograph = hodoPts), PerpAlongBez(29/63, ctlPts, dist = BezI(29/63, width)/-2, hodograph = hodoPts), PerpAlongBez(28/63, ctlPts, dist = BezI(28/63, width)/-2, hodograph = hodoPts), PerpAlongBez(27/63, ctlPts, dist = BezI(27/63, width)/-2, hodograph = hodoPts), PerpAlongBez(26/63, ctlPts, dist = BezI(26/63, width)/-2, hodograph = hodoPts), PerpAlongBez(25/63, ctlPts, dist = BezI(25/63, width)/-2, hodograph = hodoPts), PerpAlongBez(24/63, ctlPts, dist = BezI(24/63, width)/-2, hodograph = hodoPts), PerpAlongBez(23/63, ctlPts, dist = BezI(23/63, width)/-2, hodograph = hodoPts), PerpAlongBez(22/63, ctlPts, dist = BezI(22/63, width)/-2, hodograph = hodoPts), PerpAlongBez(21/63, ctlPts, dist = BezI(21/63, width)/-2, hodograph = hodoPts), PerpAlongBez(20/63, ctlPts, dist = BezI(20/63, width)/-2, hodograph = hodoPts), PerpAlongBez(19/63, ctlPts, dist = BezI(19/63, width)/-2, hodograph = hodoPts), PerpAlongBez(18/63, ctlPts, dist = BezI(18/63, width)/-2, hodograph = hodoPts), PerpAlongBez(17/63, ctlPts, dist = BezI(17/63, width)/-2, hodograph = hodoPts), PerpAlongBez(16/63, ctlPts, dist = BezI(16/63, width)/-2, hodograph = hodoPts), PerpAlongBez(15/63, ctlPts, dist = BezI(15/63, width)/-2, hodograph = hodoPts), PerpAlongBez(14/63, ctlPts, dist = BezI(14/63, width)/-2, hodograph = hodoPts), PerpAlongBez(13/63, ctlPts, dist = BezI(13/63, width)/-2, hodograph = hodoPts), PerpAlongBez(12/63, ctlPts, dist = BezI(12/63, width)/-2, hodograph = hodoPts), PerpAlongBez(11/63, ctlPts, dist = BezI(11/63, width)/-2, hodograph = hodoPts), PerpAlongBez(10/63, ctlPts, dist = BezI(10/63, width)/-2, hodograph = hodoPts), PerpAlongBez(9/63, ctlPts, dist = BezI(9/63, width)/-2, hodograph = hodoPts), PerpAlongBez(8/63, ctlPts, dist = BezI(8/63, width)/-2, hodograph = hodoPts), PerpAlongBez(7/63, ctlPts, dist = BezI(7/63, width)/-2, hodograph = hodoPts), PerpAlongBez(6/63, ctlPts, dist = BezI(6/63, width)/-2, hodograph = hodoPts), PerpAlongBez(5/63, ctlPts, dist = BezI(5/63, width)/-2, hodograph = hodoPts), PerpAlongBez(4/63, ctlPts, dist = BezI(4/63, width)/-2, hodograph = hodoPts), PerpAlongBez(3/63, ctlPts, dist = BezI(3/63, width)/-2, hodograph = hodoPts), PerpAlongBez(2/63, ctlPts, dist = BezI(2/63, width)/-2, hodograph = hodoPts), PerpAlongBez(1/63, ctlPts, dist = BezI(1/63, width)/-2, hodograph = hodoPts), PerpAlongBez(0/63, ctlPts, dist = BezI(0/63, width)/-2, hodograph = hodoPts) 83 | ]); 84 | } else { 85 | polygon([ 86 | PointAlongBez(0/63, ctlPts), PointAlongBez(1/63, ctlPts), PointAlongBez(2/63, ctlPts), PointAlongBez(3/63, ctlPts), PointAlongBez(4/63, ctlPts), PointAlongBez(5/63, ctlPts), PointAlongBez(6/63, ctlPts), PointAlongBez(7/63, ctlPts), PointAlongBez(8/63, ctlPts), PointAlongBez(9/63, ctlPts), PointAlongBez(10/63, ctlPts), PointAlongBez(11/63, ctlPts), PointAlongBez(12/63, ctlPts), PointAlongBez(13/63, ctlPts), PointAlongBez(14/63, ctlPts), PointAlongBez(15/63, ctlPts), PointAlongBez(16/63, ctlPts), PointAlongBez(17/63, ctlPts), PointAlongBez(18/63, ctlPts), PointAlongBez(19/63, ctlPts), PointAlongBez(20/63, ctlPts), PointAlongBez(21/63, ctlPts), PointAlongBez(22/63, ctlPts), PointAlongBez(23/63, ctlPts), PointAlongBez(24/63, ctlPts), PointAlongBez(25/63, ctlPts), PointAlongBez(26/63, ctlPts), PointAlongBez(27/63, ctlPts), PointAlongBez(28/63, ctlPts), PointAlongBez(29/63, ctlPts), PointAlongBez(30/63, ctlPts), PointAlongBez(31/63, ctlPts), PointAlongBez(32/63, ctlPts), PointAlongBez(33/63, ctlPts), PointAlongBez(34/63, ctlPts), PointAlongBez(35/63, ctlPts), PointAlongBez(36/63, ctlPts), PointAlongBez(37/63, ctlPts), PointAlongBez(38/63, ctlPts), PointAlongBez(39/63, ctlPts), PointAlongBez(40/63, ctlPts), PointAlongBez(41/63, ctlPts), PointAlongBez(42/63, ctlPts), PointAlongBez(43/63, ctlPts), PointAlongBez(44/63, ctlPts), PointAlongBez(45/63, ctlPts), PointAlongBez(46/63, ctlPts), PointAlongBez(47/63, ctlPts), PointAlongBez(48/63, ctlPts), PointAlongBez(49/63, ctlPts), PointAlongBez(50/63, ctlPts), PointAlongBez(51/63, ctlPts), PointAlongBez(52/63, ctlPts), PointAlongBez(53/63, ctlPts), PointAlongBez(54/63, ctlPts), PointAlongBez(55/63, ctlPts), PointAlongBez(56/63, ctlPts), PointAlongBez(57/63, ctlPts), PointAlongBez(58/63, ctlPts), PointAlongBez(59/63, ctlPts), PointAlongBez(60/63, ctlPts), PointAlongBez(61/63, ctlPts), PointAlongBez(62/63, ctlPts), PointAlongBez(63/63, ctlPts), PerpAlongBez(63/63, ctlPts, dist = BezI(63/63, width), hodograph = hodoPts), PerpAlongBez(62/63, ctlPts, dist = BezI(62/63, width), hodograph = hodoPts), PerpAlongBez(61/63, ctlPts, dist = BezI(61/63, width), hodograph = hodoPts), PerpAlongBez(60/63, ctlPts, dist = BezI(60/63, width), hodograph = hodoPts), PerpAlongBez(59/63, ctlPts, dist = BezI(59/63, width), hodograph = hodoPts), PerpAlongBez(58/63, ctlPts, dist = BezI(58/63, width), hodograph = hodoPts), PerpAlongBez(57/63, ctlPts, dist = BezI(57/63, width), hodograph = hodoPts), PerpAlongBez(56/63, ctlPts, dist = BezI(56/63, width), hodograph = hodoPts), PerpAlongBez(55/63, ctlPts, dist = BezI(55/63, width), hodograph = hodoPts), PerpAlongBez(54/63, ctlPts, dist = BezI(54/63, width), hodograph = hodoPts), PerpAlongBez(53/63, ctlPts, dist = BezI(53/63, width), hodograph = hodoPts), PerpAlongBez(52/63, ctlPts, dist = BezI(52/63, width), hodograph = hodoPts), PerpAlongBez(51/63, ctlPts, dist = BezI(51/63, width), hodograph = hodoPts), PerpAlongBez(50/63, ctlPts, dist = BezI(50/63, width), hodograph = hodoPts), PerpAlongBez(49/63, ctlPts, dist = BezI(49/63, width), hodograph = hodoPts), PerpAlongBez(48/63, ctlPts, dist = BezI(48/63, width), hodograph = hodoPts), PerpAlongBez(47/63, ctlPts, dist = BezI(47/63, width), hodograph = hodoPts), PerpAlongBez(46/63, ctlPts, dist = BezI(46/63, width), hodograph = hodoPts), PerpAlongBez(45/63, ctlPts, dist = BezI(45/63, width), hodograph = hodoPts), PerpAlongBez(44/63, ctlPts, dist = BezI(44/63, width), hodograph = hodoPts), PerpAlongBez(43/63, ctlPts, dist = BezI(43/63, width), hodograph = hodoPts), PerpAlongBez(42/63, ctlPts, dist = BezI(42/63, width), hodograph = hodoPts), PerpAlongBez(41/63, ctlPts, dist = BezI(41/63, width), hodograph = hodoPts), PerpAlongBez(40/63, ctlPts, dist = BezI(40/63, width), hodograph = hodoPts), PerpAlongBez(39/63, ctlPts, dist = BezI(39/63, width), hodograph = hodoPts), PerpAlongBez(38/63, ctlPts, dist = BezI(38/63, width), hodograph = hodoPts), PerpAlongBez(37/63, ctlPts, dist = BezI(37/63, width), hodograph = hodoPts), PerpAlongBez(36/63, ctlPts, dist = BezI(36/63, width), hodograph = hodoPts), PerpAlongBez(35/63, ctlPts, dist = BezI(35/63, width), hodograph = hodoPts), PerpAlongBez(34/63, ctlPts, dist = BezI(34/63, width), hodograph = hodoPts), PerpAlongBez(33/63, ctlPts, dist = BezI(33/63, width), hodograph = hodoPts), PerpAlongBez(32/63, ctlPts, dist = BezI(32/63, width), hodograph = hodoPts), PerpAlongBez(31/63, ctlPts, dist = BezI(31/63, width), hodograph = hodoPts), PerpAlongBez(30/63, ctlPts, dist = BezI(30/63, width), hodograph = hodoPts), PerpAlongBez(29/63, ctlPts, dist = BezI(29/63, width), hodograph = hodoPts), PerpAlongBez(28/63, ctlPts, dist = BezI(28/63, width), hodograph = hodoPts), PerpAlongBez(27/63, ctlPts, dist = BezI(27/63, width), hodograph = hodoPts), PerpAlongBez(26/63, ctlPts, dist = BezI(26/63, width), hodograph = hodoPts), PerpAlongBez(25/63, ctlPts, dist = BezI(25/63, width), hodograph = hodoPts), PerpAlongBez(24/63, ctlPts, dist = BezI(24/63, width), hodograph = hodoPts), PerpAlongBez(23/63, ctlPts, dist = BezI(23/63, width), hodograph = hodoPts), PerpAlongBez(22/63, ctlPts, dist = BezI(22/63, width), hodograph = hodoPts), PerpAlongBez(21/63, ctlPts, dist = BezI(21/63, width), hodograph = hodoPts), PerpAlongBez(20/63, ctlPts, dist = BezI(20/63, width), hodograph = hodoPts), PerpAlongBez(19/63, ctlPts, dist = BezI(19/63, width), hodograph = hodoPts), PerpAlongBez(18/63, ctlPts, dist = BezI(18/63, width), hodograph = hodoPts), PerpAlongBez(17/63, ctlPts, dist = BezI(17/63, width), hodograph = hodoPts), PerpAlongBez(16/63, ctlPts, dist = BezI(16/63, width), hodograph = hodoPts), PerpAlongBez(15/63, ctlPts, dist = BezI(15/63, width), hodograph = hodoPts), PerpAlongBez(14/63, ctlPts, dist = BezI(14/63, width), hodograph = hodoPts), PerpAlongBez(13/63, ctlPts, dist = BezI(13/63, width), hodograph = hodoPts), PerpAlongBez(12/63, ctlPts, dist = BezI(12/63, width), hodograph = hodoPts), PerpAlongBez(11/63, ctlPts, dist = BezI(11/63, width), hodograph = hodoPts), PerpAlongBez(10/63, ctlPts, dist = BezI(10/63, width), hodograph = hodoPts), PerpAlongBez(9/63, ctlPts, dist = BezI(9/63, width), hodograph = hodoPts), PerpAlongBez(8/63, ctlPts, dist = BezI(8/63, width), hodograph = hodoPts), PerpAlongBez(7/63, ctlPts, dist = BezI(7/63, width), hodograph = hodoPts), PerpAlongBez(6/63, ctlPts, dist = BezI(6/63, width), hodograph = hodoPts), PerpAlongBez(5/63, ctlPts, dist = BezI(5/63, width), hodograph = hodoPts), PerpAlongBez(4/63, ctlPts, dist = BezI(4/63, width), hodograph = hodoPts), PerpAlongBez(3/63, ctlPts, dist = BezI(3/63, width), hodograph = hodoPts), PerpAlongBez(2/63, ctlPts, dist = BezI(2/63, width), hodograph = hodoPts), PerpAlongBez(1/63, ctlPts, dist = BezI(1/63, width), hodograph = hodoPts), PerpAlongBez(0/63, ctlPts, dist = BezI(0/63, width), hodograph = hodoPts) 87 | ]); 88 | } 89 | } 90 | } 91 | module BezWall( 92 | ctlPts, 93 | width = 1, 94 | height = 1, 95 | steps = 16, 96 | widthCtls = [], 97 | heightCtls = [], 98 | centered = false, 99 | showCtlR = 1 100 | ) { 101 | hodoPts = hodograph(ctlPts); 102 | if (showCtlR > 0) { 103 | for (pt = ctlPts) { 104 | % translate([pt[0], pt[1], 0]) circle(showCtlR); 105 | } 106 | } 107 | triangles = [ 108 | [0,2,1], 109 | [0,3,2], 110 | [0,4,5], 111 | [0,1,4], 112 | [0,6,3], 113 | [0,5,6], 114 | [4,6,5], 115 | [4,7,6], 116 | [1,2,7], 117 | [1,7,4], 118 | [2,3,6], 119 | [2,6,7] 120 | ]; 121 | for(step = [steps-1 : 1]) 122 | { 123 | assign( 124 | t1 = step/(steps-1), 125 | t0 = (step-1)/(steps-1) 126 | ) { 127 | assign( 128 | hgt0 = len(heightCtls) > 0 ? BezI(t0, heightCtls) : height, 129 | hgt1 = len(heightCtls) > 0 ? BezI(t1, heightCtls) : height, 130 | wid0 = len(widthCtls) > 0 ? BezI(t0, widthCtls) : width, 131 | wid1 = len(widthCtls) > 0 ? BezI(t1, widthCtls) : width 132 | ) { 133 | if (centered) { 134 | assign( 135 | p0 = PerpAlongBez(t0, ctlPts, dist = -wid0/2, hodograph = hodoPts), 136 | p1 = PerpAlongBez(t0, ctlPts, dist = wid0/2, hodograph = hodoPts), 137 | p4 = PerpAlongBez(t1, ctlPts, dist = wid1/2, hodograph = hodoPts), 138 | p5 = PerpAlongBez(t1, ctlPts, dist = -wid1/2, hodograph = hodoPts) 139 | ) { 140 | if (hgt0 == 0 && hgt1 == 0 ) { 141 | polygon([ p5, p0, p1, p4 ]); 142 | } else if (hgt0 == hgt1) { 143 | linear_extrude(height = hgt0, convexity = 2) polygon([ p5, p0, p1, p4 ]); 144 | } else { 145 | polyhedron( 146 | points =[ 147 | [p0[0],p0[1],0], // 0 148 | [p1[0],p1[1],0], // 1 149 | [p1[0],p1[1],hgt0], // 2 150 | [p0[0],p0[1],hgt0], // 3 151 | [p4[0],p4[1],0], // 4 152 | [p5[0],p5[1],0], // 5 153 | [p5[0],p5[1],hgt1], // 6 154 | [p4[0],p4[1],hgt1], // 7 155 | ], 156 | triangles = triangles, 157 | convexity = 2 158 | ); 159 | } 160 | } 161 | } else { 162 | assign( 163 | p0 = PointAlongBez(t0, ctlPts), 164 | p1 = PerpAlongBez(t0, ctlPts, dist = wid0, hodograph = hodoPts), 165 | p4 = PerpAlongBez(t1, ctlPts, dist = wid1, hodograph = hodoPts), 166 | p5 = PointAlongBez(t1, ctlPts) 167 | ) { 168 | if (hgt0 == 0 && hgt1 == 0 ) { 169 | polygon([ p5, p0, p1, p4 ]); 170 | } else if (hgt0 == hgt1) { 171 | linear_extrude(height = hgt0, convexity = 2) polygon([ p5, p0, p1, p4 ]); 172 | } else { 173 | polyhedron( 174 | points =[ 175 | [p0[0],p0[1],0], // 0 176 | [p1[0],p1[1],0], // 1 177 | [p1[0],p1[1],hgt0], // 2 178 | [p0[0],p0[1],hgt0], // 3 179 | [p4[0],p4[1],0], // 4 180 | [p5[0],p5[1],0], // 5 181 | [p5[0],p5[1],hgt1], // 6 182 | [p4[0],p4[1],hgt1], // 7 183 | ], 184 | triangles = triangles, 185 | convexity = 2 186 | ); 187 | } 188 | } 189 | } 190 | } } 191 | } 192 | } 193 | 194 | module BezArc(ctlPts, focalPoint, steps=12, height = 1, heightCtls = [], showCtlR = 1) 195 | { 196 | if (showCtlR > 0) { 197 | for (pt = ctlPts) { 198 | % translate([pt[0], pt[1], 0]) circle(showCtlR); 199 | } 200 | } 201 | triangles = [ 202 | [0,2,1], 203 | [3,4,5], 204 | [1,5,4], 205 | [2,5,1], 206 | [0,1,4], 207 | [0,4,3], 208 | [0,5,2], 209 | [0,3,5], 210 | ]; 211 | for(step = [1 : steps-1]) 212 | { 213 | assign( 214 | t1 = step/(steps-1), 215 | t0 = (step-1)/(steps-1), 216 | fp = [focalPoint[0], focalPoint[1], len(heightCtls) > 0 ? BezI(0, heightCtls) : height] 217 | ) { 218 | assign( 219 | hgt0 = len(heightCtls) > 0 ? BezI(t0, heightCtls) : height, 220 | hgt1 = len(heightCtls) > 0 ? BezI(t1, heightCtls) : height, 221 | p0 = PointAlongBez(t0, ctlPts), 222 | p1 = PointAlongBez(t1, ctlPts) 223 | ) { 224 | if (hgt0 == 0 && hgt1 == 0 ) { 225 | // polygon([ focalPoint, p0, p1, [focalPoint[0], p1[1]] ]); // makes a solid in 2014.01.14, but won't render in OpenSCAD version 2014.05.17 226 | polygon([ focalPoint, p0, p1 ]); // won't render in OpenSCAD 2014.01.14; will render in 2015.02.20 227 | } else if (hgt0 == hgt1 || false) { 228 | linear_extrude(height = hgt0, convexity = 2) polygon([ focalPoint, p0, p1 ]); 229 | } else { 230 | polyhedron( // not manifold 231 | points = [ 232 | [focalPoint[0], focalPoint[1], 0], // 0 233 | [p1[0], p1[1], 0], // 1 234 | [p0[0], p0[1], 0], // 2 235 | [focalPoint[0], focalPoint[1], hgt0], // 3 236 | [p1[0], p1[1], hgt1], // 4 237 | [p0[0], p0[1], hgt0], // 5 238 | [focalPoint[0], focalPoint[1], hgt1], // 6 239 | ], 240 | triangles = triangles, 241 | convexity = 2 242 | ); 243 | } 244 | } } 245 | } 246 | } 247 | function PointAlongBez(t, ctlPts) = 248 | len(ctlPts) == 1 ? PointAlongBez1(t, ctlPts) : 249 | len(ctlPts) == 2 ? PointAlongBez2(t, ctlPts) : 250 | len(ctlPts) == 3 ? PointAlongBez3(t, ctlPts) : 251 | len(ctlPts) == 4 ? PointAlongBez4(t, ctlPts) : 252 | len(ctlPts) == 5 ? PointAlongBez5(t, ctlPts) : 253 | len(ctlPts) == 6 ? PointAlongBez6(t, ctlPts) : 254 | len(ctlPts) == 7 ? PointAlongBez7(t, ctlPts) : 255 | len(ctlPts) == 8 ? PointAlongBez8(t, ctlPts) : 256 | []; 257 | 258 | function BezI(t, ctls) = 259 | len(ctls) == 1 ? BezI1(t, ctls) : 260 | len(ctls) == 2 ? BezI2(t, ctls) : 261 | len(ctls) == 3 ? BezI3(t, ctls) : 262 | len(ctls) == 4 ? BezI4(t, ctls) : 263 | len(ctls) == 5 ? BezI5(t, ctls) : 264 | len(ctls) == 6 ? BezI6(t, ctls) : 265 | len(ctls) == 7 ? BezI7(t, ctls) : 266 | len(ctls) == 8 ? BezI8(t, ctls) : 267 | []; 268 | 269 | function PointAlongBez1(t, ctlPts) = [ 270 | BezI1(t, [ctlPts[0][0]]), 271 | BezI1(t, [ctlPts[0][1]]) 272 | ]; 273 | function PointAlongBez2(t, ctlPts) = [ 274 | BezI2(t, [ctlPts[0][0], ctlPts[1][0]]), 275 | BezI2(t, [ctlPts[0][1], ctlPts[1][1]]) 276 | ]; 277 | function PointAlongBez3(t, ctlPts) = [ 278 | BezI3(t, [ctlPts[0][0], ctlPts[1][0], ctlPts[2][0]]), 279 | BezI3(t, [ctlPts[0][1], ctlPts[1][1], ctlPts[2][1]]) 280 | ]; 281 | function PointAlongBez4(t, ctlPts) = [ 282 | BezI4(t, [ctlPts[0][0], ctlPts[1][0], ctlPts[2][0], ctlPts[3][0]]), 283 | BezI4(t, [ctlPts[0][1], ctlPts[1][1], ctlPts[2][1], ctlPts[3][1]]) 284 | ]; 285 | function PointAlongBez5(t, ctlPts) = [ 286 | BezI5(t, [ctlPts[0][0], ctlPts[1][0], ctlPts[2][0], ctlPts[3][0], ctlPts[4][0]]), 287 | BezI5(t, [ctlPts[0][1], ctlPts[1][1], ctlPts[2][1], ctlPts[3][1], ctlPts[4][1]]) 288 | ]; 289 | function PointAlongBez6(t, ctlPts) = [ 290 | BezI6(t, [ctlPts[0][0], ctlPts[1][0], ctlPts[2][0], ctlPts[3][0], ctlPts[4][0], ctlPts[5][0]]), 291 | BezI6(t, [ctlPts[0][1], ctlPts[1][1], ctlPts[2][1], ctlPts[3][1], ctlPts[4][1], ctlPts[5][1]]) 292 | ]; 293 | function PointAlongBez7(t, ctlPts) = [ 294 | BezI7(t, [ctlPts[0][0], ctlPts[1][0], ctlPts[2][0], ctlPts[3][0], ctlPts[4][0], ctlPts[5][0], ctlPts[6][0]]), 295 | BezI7(t, [ctlPts[0][1], ctlPts[1][1], ctlPts[2][1], ctlPts[3][1], ctlPts[4][1], ctlPts[5][1], ctlPts[6][1]]) 296 | ]; 297 | function PointAlongBez8(t, ctlPts) = [ 298 | BezI8(t, [ctlPts[0][0], ctlPts[1][0], ctlPts[2][0], ctlPts[3][0], ctlPts[4][0], ctlPts[5][0], ctlPts[6][0], ctlPts[7][0]]), 299 | BezI8(t, [ctlPts[0][1], ctlPts[1][1], ctlPts[2][1], ctlPts[3][1], ctlPts[4][1], ctlPts[5][1], ctlPts[6][1], ctlPts[7][1]]) 300 | ]; 301 | 302 | function PerpAlongBez(t, ctlPts, dist = 1, hodograph = []) = 303 | len(ctlPts) == 2 ? PerpAlongBez2(t, ctlPts, dist, hodograph) : 304 | len(ctlPts) == 3 ? PerpAlongBez3(t, ctlPts, dist, hodograph) : 305 | len(ctlPts) == 4 ? PerpAlongBez4(t, ctlPts, dist, hodograph) : 306 | len(ctlPts) == 5 ? PerpAlongBez5(t, ctlPts, dist, hodograph) : 307 | len(ctlPts) == 6 ? PerpAlongBez6(t, ctlPts, dist, hodograph) : 308 | len(ctlPts) == 7 ? PerpAlongBez7(t, ctlPts, dist, hodograph) : 309 | len(ctlPts) == 8 ? PerpAlongBez8(t, ctlPts, dist, hodograph) : 310 | []; 311 | 312 | function PerpAlongBez2(t, ctlPts, dist = 1, hodograph = []) = 313 | pSum( 314 | PointAlongBez2(t, ctlPts), 315 | rot90cw( 316 | normalize( 317 | PointAlongBez1( t, (len(hodograph) > 1) ? hodograph : hodograph(ctlPts) ), 318 | dist 319 | ) 320 | ) 321 | ); 322 | 323 | function PerpAlongBez3(t, ctlPts, dist = 1, hodograph = []) = 324 | pSum( 325 | PointAlongBez3(t, ctlPts), 326 | rot90cw( 327 | normalize( 328 | PointAlongBez2( t, (len(hodograph) > 1) ? hodograph : hodograph(ctlPts) ), 329 | dist 330 | ) 331 | ) 332 | ); 333 | 334 | function PerpAlongBez4(t, ctlPts, dist = 1, hodograph = []) = 335 | pSum( 336 | PointAlongBez4(t, ctlPts), 337 | rot90cw( 338 | normalize( 339 | PointAlongBez3( t, (len(hodograph) > 1) ? hodograph : hodograph(ctlPts) ), 340 | dist 341 | ) 342 | ) 343 | ); 344 | 345 | function PerpAlongBez5(t, ctlPts, dist = 1, hodograph = []) = 346 | pSum( 347 | PointAlongBez5(t, ctlPts), 348 | rot90cw( 349 | normalize( 350 | PointAlongBez4( t, (len(hodograph) > 1) ? hodograph : hodograph(ctlPts) ), 351 | dist 352 | ) 353 | ) 354 | ); 355 | 356 | function PerpAlongBez6(t, ctlPts, dist = 1, hodograph = []) = 357 | pSum( 358 | PointAlongBez6(t, ctlPts), 359 | rot90cw( 360 | normalize( 361 | PointAlongBez5( t, (len(hodograph) > 1) ? hodograph : hodograph(ctlPts) ), 362 | dist 363 | ) 364 | ) 365 | ); 366 | 367 | function PerpAlongBez7(t, ctlPts, dist = 1, hodograph = []) = 368 | pSum( 369 | PointAlongBez7(t, ctlPts), 370 | rot90cw( 371 | normalize( 372 | PointAlongBez6( t, (len(hodograph) > 1) ? hodograph : hodograph(ctlPts) ), 373 | dist 374 | ) 375 | ) 376 | ); 377 | 378 | function PerpAlongBez8(t, ctlPts, dist = 1, hodograph = []) = 379 | pSum( 380 | PointAlongBez8(t, ctlPts), 381 | rot90cw( 382 | normalize( 383 | PointAlongBez7( t, (len(hodograph) > 1) ? hodograph : hodograph(ctlPts) ), 384 | dist 385 | ) 386 | ) 387 | ); 388 | 389 | 390 | function hodograph(p) = 391 | len(p) == 2 ? 392 | [ pDiff(p[1], p[0]) ] : 393 | len(p) == 3 ? 394 | [ pDiff(p[1], p[0]), pDiff(p[2], p[1]) ] : 395 | len(p) == 4 ? 396 | [ pDiff(p[1], p[0]), pDiff(p[2], p[1]), pDiff(p[3], p[2]) ] : 397 | len(p) == 5 ? 398 | [ pDiff(p[1], p[0]), pDiff(p[2], p[1]), pDiff(p[3], p[2]), pDiff(p[4], p[3]) ] : 399 | len(p) == 6 ? 400 | [ pDiff(p[1], p[0]), pDiff(p[2], p[1]), pDiff(p[3], p[2]), pDiff(p[4], p[3]), pDiff(p[5], p[4]) ] : 401 | len(p) == 7 ? 402 | [ pDiff(p[1], p[0]), pDiff(p[2], p[1]), pDiff(p[3], p[2]), pDiff(p[4], p[3]), pDiff(p[5], p[4]), pDiff(p[6], p[5]) ] : 403 | len(p) == 8 ? 404 | [ pDiff(p[1], p[0]), pDiff(p[2], p[1]), pDiff(p[3], p[2]), pDiff(p[4], p[3]), pDiff(p[5], p[4]), pDiff(p[6], p[5]), pDiff(p[7], p[6]) ] : 405 | []; 406 | 407 | function BezI1(t, ctls) = 408 | (ctls[0]) 409 | ; 410 | 411 | function BezI2(t, ctls) = 412 | ((1-t) * ctls[0]) + 413 | (t * ctls[1]) 414 | ; 415 | 416 | function BezI3(t, ctls) = 417 | (pow(1-t, 2) * ctls[0]) + 418 | (2 * t * (1-t) * ctls[1]) + 419 | (pow(t, 2) * ctls[2]) 420 | ; 421 | 422 | function BezI4(t, ctls) = 423 | (pow(1-t, 3) * ctls[0]) + 424 | (3 * t * pow(1-t, 2) * ctls[1]) + 425 | (3 * pow(t, 2) * (1-t) * ctls[2]) + 426 | (pow(t, 3) * ctls[3]) 427 | ; 428 | 429 | function BezI5(t, ctls) = 430 | (pow(1-t, 4) * ctls[0]) + 431 | (4 * t * pow(1-t, 3) * ctls[1]) + 432 | (6 * pow(t, 2) * pow(1-t, 2) * ctls[2]) + 433 | (4 * pow(t, 3) * (1-t) * ctls[3]) + 434 | (pow(t, 4) * ctls[4]) 435 | ; 436 | 437 | function BezI6(t, ctls) = 438 | (pow(1-t, 5) * ctls[0]) + 439 | (5 * t * pow(1-t, 4) * ctls[1]) + 440 | (10 * pow(t, 2) * pow(1-t, 3) * ctls[2]) + 441 | (10 * pow(t, 3) * pow(1-t, 2) * ctls[3]) + 442 | (5 * pow(t, 4) * (1-t) * ctls[4]) + 443 | (pow(t, 5) * ctls[5]) 444 | ; 445 | 446 | function BezI7(t, ctls) = 447 | (pow(1-t, 6) * ctls[0]) + 448 | (6 * t * pow(1-t, 5) * ctls[1]) + 449 | (15 * pow(t, 2) * pow(1-t, 4) * ctls[2]) + 450 | (20 * pow(t, 3) * pow(1-t, 3) * ctls[3]) + 451 | (15 * pow(t, 4) * pow(1-t, 2) * ctls[4]) + 452 | (6 * pow(t, 5) * (1-t) * ctls[5]) + 453 | (pow(t, 6) * ctls[6]) 454 | ; 455 | 456 | function BezI8(t, ctls) = 457 | (pow(1-t, 7) * ctls[0]) + 458 | (7 * t * pow(1-t, 6) * ctls[1]) + 459 | (21 * pow(t, 2) * pow(1-t, 5) * ctls[2]) + 460 | (35 * pow(t, 3) * pow(1-t, 4) * ctls[3]) + 461 | (35 * pow(t, 4) * pow(1-t, 3) * ctls[4]) + 462 | (21 * pow(t, 5) * pow(1-t, 2) * ctls[5]) + 463 | (7 * pow(t, 6) * (1-t) * ctls[6]) + 464 | (pow(t, 7) * ctls[7]) 465 | ; 466 | 467 | function x(p) = p[0]; 468 | function y(p) = p[1]; 469 | function dx(p1, p2) = x(p1) - x(p2); 470 | function dy(p1, p2) = y(p1) - y(p2); 471 | function sx(p1, p2) = x(p1) + x(p2); 472 | function sy(p1, p2) = y(p1) + y(p2); 473 | 474 | function dist(p1, p2 = [0,0]) = sqrt( pow( dx(p1,p2), 2) + pow( dy(p1,p2), 2) ); 475 | function normalize(p, n = 1) = pScale( p, n / dist( p ) ); 476 | 477 | function pSum(p1, p2) = [sx(p1, p2), sy(p1, p2)]; 478 | function pDiff(p1, p2) = [dx(p1, p2), dy(p1, p2)]; 479 | function pScale(p, v) = [x(p)*v, y(p)*v]; 480 | 481 | function rot90cw(p) = [y(p), -x(p)]; 482 | function rot90ccw(p) = [-y(p), x(p)]; 483 | function rot(p, a) = [ 484 | x(p) * cos(a) - y(p) * sin(a), 485 | x(p) * sin(a) - y(p) * cos(a), 486 | ]; 487 | function rotAbout(p1, p2, a) = pSum(rot(pDiff(p1, p2), a), p2); // rotate p1 about p2 488 | -------------------------------------------------------------------------------- /BezierTest.scad: -------------------------------------------------------------------------------- 1 | use ; 2 | x = 25; 3 | 4 | translate([7.5,0,0]) 5 | BezWall( [ 6 | [0,0], 7 | [x/2, x], 8 | [x,0], 9 | ] , width = 1.5, height = 10, steps = 4, centered = true ); 10 | 11 | translate([37.5,0,0]) 12 | BezWall( [ 13 | [0,0], 14 | [0, x], [x, x], 15 | [x,0], 16 | ] , width = 1.5, height = 10, steps = 6, centered = true ); 17 | 18 | translate([67.5,0,0]) 19 | BezWall( [ 20 | [0,0], 21 | [0, x], [x/2, x], [x, x], 22 | [x,0], 23 | ] , width = 1.5, height = 10, steps = 8, centered = true ); 24 | 25 | translate([97.5,0,0]) 26 | BezWall( [ 27 | [0,0], 28 | [0, x], [0, x], [x, x], [x, x], 29 | [x,0], 30 | ] , width = 1.5, height = 10, steps = 10, centered = true ); 31 | 32 | translate([127.5,0,0]) 33 | BezWall( [ 34 | [0,0], 35 | [0, x], [0, x], [x/2, x], [x, x], [x, x], 36 | [x,0], 37 | ] , width = 1.5, height = 10, steps = 12, centered = true ); 38 | 39 | translate([157.5,0,0]) 40 | BezWall( [ 41 | [0,0], 42 | [0, x], [0, x], [0, x], [x, x], [x, x], [x, x], 43 | [x,0], 44 | ] , width = 1.5, height = 10, steps = 14, centered = true ); 45 | 46 | BezWall([ 47 | [-0.1,0], 48 | [-20, 0], 49 | [-25,25] 50 | ], widthCtls = [10, 1], 51 | heightCtls = [1, 5, 6, 35], 52 | steps = 32, 53 | centered = true 54 | ); 55 | translate([0,30,0]) 56 | BezWall([ 57 | [-0.1,0], 58 | [-15, 0], 59 | [-15, 25], 60 | [-25,25] 61 | ], 62 | width = 2, 63 | heightCtls = [1, 35, 1], 64 | steps = 16, 65 | centered = false 66 | ); 67 | 68 | translate([-30,30,0]) 69 | BezWall([ 70 | [-0.1,0], 71 | [-15, 0], 72 | [-15, 25], 73 | [-25,25] 74 | ], 75 | widthCtls = [2, 10], 76 | height = 5, 77 | steps = 16, 78 | centered = true 79 | ); 80 | 81 | linear_extrude(height = 5) 82 | BezLine([ 83 | [0,-10], [5, -20], [0,-30] 84 | ], width = [5, 10], resolution = 2, centered = true); 85 | 86 | linear_extrude(height = 5) 87 | BezLine([ 88 | [0,10], [5, 20], [0,30] 89 | ], width = [5, 10], resolution = 3, centered = false); 90 | 91 | translate([-10, -10,0]) 92 | BezArc([ 93 | [-10,-1], 94 | [-10, -10], 95 | [-1,-10] 96 | ], [-1,-1], steps = 16, heightCtls = [1,10]); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | I wanted a bezier library that could handle an arbitrary number of control points. When working on http://www.thingiverse.com/thing:77586, I also wanted to rotate extrude a "wall" defined by a bezier path and a width. 2 | 3 | BezWall is the workhorse function. The "ctlPts" parameter accepts between 1-8 bezier control points. 4 | 5 | The parameters "width" and "height" accept static values (e.g., 5) specifying the width and height of the wall. If height is 0, it will generate a 2d object you can extrude yourself. 6 | 7 | The alternate parameters "widthCtls" and "heightCtls" accept an array of values that will be bezier-interpolated along the length of the wall. 8 | 9 | If the "centered" parameter is "true", the wall is centered on the path defined by "ctlPts". Otherwise, one edge of the wall is defined by "ctlPts". 10 | 11 | At the moment, there is no documentation! But there is a test file that runs through most of the available features. 12 | 13 | I'd previously done some work writing coffeescript code to generate bezier interpolation functions that accept an arbitrary number of control points, and I'd written some coffeescript to generate openscad code. It occurred to me that I could use coffeescript to automate a lot of the tedium in writing openscad functions. So, the coffeescript file in this thing will generate openscad functions to handle bezier interpolation with a varying number of control points. The attached BezierScad.scad file can deal with up to 8 control points, but you can easily modify orderMax in the coffeescript file to have it generate functions that can deal with higher or lower orders. 14 | 15 | The BezLine function is simpler than BezWall and offers a subset of the BezWall functionality. 16 | 17 | BezLine takes an array of 1-8 control points and an array of 1-8 width values, which will be bezier interpolated as widths for the resulting line. 18 | 19 | BezLine doesn't accept a "steps" parameter. Rather, it takes a "resolution" parameter of between 2-6. The resulting line will have (2**resolution) segments. 20 | 21 | BezArc returns a shape similar to that generated by WilliamAAdams' [BezQuadCurve function](http://www.thingiverse.com/thing:8443). 22 | 23 | --------------------------------------------------------------------------------