yapCAD 0.5.0__py2.py3-none-any.whl → 0.5.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
yapcad/drawable.py CHANGED
@@ -286,6 +286,23 @@ class Drawable:
286
286
  else:
287
287
  raise ValueError("bad value for polystyle: {}".format(self.polystyle))
288
288
 
289
+ elif iscatmullrom(x):
290
+ from yapcad.spline import sample_catmullrom
291
+ pts = sample_catmullrom(x)
292
+ closed = bool(x[2].get('closed', False))
293
+ for i in range(1, len(pts)):
294
+ self.draw_line(pts[i-1], pts[i])
295
+ if closed and pts:
296
+ self.draw_line(pts[-1], pts[0])
297
+ elif isnurbs(x):
298
+ from yapcad.spline import sample_nurbs
299
+ meta = x[2]
300
+ default = max(32, len(x[1]) * 8)
301
+ count = int(meta.get('samples', default))
302
+ pts = sample_nurbs(x, samples=max(4, count))
303
+ for i in range(1, len(pts)):
304
+ self.draw_line(pts[i-1], pts[i])
305
+
289
306
  elif isinstance(x,Geometry):
290
307
  gl = x.geom
291
308
  self.draw(gl)
@@ -304,25 +321,362 @@ class Drawable:
304
321
  return True
305
322
 
306
323
 
307
- ## Standard color names, ala HTML: https://www.rapidtables.com/web/color/RGB_Color.html
324
+ ## Standard color names per W3C CSS Color Module Level 4 keywords.
325
+ # Standardized color keywords (CSS Color Module Level 4) plus
326
+ # X11 gray/grey ramp entries for broader palette coverage.
308
327
  colordict= {
309
- 'black': [ [0,0,0], 0],
310
- 'white': [ [255,255,255], 7],
311
- 'red': [ [255,0,0], 1],
312
- 'lime': [ [0,255,0],3],
313
- 'blue': [ [0,0,255], 5],
314
- 'yellow': [ [255,255,0], 2],
315
- 'silver': [ [192,192,192], 9],
316
- 'gray': [ [128,128,128], 8],
317
- 'maroon': [ [127,0,0], 14],
318
- 'olive': [ [127,127,0], 54],
319
- 'green': [ [0,127,0], 94],
320
- 'aqua': [ [0,255,255], 4],
321
- 'teal': [ [0,127,127], 134],
322
- 'navy': [ [0,0,128], 174],
323
- 'fuchsia': [ [255,0,255], 6],
324
- 'purple': [ [128,0,128], 214] }
325
-
328
+ 'aliceblue': ([240, 248, 255], None),
329
+ 'antiquewhite': ([250, 235, 215], None),
330
+ 'aqua': ([0, 255, 255], 4),
331
+ 'aquamarine': ([127, 255, 212], None),
332
+ 'azure': ([240, 255, 255], None),
333
+ 'beige': ([245, 245, 220], None),
334
+ 'bisque': ([255, 228, 196], None),
335
+ 'black': ([0, 0, 0], 0),
336
+ 'blanchedalmond': ([255, 235, 205], None),
337
+ 'blue': ([0, 0, 255], 5),
338
+ 'blueviolet': ([138, 43, 226], None),
339
+ 'brown': ([165, 42, 42], None),
340
+ 'burlywood': ([222, 184, 135], None),
341
+ 'cadetblue': ([95, 158, 160], None),
342
+ 'chartreuse': ([127, 255, 0], None),
343
+ 'chocolate': ([210, 105, 30], None),
344
+ 'coral': ([255, 127, 80], None),
345
+ 'cornflowerblue': ([100, 149, 237], None),
346
+ 'cornsilk': ([255, 248, 220], None),
347
+ 'crimson': ([220, 20, 60], None),
348
+ 'cyan': ([0, 255, 255], None),
349
+ 'darkblue': ([0, 0, 139], None),
350
+ 'darkcyan': ([0, 139, 139], None),
351
+ 'darkgoldenrod': ([184, 134, 11], None),
352
+ 'darkgray': ([169, 169, 169], None),
353
+ 'darkgreen': ([0, 100, 0], None),
354
+ 'darkgrey': ([169, 169, 169], None),
355
+ 'darkkhaki': ([189, 183, 107], None),
356
+ 'darkmagenta': ([139, 0, 139], None),
357
+ 'darkolivegreen': ([85, 107, 47], None),
358
+ 'darkorange': ([255, 140, 0], None),
359
+ 'darkorchid': ([153, 50, 204], None),
360
+ 'darkred': ([139, 0, 0], None),
361
+ 'darksalmon': ([233, 150, 122], None),
362
+ 'darkseagreen': ([143, 188, 143], None),
363
+ 'darkslateblue': ([72, 61, 139], None),
364
+ 'darkslategray': ([47, 79, 79], None),
365
+ 'darkslategrey': ([47, 79, 79], None),
366
+ 'darkturquoise': ([0, 206, 209], None),
367
+ 'darkviolet': ([148, 0, 211], None),
368
+ 'deeppink': ([255, 20, 147], None),
369
+ 'deepskyblue': ([0, 191, 255], None),
370
+ 'dimgray': ([105, 105, 105], None),
371
+ 'dimgrey': ([105, 105, 105], None),
372
+ 'dodgerblue': ([30, 144, 255], None),
373
+ 'firebrick': ([178, 34, 34], None),
374
+ 'floralwhite': ([255, 250, 240], None),
375
+ 'forestgreen': ([34, 139, 34], None),
376
+ 'fuchsia': ([255, 0, 255], 6),
377
+ 'gainsboro': ([220, 220, 220], None),
378
+ 'ghostwhite': ([248, 248, 255], None),
379
+ 'gold': ([255, 215, 0], None),
380
+ 'goldenrod': ([218, 165, 32], None),
381
+ 'gray': ([128, 128, 128], 8),
382
+ 'gray0': ([0, 0, 0], None),
383
+ 'gray1': ([3, 3, 3], None),
384
+ 'gray10': ([26, 26, 26], None),
385
+ 'gray100': ([255, 255, 255], None),
386
+ 'gray11': ([28, 28, 28], None),
387
+ 'gray12': ([31, 31, 31], None),
388
+ 'gray13': ([33, 33, 33], None),
389
+ 'gray14': ([36, 36, 36], None),
390
+ 'gray15': ([38, 38, 38], None),
391
+ 'gray16': ([41, 41, 41], None),
392
+ 'gray17': ([43, 43, 43], None),
393
+ 'gray18': ([46, 46, 46], None),
394
+ 'gray19': ([48, 48, 48], None),
395
+ 'gray2': ([5, 5, 5], None),
396
+ 'gray20': ([51, 51, 51], None),
397
+ 'gray21': ([54, 54, 54], None),
398
+ 'gray22': ([56, 56, 56], None),
399
+ 'gray23': ([59, 59, 59], None),
400
+ 'gray24': ([61, 61, 61], None),
401
+ 'gray25': ([64, 64, 64], None),
402
+ 'gray26': ([66, 66, 66], None),
403
+ 'gray27': ([69, 69, 69], None),
404
+ 'gray28': ([71, 71, 71], None),
405
+ 'gray29': ([74, 74, 74], None),
406
+ 'gray3': ([8, 8, 8], None),
407
+ 'gray30': ([76, 76, 76], None),
408
+ 'gray31': ([79, 79, 79], None),
409
+ 'gray32': ([82, 82, 82], None),
410
+ 'gray33': ([84, 84, 84], None),
411
+ 'gray34': ([87, 87, 87], None),
412
+ 'gray35': ([89, 89, 89], None),
413
+ 'gray36': ([92, 92, 92], None),
414
+ 'gray37': ([94, 94, 94], None),
415
+ 'gray38': ([97, 97, 97], None),
416
+ 'gray39': ([99, 99, 99], None),
417
+ 'gray4': ([10, 10, 10], None),
418
+ 'gray40': ([102, 102, 102], None),
419
+ 'gray41': ([105, 105, 105], None),
420
+ 'gray42': ([107, 107, 107], None),
421
+ 'gray43': ([110, 110, 110], None),
422
+ 'gray44': ([112, 112, 112], None),
423
+ 'gray45': ([115, 115, 115], None),
424
+ 'gray46': ([117, 117, 117], None),
425
+ 'gray47': ([120, 120, 120], None),
426
+ 'gray48': ([122, 122, 122], None),
427
+ 'gray49': ([125, 125, 125], None),
428
+ 'gray5': ([13, 13, 13], None),
429
+ 'gray50': ([128, 128, 128], None),
430
+ 'gray51': ([130, 130, 130], None),
431
+ 'gray52': ([133, 133, 133], None),
432
+ 'gray53': ([135, 135, 135], None),
433
+ 'gray54': ([138, 138, 138], None),
434
+ 'gray55': ([140, 140, 140], None),
435
+ 'gray56': ([143, 143, 143], None),
436
+ 'gray57': ([145, 145, 145], None),
437
+ 'gray58': ([148, 148, 148], None),
438
+ 'gray59': ([150, 150, 150], None),
439
+ 'gray6': ([15, 15, 15], None),
440
+ 'gray60': ([153, 153, 153], None),
441
+ 'gray61': ([156, 156, 156], None),
442
+ 'gray62': ([158, 158, 158], None),
443
+ 'gray63': ([161, 161, 161], None),
444
+ 'gray64': ([163, 163, 163], None),
445
+ 'gray65': ([166, 166, 166], None),
446
+ 'gray66': ([168, 168, 168], None),
447
+ 'gray67': ([171, 171, 171], None),
448
+ 'gray68': ([173, 173, 173], None),
449
+ 'gray69': ([176, 176, 176], None),
450
+ 'gray7': ([18, 18, 18], None),
451
+ 'gray70': ([178, 178, 178], None),
452
+ 'gray71': ([181, 181, 181], None),
453
+ 'gray72': ([184, 184, 184], None),
454
+ 'gray73': ([186, 186, 186], None),
455
+ 'gray74': ([189, 189, 189], None),
456
+ 'gray75': ([191, 191, 191], None),
457
+ 'gray76': ([194, 194, 194], None),
458
+ 'gray77': ([196, 196, 196], None),
459
+ 'gray78': ([199, 199, 199], None),
460
+ 'gray79': ([201, 201, 201], None),
461
+ 'gray8': ([20, 20, 20], None),
462
+ 'gray80': ([204, 204, 204], None),
463
+ 'gray81': ([207, 207, 207], None),
464
+ 'gray82': ([209, 209, 209], None),
465
+ 'gray83': ([212, 212, 212], None),
466
+ 'gray84': ([214, 214, 214], None),
467
+ 'gray85': ([217, 217, 217], None),
468
+ 'gray86': ([219, 219, 219], None),
469
+ 'gray87': ([222, 222, 222], None),
470
+ 'gray88': ([224, 224, 224], None),
471
+ 'gray89': ([227, 227, 227], None),
472
+ 'gray9': ([23, 23, 23], None),
473
+ 'gray90': ([230, 230, 230], None),
474
+ 'gray91': ([232, 232, 232], None),
475
+ 'gray92': ([235, 235, 235], None),
476
+ 'gray93': ([237, 237, 237], None),
477
+ 'gray94': ([240, 240, 240], None),
478
+ 'gray95': ([242, 242, 242], None),
479
+ 'gray96': ([245, 245, 245], None),
480
+ 'gray97': ([247, 247, 247], None),
481
+ 'gray98': ([250, 250, 250], None),
482
+ 'gray99': ([252, 252, 252], None),
483
+ 'green': ([0, 127, 0], 94),
484
+ 'greenyellow': ([173, 255, 47], None),
485
+ 'grey': ([128, 128, 128], None),
486
+ 'grey0': ([0, 0, 0], None),
487
+ 'grey1': ([3, 3, 3], None),
488
+ 'grey10': ([26, 26, 26], None),
489
+ 'grey100': ([255, 255, 255], None),
490
+ 'grey11': ([28, 28, 28], None),
491
+ 'grey12': ([31, 31, 31], None),
492
+ 'grey13': ([33, 33, 33], None),
493
+ 'grey14': ([36, 36, 36], None),
494
+ 'grey15': ([38, 38, 38], None),
495
+ 'grey16': ([41, 41, 41], None),
496
+ 'grey17': ([43, 43, 43], None),
497
+ 'grey18': ([46, 46, 46], None),
498
+ 'grey19': ([48, 48, 48], None),
499
+ 'grey2': ([5, 5, 5], None),
500
+ 'grey20': ([51, 51, 51], None),
501
+ 'grey21': ([54, 54, 54], None),
502
+ 'grey22': ([56, 56, 56], None),
503
+ 'grey23': ([59, 59, 59], None),
504
+ 'grey24': ([61, 61, 61], None),
505
+ 'grey25': ([64, 64, 64], None),
506
+ 'grey26': ([66, 66, 66], None),
507
+ 'grey27': ([69, 69, 69], None),
508
+ 'grey28': ([71, 71, 71], None),
509
+ 'grey29': ([74, 74, 74], None),
510
+ 'grey3': ([8, 8, 8], None),
511
+ 'grey30': ([76, 76, 76], None),
512
+ 'grey31': ([79, 79, 79], None),
513
+ 'grey32': ([82, 82, 82], None),
514
+ 'grey33': ([84, 84, 84], None),
515
+ 'grey34': ([87, 87, 87], None),
516
+ 'grey35': ([89, 89, 89], None),
517
+ 'grey36': ([92, 92, 92], None),
518
+ 'grey37': ([94, 94, 94], None),
519
+ 'grey38': ([97, 97, 97], None),
520
+ 'grey39': ([99, 99, 99], None),
521
+ 'grey4': ([10, 10, 10], None),
522
+ 'grey40': ([102, 102, 102], None),
523
+ 'grey41': ([105, 105, 105], None),
524
+ 'grey42': ([107, 107, 107], None),
525
+ 'grey43': ([110, 110, 110], None),
526
+ 'grey44': ([112, 112, 112], None),
527
+ 'grey45': ([115, 115, 115], None),
528
+ 'grey46': ([117, 117, 117], None),
529
+ 'grey47': ([120, 120, 120], None),
530
+ 'grey48': ([122, 122, 122], None),
531
+ 'grey49': ([125, 125, 125], None),
532
+ 'grey5': ([13, 13, 13], None),
533
+ 'grey50': ([128, 128, 128], None),
534
+ 'grey51': ([130, 130, 130], None),
535
+ 'grey52': ([133, 133, 133], None),
536
+ 'grey53': ([135, 135, 135], None),
537
+ 'grey54': ([138, 138, 138], None),
538
+ 'grey55': ([140, 140, 140], None),
539
+ 'grey56': ([143, 143, 143], None),
540
+ 'grey57': ([145, 145, 145], None),
541
+ 'grey58': ([148, 148, 148], None),
542
+ 'grey59': ([150, 150, 150], None),
543
+ 'grey6': ([15, 15, 15], None),
544
+ 'grey60': ([153, 153, 153], None),
545
+ 'grey61': ([156, 156, 156], None),
546
+ 'grey62': ([158, 158, 158], None),
547
+ 'grey63': ([161, 161, 161], None),
548
+ 'grey64': ([163, 163, 163], None),
549
+ 'grey65': ([166, 166, 166], None),
550
+ 'grey66': ([168, 168, 168], None),
551
+ 'grey67': ([171, 171, 171], None),
552
+ 'grey68': ([173, 173, 173], None),
553
+ 'grey69': ([176, 176, 176], None),
554
+ 'grey7': ([18, 18, 18], None),
555
+ 'grey70': ([178, 178, 178], None),
556
+ 'grey71': ([181, 181, 181], None),
557
+ 'grey72': ([184, 184, 184], None),
558
+ 'grey73': ([186, 186, 186], None),
559
+ 'grey74': ([189, 189, 189], None),
560
+ 'grey75': ([191, 191, 191], None),
561
+ 'grey76': ([194, 194, 194], None),
562
+ 'grey77': ([196, 196, 196], None),
563
+ 'grey78': ([199, 199, 199], None),
564
+ 'grey79': ([201, 201, 201], None),
565
+ 'grey8': ([20, 20, 20], None),
566
+ 'grey80': ([204, 204, 204], None),
567
+ 'grey81': ([207, 207, 207], None),
568
+ 'grey82': ([209, 209, 209], None),
569
+ 'grey83': ([212, 212, 212], None),
570
+ 'grey84': ([214, 214, 214], None),
571
+ 'grey85': ([217, 217, 217], None),
572
+ 'grey86': ([219, 219, 219], None),
573
+ 'grey87': ([222, 222, 222], None),
574
+ 'grey88': ([224, 224, 224], None),
575
+ 'grey89': ([227, 227, 227], None),
576
+ 'grey9': ([23, 23, 23], None),
577
+ 'grey90': ([230, 230, 230], None),
578
+ 'grey91': ([232, 232, 232], None),
579
+ 'grey92': ([235, 235, 235], None),
580
+ 'grey93': ([237, 237, 237], None),
581
+ 'grey94': ([240, 240, 240], None),
582
+ 'grey95': ([242, 242, 242], None),
583
+ 'grey96': ([245, 245, 245], None),
584
+ 'grey97': ([247, 247, 247], None),
585
+ 'grey98': ([250, 250, 250], None),
586
+ 'grey99': ([252, 252, 252], None),
587
+ 'honeydew': ([240, 255, 240], None),
588
+ 'hotpink': ([255, 105, 180], None),
589
+ 'indianred': ([205, 92, 92], None),
590
+ 'indigo': ([75, 0, 130], None),
591
+ 'ivory': ([255, 255, 240], None),
592
+ 'khaki': ([240, 230, 140], None),
593
+ 'lavender': ([230, 230, 250], None),
594
+ 'lavenderblush': ([255, 240, 245], None),
595
+ 'lawngreen': ([124, 252, 0], None),
596
+ 'lemonchiffon': ([255, 250, 205], None),
597
+ 'lightblue': ([173, 216, 230], None),
598
+ 'lightcoral': ([240, 128, 128], None),
599
+ 'lightcyan': ([224, 255, 255], None),
600
+ 'lightgoldenrodyellow': ([250, 250, 210], None),
601
+ 'lightgray': ([211, 211, 211], None),
602
+ 'lightgreen': ([144, 238, 144], None),
603
+ 'lightgrey': ([211, 211, 211], None),
604
+ 'lightpink': ([255, 182, 193], None),
605
+ 'lightsalmon': ([255, 160, 122], None),
606
+ 'lightseagreen': ([32, 178, 170], None),
607
+ 'lightskyblue': ([135, 206, 250], None),
608
+ 'lightslategray': ([119, 136, 153], None),
609
+ 'lightslategrey': ([119, 136, 153], None),
610
+ 'lightsteelblue': ([176, 196, 222], None),
611
+ 'lightyellow': ([255, 255, 224], None),
612
+ 'lime': ([0, 255, 0], 3),
613
+ 'limegreen': ([50, 205, 50], None),
614
+ 'linen': ([250, 240, 230], None),
615
+ 'magenta': ([255, 0, 255], None),
616
+ 'maroon': ([127, 0, 0], 14),
617
+ 'mediumaquamarine': ([102, 205, 170], None),
618
+ 'mediumblue': ([0, 0, 205], None),
619
+ 'mediumorchid': ([186, 85, 211], None),
620
+ 'mediumpurple': ([147, 112, 219], None),
621
+ 'mediumseagreen': ([60, 179, 113], None),
622
+ 'mediumslateblue': ([123, 104, 238], None),
623
+ 'mediumspringgreen': ([0, 250, 154], None),
624
+ 'mediumturquoise': ([72, 209, 204], None),
625
+ 'mediumvioletred': ([199, 21, 133], None),
626
+ 'midnightblue': ([25, 25, 112], None),
627
+ 'mintcream': ([245, 255, 250], None),
628
+ 'mistyrose': ([255, 228, 225], None),
629
+ 'moccasin': ([255, 228, 181], None),
630
+ 'navajowhite': ([255, 222, 173], None),
631
+ 'navy': ([0, 0, 128], 174),
632
+ 'oldlace': ([253, 245, 230], None),
633
+ 'olive': ([127, 127, 0], 54),
634
+ 'olivedrab': ([107, 142, 35], None),
635
+ 'orange': ([255, 165, 0], None),
636
+ 'orangered': ([255, 69, 0], None),
637
+ 'orchid': ([218, 112, 214], None),
638
+ 'palegoldenrod': ([238, 232, 170], None),
639
+ 'palegreen': ([152, 251, 152], None),
640
+ 'paleturquoise': ([175, 238, 238], None),
641
+ 'palevioletred': ([219, 112, 147], None),
642
+ 'papayawhip': ([255, 239, 213], None),
643
+ 'peachpuff': ([255, 218, 185], None),
644
+ 'peru': ([205, 133, 63], None),
645
+ 'pink': ([255, 192, 203], None),
646
+ 'plum': ([221, 160, 221], None),
647
+ 'powderblue': ([176, 224, 230], None),
648
+ 'purple': ([128, 0, 128], 214),
649
+ 'rebeccapurple': ([102, 51, 153], None),
650
+ 'red': ([255, 0, 0], 1),
651
+ 'rosybrown': ([188, 143, 143], None),
652
+ 'royalblue': ([65, 105, 225], None),
653
+ 'saddlebrown': ([139, 69, 19], None),
654
+ 'salmon': ([250, 128, 114], None),
655
+ 'sandybrown': ([244, 164, 96], None),
656
+ 'seagreen': ([46, 139, 87], None),
657
+ 'seashell': ([255, 245, 238], None),
658
+ 'sienna': ([160, 82, 45], None),
659
+ 'silver': ([192, 192, 192], 9),
660
+ 'skyblue': ([135, 206, 235], None),
661
+ 'slateblue': ([106, 90, 205], None),
662
+ 'slategray': ([112, 128, 144], None),
663
+ 'slategrey': ([112, 128, 144], None),
664
+ 'snow': ([255, 250, 250], None),
665
+ 'springgreen': ([0, 255, 127], None),
666
+ 'steelblue': ([70, 130, 180], None),
667
+ 'tan': ([210, 180, 140], None),
668
+ 'teal': ([0, 127, 127], 134),
669
+ 'thistle': ([216, 191, 216], None),
670
+ 'tomato': ([255, 99, 71], None),
671
+ 'turquoise': ([64, 224, 208], None),
672
+ 'violet': ([238, 130, 238], None),
673
+ 'wheat': ([245, 222, 179], None),
674
+ 'white': ([255, 255, 255], 7),
675
+ 'whitesmoke': ([245, 245, 245], None),
676
+ 'yellow': ([255, 255, 0], 2),
677
+ 'yellowgreen': ([154, 205, 50], None),
678
+ }
679
+
326
680
  ## AUTOCAD color index:
327
681
  ## https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/
328
682
  ## rgb-values-of-the-256-standard-indexed-colors/td-p/848912
@@ -614,14 +968,33 @@ class Drawable:
614
968
  ## function to convert between different color representations
615
969
  def thing2color(self,thing,convert='b',colormap=None,colordict=None):
616
970
  def _b2f(c):
617
- return [ c[0]/255.0,c[1]/255.0,c[2]/255.0 ]
971
+ return [c[0] / 255.0, c[1] / 255.0, c[2] / 255.0]
972
+
618
973
  def _f2b(c):
619
- return [ round(c[0]*255.0),rount(c[1]*255.0),round(c[2]*255.0) ]
974
+ return [round(c[0] * 255.0), round(c[1] * 255.0), round(c[2] * 255.0)]
975
+
976
+ def _nearest_index(rgb):
977
+ best_idx = 0
978
+ best_dist = float('inf')
979
+ for idx, candidate in enumerate(colormap):
980
+ if not isinstance(candidate, (list, tuple)) or len(candidate) != 3:
981
+ continue
982
+ dist = ((candidate[0] - rgb[0]) ** 2 +
983
+ (candidate[1] - rgb[1]) ** 2 +
984
+ (candidate[2] - rgb[2]) ** 2)
985
+ if dist < best_dist:
986
+ best_idx = idx
987
+ best_dist = dist
988
+ if dist == 0:
989
+ break
990
+ return best_idx
991
+
620
992
  def _b2i(c):
621
993
  for i in range(len(colormap)):
622
- if colormap[i] == thing:
994
+ if colormap[i] == c:
623
995
  return i
624
- return False
996
+ return _nearest_index(c)
997
+
625
998
  def _f2i(c):
626
999
  return _b2i(_f2b(c))
627
1000
  def _isgoodf(x):
@@ -657,13 +1030,19 @@ class Drawable:
657
1030
  else:
658
1031
  return thing
659
1032
  elif isinstance(thing,str):
660
- cd = colordict[thing]
1033
+ key = thing.lower()
1034
+ if key not in colordict:
1035
+ raise ValueError('bad color name passed to thing2color: {}'.format(thing))
1036
+ cd = colordict[key]
661
1037
  if isinstance(cd,bool) and cd == False:
662
1038
  raise ValueError('bad color name passed to thing2color: {}'.format(thing))
663
1039
  if convert == 'i':
664
- return cd[1]
1040
+ idx = cd[1]
1041
+ if idx is None:
1042
+ idx = _nearest_index(cd[0])
1043
+ return idx
665
1044
  else:
666
- c = cd[0]
1045
+ c = list(cd[0])
667
1046
  elif isinstance(thing,int):
668
1047
  if thing < 0 or thing > len(colormap):
669
1048
  raise ValueError('colormap index out of range: {}'.format(thing))
@@ -681,4 +1060,3 @@ class Drawable:
681
1060
  return _b2f(c)
682
1061
  return list(c)
683
1062
 
684
-
yapcad/geom.py CHANGED
@@ -409,6 +409,92 @@ and polygon-specific computational geometry operations, notably:
409
409
 
410
410
  """
411
411
 
412
+ ## spline curves
413
+ ## =============
414
+ ##
415
+ ## Modern procedural CAD workflows frequently mix straight segments with
416
+ ## smooth interpolants. **yapCAD** represents spline curves as tagged lists so
417
+ ## they can travel through geometry lists and be sampled on demand.
418
+
419
+
420
+ def catmullrom(points, closed=False, alpha=0.5):
421
+ """Return a Catmull-Rom spline definition."""
422
+
423
+ pts = [point(p) for p in points]
424
+ if len(pts) < 2:
425
+ raise ValueError('catmullrom requires at least two control points')
426
+ return ['catmullrom', pts, {'closed': bool(closed), 'alpha': float(alpha)}]
427
+
428
+
429
+ def iscatmullrom(obj):
430
+ """Return ``True`` if *obj* is a Catmull-Rom spline."""
431
+
432
+ return (
433
+ isinstance(obj, list)
434
+ and len(obj) == 3
435
+ and obj[0] == 'catmullrom'
436
+ and isinstance(obj[1], list)
437
+ and isinstance(obj[2], dict)
438
+ )
439
+
440
+
441
+ def nurbs(control_points, *, degree=3, weights=None, knots=None):
442
+ """Return a NURBS curve definition."""
443
+
444
+ pts = [point(p) for p in control_points]
445
+ n = len(pts)
446
+ if n == 0:
447
+ raise ValueError('nurbs requires at least one control point')
448
+ if degree < 1:
449
+ raise ValueError('nurbs degree must be >= 1')
450
+ if n < degree + 1:
451
+ raise ValueError('nurbs requires len(control_points) >= degree + 1')
452
+
453
+ if weights is None:
454
+ wts = [1.0] * n
455
+ else:
456
+ if len(weights) != n:
457
+ raise ValueError('weights must match number of control points')
458
+ wts = [float(w) for w in weights]
459
+
460
+ if knots is None:
461
+ knots = _open_uniform_knot_vector(n, degree)
462
+ else:
463
+ if len(knots) != n + degree + 1:
464
+ raise ValueError('knot vector must have length n + degree + 1')
465
+ knots = [float(k) for k in knots]
466
+
467
+ return ['nurbs', pts, {'degree': int(degree), 'weights': wts, 'knots': knots}]
468
+
469
+
470
+ def isnurbs(obj):
471
+ """Return ``True`` if *obj* is a NURBS curve."""
472
+
473
+ return (
474
+ isinstance(obj, list)
475
+ and len(obj) == 3
476
+ and obj[0] == 'nurbs'
477
+ and isinstance(obj[1], list)
478
+ and isinstance(obj[2], dict)
479
+ )
480
+
481
+
482
+ def _open_uniform_knot_vector(count, degree):
483
+ """Generate an open-uniform knot vector of length ``count + degree + 1``."""
484
+
485
+ length = count + degree + 1
486
+ knots = [0.0] * (degree + 1)
487
+
488
+ interior_knots = count - degree - 1
489
+ if interior_knots > 0:
490
+ denom = count - degree
491
+ for j in range(1, interior_knots + 1):
492
+ knots.append(j / denom)
493
+
494
+ knots.extend([1.0] * (degree + 1))
495
+ return knots[:length]
496
+
497
+
412
498
  from math import *
413
499
  import mpmath as mpm
414
500
  import copy
@@ -2495,6 +2581,8 @@ def intersectGeomListXY(g,gl,inside=True,params=False):
2495
2581
  if gtype == 'glist':
2496
2582
  r = intersectGeomListXY(gl[0],g,inside,params)
2497
2583
  if params:
2584
+ if isinstance(r,bool):
2585
+ return r
2498
2586
  return [ r[1], r[0] ]
2499
2587
  else:
2500
2588
  return r
@@ -2719,6 +2807,12 @@ def sample(x,u):
2719
2807
  return samplearc(x,u)
2720
2808
  elif ispoly(x):
2721
2809
  return samplepoly(x,u)
2810
+ elif iscatmullrom(x):
2811
+ from yapcad.spline import evaluate_catmullrom
2812
+ return evaluate_catmullrom(x, u)
2813
+ elif isnurbs(x):
2814
+ from yapcad.spline import evaluate_nurbs
2815
+ return evaluate_nurbs(x, u)
2722
2816
  elif isgeomlist(x):
2723
2817
  return samplegeomlist(x,u)
2724
2818
  else:
@@ -2742,11 +2836,33 @@ def unsample(x,p):
2742
2836
  return unsamplearc(x,p)
2743
2837
  elif ispoly(x):
2744
2838
  return unsamplepoly(x,p)
2839
+ elif iscatmullrom(x):
2840
+ from yapcad.spline import evaluate_catmullrom
2841
+ return _unsample_curve(x, p, evaluate_catmullrom)
2842
+ elif isnurbs(x):
2843
+ from yapcad.spline import evaluate_nurbs
2844
+ return _unsample_curve(x, p, evaluate_nurbs)
2745
2845
  elif isgeomlist(x):
2746
2846
  return unsamplegeomlist(x,p)
2747
2847
  else:
2748
2848
  raise ValueError("inappropriate type for unasample(): "+str(x))
2749
2849
 
2850
+
2851
+ def _unsample_curve(curve, target, evaluator, *, steps=200):
2852
+ """Return approximate parameter for ``target`` on ``curve`` or ``False``."""
2853
+
2854
+ target = point(target)
2855
+ best_u = 0.0
2856
+ best_d = float('inf')
2857
+ for i in range(steps + 1):
2858
+ u = i / steps
2859
+ sample_pt = evaluator(curve, u)
2860
+ d = dist(sample_pt, target)
2861
+ if d < best_d:
2862
+ best_d = d
2863
+ best_u = u
2864
+ return best_u if best_d <= epsilon * 10 else False
2865
+
2750
2866
  def segment(x,u1,u2):
2751
2867
  """ given a figure x, create a new figure spanning the specified interval in the original figure
2752
2868
  """