processing 0.5.32 → 0.5.33

Sign up to get free protection for your applications and to get access to all the features.
@@ -25,6 +25,14 @@ module Processing
25
25
  #
26
26
  TAU = PI * 2
27
27
 
28
+ # Processing mode for renderMode().
29
+ #
30
+ PROCESSING = :processing
31
+
32
+ # p5.js mode for renderMode().
33
+ #
34
+ P5JS = :p5js
35
+
28
36
  # RGBA format for createImage().
29
37
  #
30
38
  RGBA = :rgba
@@ -267,28 +275,42 @@ module Processing
267
275
 
268
276
  # @private
269
277
  def init__(image, painter)
270
- @drawing__ = false
271
- @colorMode__ = nil
272
- @hsbColor__ = false
273
- @colorMaxes__ = [1.0] * 4
274
- @angleMode__ = nil
275
- @angleScale__ = 1.0
276
- @rectMode__ = nil
277
- @ellipseMode__ = nil
278
- @imageMode__ = nil
279
- @shapeMode__ = nil
280
- @blendMode__ = nil
281
- @textAlignH__ = nil
282
- @textAlignV__ = nil
283
- @textFont__ = nil
284
- @tint__ = nil
285
- @filter__ = nil
286
- @pixels__ = nil
287
- @matrixStack__ = []
288
- @styleStack__ = []
278
+ @drawing__ = false
279
+ @renderMode__ = nil
280
+ @p5jsMode__ = false
281
+ @colorMode__ = nil
282
+ @hsbColor__ = false
283
+ @colorMaxes__ = [1.0] * 4
284
+ @angleMode__ = nil
285
+ @toRad__ = 1.0
286
+ @toDeg__ = 1.0
287
+ @fromRad__ = 1.0
288
+ @fromDeg__ = 1.0
289
+ @rectMode__ = nil
290
+ @ellipseMode__ = nil
291
+ @imageMode__ = nil
292
+ @shapeMode__ = nil
293
+ @blendMode__ = nil
294
+ @curveDetail__ = nil
295
+ @curveTightness__ = nil
296
+ @bezierDetail__ = nil
297
+ @textAlignH__ = nil
298
+ @textAlignV__ = nil
299
+ @textFont__ = nil
300
+ @tint__ = nil
301
+ @filter__ = nil
302
+ @pixels__ = nil
303
+ @random__ = nil
304
+ @nextGaussian__ = nil
305
+ @noiseSeed__ = nil
306
+ @noiseOctaves__ = nil
307
+ @noiseFallOff__ = nil
308
+ @matrixStack__ = []
309
+ @styleStack__ = []
289
310
 
290
311
  updateCanvas__ image, painter
291
312
 
313
+ renderMode PROCESSING
292
314
  colorMode RGB, 255
293
315
  angleMode RADIANS
294
316
  rectMode CORNER
@@ -303,10 +325,16 @@ module Processing
303
325
  textureMode IMAGE
304
326
  textureWrap CLAMP
305
327
 
306
- fill 255
307
- stroke 0
308
- strokeWeight 1
328
+ fill 255
329
+ stroke 0
330
+ strokeWeight 1
309
331
  noTint
332
+ curveDetail 20
333
+ curveTightness 0
334
+ bezierDetail 20
335
+ randomSeed Random.new_seed
336
+ noiseSeed Random.new_seed
337
+ noiseDetail 4, 0.5
310
338
  end
311
339
 
312
340
  # @private
@@ -322,6 +350,26 @@ module Processing
322
350
  @matrixStack__.clear
323
351
  @styleStack__.clear
324
352
  @drawing__ = true
353
+ setupMatrix__
354
+ end
355
+
356
+ # @private
357
+ def setupMatrix__()
358
+ w, h = width.to_f, height.to_f
359
+ x, y = w / 2.0, h / 2.0
360
+
361
+ fov, z = nil
362
+ if @p5jsMode__
363
+ z = 800
364
+ fov = degrees Math.atan(y / z) * 2.0
365
+ else
366
+ fov = 60
367
+ z = y / Math.tan(radians(fov) / 2.0)
368
+ end
369
+
370
+ @painter__.matrix =
371
+ Rays::Matrix.perspective(fov, w / h, z / 10.0, z * 10.0) *
372
+ Rays::Matrix.look_at(x, y, z, x, y, 0)
325
373
  end
326
374
 
327
375
  # @private
@@ -370,6 +418,20 @@ module Processing
370
418
  @painter__.pixel_density
371
419
  end
372
420
 
421
+ # Sets render mode.
422
+ #
423
+ # @param mode [PROCESSING, P5JS] compatible to Processing or p5.js
424
+ #
425
+ # @return [PROCESSING, P5JS] current mode
426
+ #
427
+ def renderMode(mode = nil)
428
+ if mode
429
+ @renderMode__ = mode
430
+ @p5jsMode__ = mode == P5JS
431
+ end
432
+ @renderMode__
433
+ end
434
+
373
435
  # Sets color mode and max color values.
374
436
  #
375
437
  # @overload colorMode(mode)
@@ -463,15 +525,48 @@ module Processing
463
525
  ((color >> 24) & 0xff) / 255.0 * @colorMaxes__[3]
464
526
  end
465
527
 
528
+ # Returns the hue value of the color.
529
+ #
530
+ # @param color [Numeric] color value
531
+ #
532
+ # @return [Numeric] the hue value
533
+ #
534
+ def hue(color)
535
+ h, = toRawColor__(color).to_hsv
536
+ h * (@hsbColor__ ? @colorMaxes__[0] : 1)
537
+ end
538
+
539
+ # Returns the saturation value of the color.
540
+ #
541
+ # @param color [Numeric] color value
542
+ #
543
+ # @return [Numeric] the saturation value
544
+ #
545
+ def saturation(color)
546
+ _, s, = toRawColor__(color).to_hsv
547
+ s * (@hsbColor__ ? @colorMaxes__[1] : 1)
548
+ end
549
+
550
+ # Returns the brightness value of the color.
551
+ #
552
+ # @param color [Numeric] color value
553
+ #
554
+ # @return [Numeric] the brightness value
555
+ #
556
+ def brightness(color)
557
+ _, _, b = toRawColor__(color).to_hsv
558
+ b * (@hsbColor__ ? @colorMaxes__[2] : 1)
559
+ end
560
+
466
561
  # @private
467
562
  private def toRGBA__(*args)
468
563
  a, b = args
469
564
  return parseColor__(a, b || alphaMax__) if a.kind_of?(String)
470
- toRaysColor__(*args).to_a
565
+ rawColor__(*args).to_a
471
566
  end
472
567
 
473
568
  # @private
474
- def toRaysColor__(*args)
569
+ def rawColor__(*args)
475
570
  a, b, c, d = args
476
571
  rgba = case args.size
477
572
  when 1, 2 then [a, a, a, b || alphaMax__]
@@ -496,6 +591,15 @@ module Processing
496
591
  @colorMaxes__[3]
497
592
  end
498
593
 
594
+ # @private
595
+ private def toRawColor__(color)
596
+ Rays::Color.new(
597
+ ((color >> 16) & 0xff) / 255.0,
598
+ ((color >> 8) & 0xff) / 255.0,
599
+ ( color & 0xff) / 255.0,
600
+ ((color >> 24) & 0xff) / 255.0)
601
+ end
602
+
499
603
  # Sets angle mode.
500
604
  #
501
605
  # @param mode [RADIANS, DEGREES] RADIANS or DEGREES
@@ -505,37 +609,34 @@ module Processing
505
609
  def angleMode(mode = nil)
506
610
  if mode != nil
507
611
  @angleMode__ = mode
508
- @angleScale__ =
612
+ @toRad__, @toDeg__, @fromRad__, @fromDeg__ =
509
613
  case mode.downcase.to_sym
510
- when RADIANS then RAD2DEG__
511
- when DEGREES then 1.0
614
+ when RADIANS then [1.0, RAD2DEG__, 1.0, DEG2RAD__]
615
+ when DEGREES then [DEG2RAD__, 1.0, RAD2DEG__, 1.0]
512
616
  else raise ArgumentError, "invalid angle mode: #{mode}"
513
617
  end
514
618
  end
515
619
  @angleMode__
516
620
  end
517
621
 
622
+ # @private
623
+ def toRadians__(angle)
624
+ angle * @toRad__
625
+ end
626
+
518
627
  # @private
519
628
  def toDegrees__(angle)
520
- angle * @angleScale__
629
+ angle * @toDeg__
521
630
  end
522
631
 
523
632
  # @private
524
633
  def fromRadians__(radians)
525
- case @angleMode__
526
- when RADIANS then radians
527
- when DEGREES then radians * RAD2DEG__
528
- else raise "invalid angle mode: #{mode}"
529
- end
634
+ radians * @fromRad__
530
635
  end
531
636
 
532
637
  # @private
533
638
  def fromDegrees__(degrees)
534
- case @angleMode__
535
- when RADIANS then degrees * DEG2RAD__
536
- when DEGREES then degrees
537
- else raise "invalid angle mode: #{mode}"
538
- end
639
+ degrees * @fromDeg__
539
640
  end
540
641
 
541
642
  # Sets rect mode. Default is CORNER.
@@ -723,6 +824,52 @@ module Processing
723
824
  nil
724
825
  end
725
826
 
827
+ # Sets the resolution at which curves display.
828
+ # The default value is 20 while the minimum value is 3.
829
+ #
830
+ # @param detail [Numeric] resolution of the curves
831
+ #
832
+ # @return [nil] nil
833
+ #
834
+ # @see https://processing.org/reference/curveDetail_.html
835
+ # @see https://p5js.org/reference/#/p5/curveDetail
836
+ #
837
+ def curveDetail(detail)
838
+ detail = 3 if detail < 3
839
+ @curveDetail__ = detail
840
+ nil
841
+ end
842
+
843
+ # Sets the quality of curve forms.
844
+ #
845
+ # @param tightness [Numeric] determines how the curve fits to the vertex points
846
+ #
847
+ # @return [nil] nil
848
+ #
849
+ # @see https://processing.org/reference/curveTightness_.html
850
+ # @see https://p5js.org/reference/#/p5/curveTightness
851
+ #
852
+ def curveTightness(tightness)
853
+ @curveTightness__ = tightness
854
+ nil
855
+ end
856
+
857
+ # Sets the resolution at which Bezier's curve is displayed.
858
+ # The default value is 20.
859
+ #
860
+ # @param detail [Numeric] resolution of the curves
861
+ #
862
+ # @return [nil] nil
863
+ #
864
+ # @see https://processing.org/reference/bezierDetail_.html
865
+ # @see https://p5js.org/reference/#/p5/bezierDetail
866
+ #
867
+ def bezierDetail(detail)
868
+ detail = 1 if detail < 1
869
+ @bezierDetail__ = detail
870
+ nil
871
+ end
872
+
726
873
  # Sets fill color for drawing images.
727
874
  #
728
875
  # @overload tint(rgb)
@@ -786,30 +933,32 @@ module Processing
786
933
  end
787
934
 
788
935
  # Sets text font.
789
- #
790
936
  # (Passing a font name as the first parameter is deprecated)
791
937
  #
938
+ # @overload textFont()
792
939
  # @overload textFont(font)
793
- # @overload textFont(name)
940
+ # @overload textFont(name) [DEPRECATED]
794
941
  # @overload textFont(font, size)
795
- # @overload textFont(name, size)
942
+ # @overload textFont(name, size) [DEPRECATED]
796
943
  #
797
944
  # @param font [Font] font
798
945
  # @param name [String] font name
799
946
  # @param size [Numeric] font size (max 256)
800
947
  #
801
- # @return [nil] nil
948
+ # @return [Font] current font
802
949
  #
803
- def textFont(font, size = nil)
804
- size = FONT_SIZE_MAX__ if size && size > FONT_SIZE_MAX__
805
- if font.nil? || font.kind_of?(String)
806
- font = createFont font, size
807
- elsif size
808
- font.setSize__ size
950
+ def textFont(font = nil, size = nil)
951
+ if font != nil || size != nil
952
+ size = FONT_SIZE_MAX__ if size && size > FONT_SIZE_MAX__
953
+ if font.nil? || font.kind_of?(String)
954
+ font = createFont font, size
955
+ elsif size
956
+ font.setSize__ size
957
+ end
958
+ @painter__.font = font.getInternal__
959
+ @textFont__ = font
809
960
  end
810
- @textFont__ = font
811
- @painter__.font = font.getInternal__
812
- nil
961
+ @textFont__
813
962
  end
814
963
 
815
964
  # Sets text size.
@@ -839,6 +988,20 @@ module Processing
839
988
  @textAlignV__ = vertical
840
989
  end
841
990
 
991
+ # Sets the spacing between lines of text in units of pixels.
992
+ #
993
+ # @overload textLeading()
994
+ # @overload textLeading(leading)
995
+ #
996
+ # @param leading [Numeric] the size in pixels for spacing between lines
997
+ #
998
+ # @return [Numeric] current spacing
999
+ #
1000
+ def textLeading(leading = nil)
1001
+ @painter__.line_height = leading if leading
1002
+ @painter__.line_height
1003
+ end
1004
+
842
1005
  def texture(image)
843
1006
  @painter__.texture image&.getInternal__
844
1007
  nil
@@ -961,7 +1124,7 @@ module Processing
961
1124
  #
962
1125
  def point(x, y)
963
1126
  assertDrawing__
964
- @painter__.line x, y, x, y
1127
+ @painter__.point x, y
965
1128
  nil
966
1129
  end
967
1130
 
@@ -1144,7 +1307,9 @@ module Processing
1144
1307
  #
1145
1308
  def curve(cx1, cy1, x1, y1, x2, y2, cx2, cy2)
1146
1309
  assertDrawing__
1310
+ @painter__.nsegment = @curveDetail__
1147
1311
  @painter__.curve cx1, cy1, x1, y1, x2, y2, cx2, cy2
1312
+ @painter__.nsegment = 0
1148
1313
  nil
1149
1314
  end
1150
1315
 
@@ -1165,7 +1330,9 @@ module Processing
1165
1330
  #
1166
1331
  def bezier(x1, y1, cx1, cy1, cx2, cy2, x2, y2)
1167
1332
  assertDrawing__
1333
+ @painter__.nsegment = @bezierDetail__
1168
1334
  @painter__.bezier x1, y1, cx1, cy1, cx2, cy2, x2, y2
1335
+ @painter__.nsegment = 0
1169
1336
  nil
1170
1337
  end
1171
1338
 
@@ -1478,9 +1645,16 @@ module Processing
1478
1645
  #
1479
1646
  # @return [nil] nil
1480
1647
  #
1481
- def updatePixels()
1482
- return unless @pixels__
1483
- getInternal__.pixels = @pixels__
1648
+ def updatePixels(&block)
1649
+ return if !block && !@pixels__
1650
+ if block
1651
+ loadPixels
1652
+ block.call pixels
1653
+ end
1654
+ getInternal__.tap do |img|
1655
+ img.pixels = @pixels__
1656
+ img.paint {} # update texture and set modifiied
1657
+ end
1484
1658
  @pixels__ = nil
1485
1659
  end
1486
1660
 
@@ -1548,6 +1722,42 @@ module Processing
1548
1722
  nil
1549
1723
  end
1550
1724
 
1725
+ def rotateX(angle)
1726
+ assertDrawing__
1727
+ @painter__.rotate toDegrees__(angle), 1, 0, 0
1728
+ nil
1729
+ end
1730
+
1731
+ def rotateY(angle)
1732
+ assertDrawing__
1733
+ @painter__.rotate toDegrees__(angle), 0, 1, 0
1734
+ nil
1735
+ end
1736
+
1737
+ def rotateZ(angle)
1738
+ assertDrawing__
1739
+ @painter__.rotate toDegrees__(angle), 0, 0, 1
1740
+ nil
1741
+ end
1742
+
1743
+ def shearX(angle)
1744
+ t = Math.tan toRadians__(angle)
1745
+ @painter__.matrix *= Rays::Matrix.new(
1746
+ 1, t, 0, 0,
1747
+ 0, 1, 0, 0,
1748
+ 0, 0, 1, 0,
1749
+ 0, 0, 0, 1)
1750
+ end
1751
+
1752
+ def shearY(angle)
1753
+ t = Math.tan toRadians__(angle)
1754
+ @painter__.matrix *= Rays::Matrix.new(
1755
+ 1, 0, 0, 0,
1756
+ t, 1, 0, 0,
1757
+ 0, 0, 1, 0,
1758
+ 0, 0, 0, 1)
1759
+ end
1760
+
1551
1761
  # Pushes the current transformation matrix to stack.
1552
1762
  #
1553
1763
  # @return [Object] result of the expression at the end of the block
@@ -1571,6 +1781,51 @@ module Processing
1571
1781
  nil
1572
1782
  end
1573
1783
 
1784
+ # Reset current transformation matrix with 2x3, or 4x4 matrix.
1785
+ #
1786
+ # @overload applyMatrix(array)
1787
+ # @overload applyMatrix(a, b, c, d, e, f)
1788
+ # @overload applyMatrix(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
1789
+ #
1790
+ # @param array [Array] 6 or 16 numbers which define the matrix
1791
+ # @param a [Numeric] number which defines the matrix
1792
+ # @param b [Numeric] number which defines the matrix
1793
+ # @param c [Numeric] number which defines the matrix
1794
+ # @param d [Numeric] number which defines the matrix
1795
+ # @param e [Numeric] number which defines the matrix
1796
+ # @param f [Numeric] number which defines the matrix
1797
+ # @param g [Numeric] number which defines the matrix
1798
+ # @param h [Numeric] number which defines the matrix
1799
+ # @param i [Numeric] number which defines the matrix
1800
+ # @param j [Numeric] number which defines the matrix
1801
+ # @param k [Numeric] number which defines the matrix
1802
+ # @param l [Numeric] number which defines the matrix
1803
+ # @param m [Numeric] number which defines the matrix
1804
+ # @param n [Numeric] number which defines the matrix
1805
+ # @param o [Numeric] number which defines the matrix
1806
+ # @param p [Numeric] number which defines the matrix
1807
+ #
1808
+ # @return [nil] nil
1809
+ #
1810
+ def applyMatrix(*args)
1811
+ assertDrawing__
1812
+ args = args.first if args.first.kind_of?(Array)
1813
+ if args.size == 6
1814
+ a, b, c, d, e, f = args
1815
+ args = [
1816
+ a, b, 0, 0,
1817
+ c, d, 0, 0,
1818
+ 0, 0, 1, 0,
1819
+ e, f, 0, 1
1820
+ ]
1821
+ end
1822
+ raise ArgumentError unless args.size == 16
1823
+ m = Rays::Matrix.new(*args)
1824
+ m.transpose! if @p5jsMode__
1825
+ @painter__.matrix *= m
1826
+ nil
1827
+ end
1828
+
1574
1829
  # Reset current transformation matrix with identity matrix.
1575
1830
  #
1576
1831
  # @return [nil] nil
@@ -1581,6 +1836,17 @@ module Processing
1581
1836
  nil
1582
1837
  end
1583
1838
 
1839
+ # Prints matrix elements to console.
1840
+ #
1841
+ # @return [nil] nil
1842
+ #
1843
+ def printMatrix()
1844
+ m = @painter__.matrix
1845
+ m.transpose! if @p5jsMode__
1846
+ print "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n" % m.to_a
1847
+ nil
1848
+ end
1849
+
1584
1850
  # Save current style values to the style stack.
1585
1851
  #
1586
1852
  # @return [Object] result of the expression at the end of the block
@@ -1593,6 +1859,8 @@ module Processing
1593
1859
  @painter__.stroke_width,
1594
1860
  @painter__.stroke_cap,
1595
1861
  @painter__.stroke_join,
1862
+ @painter__.miter_limit,
1863
+ @painter__.line_height!,
1596
1864
  @painter__.clip,
1597
1865
  @painter__.blend_mode,
1598
1866
  @painter__.font,
@@ -1600,13 +1868,22 @@ module Processing
1600
1868
  @painter__.texcoord_mode,
1601
1869
  @painter__.texcoord_wrap,
1602
1870
  @painter__.shader,
1871
+ @colorMode__,
1603
1872
  @hsbColor__,
1604
1873
  @colorMaxes__,
1605
- @angleScale__,
1874
+ @angleMode__,
1875
+ @toRad__,
1876
+ @toDeg__,
1877
+ @fromRad__,
1878
+ @fromDeg__,
1606
1879
  @rectMode__,
1607
1880
  @ellipseMode__,
1608
1881
  @imageMode__,
1609
1882
  @shapeMode__,
1883
+ @blendMode__,
1884
+ @curveDetail__,
1885
+ @curveTightness__,
1886
+ @bezierDetail__,
1610
1887
  @textAlignH__,
1611
1888
  @textAlignV__,
1612
1889
  @textFont__,
@@ -1629,6 +1906,8 @@ module Processing
1629
1906
  @painter__.stroke_width,
1630
1907
  @painter__.stroke_cap,
1631
1908
  @painter__.stroke_join,
1909
+ @painter__.miter_limit,
1910
+ @painter__.line_height,
1632
1911
  @painter__.clip,
1633
1912
  @painter__.blend_mode,
1634
1913
  @painter__.font,
@@ -1636,13 +1915,22 @@ module Processing
1636
1915
  @painter__.texcoord_mode,
1637
1916
  @painter__.texcoord_wrap,
1638
1917
  @painter__.shader,
1918
+ @colorMode__,
1639
1919
  @hsbColor__,
1640
1920
  @colorMaxes__,
1641
- @angleScale__,
1921
+ @angleMode__,
1922
+ @toRad__,
1923
+ @toDeg__,
1924
+ @fromRad__,
1925
+ @fromDeg__,
1642
1926
  @rectMode__,
1643
1927
  @ellipseMode__,
1644
1928
  @imageMode__,
1645
1929
  @shapeMode__,
1930
+ @blendMode__,
1931
+ @curveDetail__,
1932
+ @curveTightness__,
1933
+ @bezierDetail__,
1646
1934
  @textAlignH__,
1647
1935
  @textAlignV__,
1648
1936
  @textFont__,
@@ -1678,10 +1966,10 @@ module Processing
1678
1966
  end
1679
1967
 
1680
1968
  # @private
1681
- def drawImage__(painter, *args, **states)
1969
+ def drawImage__(painter, *args, image__: getInternal__, **states)
1682
1970
  shader = painter.shader || @filter__&.getInternal__
1683
1971
  painter.push shader: shader, **states do |_|
1684
- painter.image getInternal__, *args
1972
+ painter.image image__, *args
1685
1973
  end
1686
1974
  end
1687
1975
 
@@ -2024,6 +2312,98 @@ module Processing
2024
2312
  Math.atan2 y, x
2025
2313
  end
2026
2314
 
2315
+ # Evaluates the curve at point t for points a, b, c, d.
2316
+ #
2317
+ # @param a [Numeric] coordinate of first control point
2318
+ # @param b [Numeric] coordinate of first point on the curve
2319
+ # @param c [Numeric] coordinate of second point on the curve
2320
+ # @param d [Numeric] coordinate of second control point
2321
+ # @param t [Numeric] value between 0.0 and 1.0
2322
+ #
2323
+ # @return [Numeric] interpolated value
2324
+ #
2325
+ # @see https://processing.org/reference/curvePoint_.html
2326
+ # @see https://p5js.org/reference/#/p5/curvePoint
2327
+ #
2328
+ def curvePoint(a, b, c, d, t)
2329
+ s = @curveTightness__
2330
+ t3 = t * t * t
2331
+ t2 = t * t
2332
+ f1 = ( s - 1.0) / 2.0 * t3 + ( 1.0 - s) * t2 + (s - 1.0) / 2.0 * t
2333
+ f2 = ( s + 3.0) / 2.0 * t3 + (-5.0 - s) / 2.0 * t2 + 1.0
2334
+ f3 = (-3.0 - s) / 2.0 * t3 + ( s + 2.0) * t2 + (1.0 - s) / 2.0 * t
2335
+ f4 = ( 1.0 - s) / 2.0 * t3 + ( s - 1.0) / 2.0 * t2
2336
+ a * f1 + b * f2 + c * f3 + d * f4
2337
+ end
2338
+
2339
+ # Calculates the tangent of a point on a curve.
2340
+ #
2341
+ # @param a [Numeric] coordinate of first control point
2342
+ # @param b [Numeric] coordinate of first point on the curve
2343
+ # @param c [Numeric] coordinate of second point on the curve
2344
+ # @param d [Numeric] coordinate of second control point
2345
+ # @param t [Numeric] value between 0.0 and 1.0
2346
+ #
2347
+ # @return [Numeric] tangent value
2348
+ #
2349
+ # @see https://processing.org/reference/curveTangent_.html
2350
+ # @see https://p5js.org/reference/#/p5/curveTangent
2351
+ #
2352
+ def curveTangent(a, b, c, d, t)
2353
+ s = @curveTightness__
2354
+ tt3 = t * t * 3.0
2355
+ t2 = t * 2.0
2356
+ f1 = ( s - 1.0) / 2.0 * tt3 + ( 1.0 - s) * t2 + (s - 1.0) / 2.0
2357
+ f2 = ( s + 3.0) / 2.0 * tt3 + (-5.0 - s) / 2.0 * t2
2358
+ f3 = (-3.0 - s) / 2.0 * tt3 + ( s + 2.0) * t2 + (1.0 - s) / 2.0
2359
+ f4 = ( 1.0 - s) / 2.0 * tt3 + ( s - 1.0) / 2.0 * t2
2360
+ a * f1 + b * f2 + c * f3 + d * f4
2361
+ end
2362
+
2363
+ # Evaluates the Bezier at point t for points a, b, c, d.
2364
+ #
2365
+ # @param a [Numeric] coordinate of first point on the curve
2366
+ # @param b [Numeric] coordinate of first control point
2367
+ # @param c [Numeric] coordinate of second control point
2368
+ # @param d [Numeric] coordinate of second point on the curve
2369
+ # @param t [Numeric] value between 0.0 and 1.0
2370
+ #
2371
+ # @return [Numeric] interpolated value
2372
+ #
2373
+ # @see https://processing.org/reference/bezierPoint_.html
2374
+ # @see https://p5js.org/reference/#/p5/bezierPoint
2375
+ #
2376
+ def bezierPoint(a, b, c, d, t)
2377
+ tt = 1.0 - t
2378
+ tt ** 3.0 * a +
2379
+ tt ** 2.0 * b * 3.0 * t +
2380
+ t ** 2.0 * c * 3.0 * tt +
2381
+ t ** 3.0 * d
2382
+ end
2383
+
2384
+ # Calculates the tangent of a point on a Bezier curve.
2385
+ #
2386
+ # @param a [Numeric] coordinate of first point on the curve
2387
+ # @param b [Numeric] coordinate of first control point
2388
+ # @param c [Numeric] coordinate of second control point
2389
+ # @param d [Numeric] coordinate of second point on the curve
2390
+ # @param t [Numeric] value between 0.0 and 1.0
2391
+ #
2392
+ # @return [Numeric] tangent value
2393
+ #
2394
+ # @see https://processing.org/reference/bezierTangent_.html
2395
+ # @see https://p5js.org/reference/#/p5/bezierTangent
2396
+ #
2397
+ def bezierTangent(a, b, c, d, t)
2398
+ tt = 1.0 - t
2399
+ 3.0 * d * t ** 2.0 -
2400
+ 3.0 * c * t ** 2.0 +
2401
+ 6.0 * c * tt * t -
2402
+ 6.0 * b * tt * t +
2403
+ 3.0 * b * tt ** 2.0 -
2404
+ 3.0 * a * tt ** 2.0
2405
+ end
2406
+
2027
2407
  # Returns the perlin noise value.
2028
2408
  #
2029
2409
  # @overload noise(x)
@@ -2036,13 +2416,52 @@ module Processing
2036
2416
  #
2037
2417
  # @return [Numeric] noise value (0.0..1.0)
2038
2418
  #
2419
+ # @see https://processing.org/reference/noise_.html
2420
+ # @see https://p5js.org/reference/#/p5/noise
2421
+ #
2039
2422
  def noise(x, y = 0, z = 0)
2040
- Rays.perlin(x, y, z) / 2.0 + 0.5
2423
+ seed, falloff = @noiseSeed__, @noiseFallOff__
2424
+ amp = 0.5
2425
+ @noiseOctaves__.times.reduce(0) do |sum|
2426
+ value = (Rays.perlin(x, y, z, seed) / 2.0 + 0.5) * amp
2427
+ x *= 2
2428
+ y *= 2
2429
+ z *= 2
2430
+ amp *= falloff
2431
+ sum + value
2432
+ end
2433
+ end
2434
+
2435
+ # Sets the seed value for noise()
2436
+ #
2437
+ # @param seed [Numeric] seed value
2438
+ #
2439
+ # @return [nil] nil
2440
+ #
2441
+ # @see https://processing.org/reference/noiseSeed_.html
2442
+ # @see https://p5js.org/reference/#/p5/noiseSeed
2443
+ #
2444
+ def noiseSeed(seed)
2445
+ @noiseSeed__ = Random.new(seed).rand 0.0..1.0
2446
+ end
2447
+
2448
+ # Adjusts the character and level of detail produced by the Perlin noise function.
2449
+ #
2450
+ # @param lod [Numeric] number of octaves to be used by the noise
2451
+ # @param falloff [Numeric] falloff factor for each octave
2452
+ #
2453
+ # @return [nil] nil
2454
+ #
2455
+ # @see https://processing.org/reference/noiseDetail_.html
2456
+ # @see https://p5js.org/reference/#/p5/noiseDetail
2457
+ #
2458
+ def noiseDetail(lod, falloff = nil)
2459
+ @noiseOctaves__ = lod if lod && lod > 0
2460
+ @noiseFallOff__ = falloff if falloff && falloff > 0
2041
2461
  end
2042
2462
 
2043
2463
  # Returns a random number in range low...high
2044
2464
  #
2045
- # @overload random()
2046
2465
  # @overload random(high)
2047
2466
  # @overload random(low, high)
2048
2467
  # @overload random(choices)
@@ -2053,10 +2472,60 @@ module Processing
2053
2472
  #
2054
2473
  # @return [Float] random number
2055
2474
  #
2475
+ # @see https://processing.org/reference/random_.html
2476
+ # @see https://p5js.org/reference/#/p5/random
2477
+ #
2056
2478
  def random(*args)
2057
- return args.first.sample if args.first.kind_of? Array
2058
- high, low = args.reverse
2059
- rand (low || 0).to_f...(high || 1).to_f
2479
+ if args.first.kind_of? Array
2480
+ a = args.first
2481
+ a.empty? ? nil : a[@random__.rand a.size]
2482
+ else
2483
+ high, low = args.reverse
2484
+ @random__.rand (low || 0).to_f...(high || 1).to_f
2485
+ end
2486
+ end
2487
+
2488
+ # Sets the seed value for random()
2489
+ #
2490
+ # @param seed [Numeric] seed value
2491
+ #
2492
+ # @return [nil] nil
2493
+ #
2494
+ # @see https://processing.org/reference/randomSeed_.html
2495
+ # @see https://p5js.org/reference/#/p5/randomSeed
2496
+ #
2497
+ def randomSeed(seed)
2498
+ @random__ = Random.new seed
2499
+ @nextGaussian__ = nil
2500
+ end
2501
+
2502
+ # Returns a random number fitting a Gaussian, or normal, distribution.
2503
+ #
2504
+ # @param mean [Numeric] mean
2505
+ # @param sd [Numeric] standard deviation
2506
+ #
2507
+ # @return [Float] random number
2508
+ #
2509
+ # @see https://processing.org/reference/randomGaussian_.html
2510
+ # @see https://p5js.org/reference/#/p5/randomGaussian
2511
+ #
2512
+ def randomGaussian(mean = 0, sd = 1)
2513
+ value =
2514
+ if @nextGaussian__
2515
+ x, @nextGaussian__ = @nextGaussian__, nil
2516
+ x
2517
+ else
2518
+ a, b, w = 0, 0, 1
2519
+ until w < 1
2520
+ a = random(2) - 1
2521
+ b = random(2) - 1
2522
+ w = a ** 2 + b ** 2
2523
+ end
2524
+ w = Math.sqrt(-2 * Math.log(w) / w)
2525
+ @randomGaussian__ = a * w
2526
+ b * w
2527
+ end
2528
+ value * sd + mean
2060
2529
  end
2061
2530
 
2062
2531
  # Creates a new vector object.
@@ -2235,7 +2704,7 @@ module Processing
2235
2704
  raise "unsupported font type -- '#{ext}'" unless ext =~ /^\.?(ttf|otf)$/i
2236
2705
 
2237
2706
  filename = httpGet__ filename, ext if filename =~ %r|^https?://|
2238
- Font.new Rays::Font.load p filename
2707
+ Font.new Rays::Font.load filename
2239
2708
  end
2240
2709
 
2241
2710
  # Loads image.
@@ -2299,15 +2768,10 @@ module Processing
2299
2768
  path = path.sub_ext ext
2300
2769
 
2301
2770
  unless path.file?
2302
- URI.open uri do |input|
2303
- input.set_encoding nil# disable default_internal
2771
+ Net::HTTP.get_response URI.parse(uri) do |res|
2772
+ res.value # raise an error unless successful
2304
2773
  tmpdir.mkdir unless tmpdir.directory?
2305
- path.open('w') do |output|
2306
- output.set_encoding Encoding::ASCII_8BIT
2307
- while buf = input.read(2 ** 16)
2308
- output.write buf
2309
- end
2310
- end
2774
+ path.open('wb') {|file| res.read_body {|body| file.write body}}
2311
2775
  end
2312
2776
  end
2313
2777
  path.to_s