Skip to content

Commit f611bab

Browse files
committed
circles
1 parent 52749a7 commit f611bab

1 file changed

Lines changed: 108 additions & 0 deletions

File tree

contributed/circles.rb

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Circles by Bárbara Almeida
2+
# A fork of Circle through 3 points by Bárbara Almeida.
3+
# Draw circles from 3 points moving on smooth random trajectories.
4+
# https://www.openprocessing.org/sketch/211167
5+
6+
# JRubyArt version by Martin Prout
7+
PBisector = Struct.new(:vector, :angle) # perpendicular bisector
8+
Vect = Struct.new(:x, :y, :z) # for calculation of center
9+
10+
def settings
11+
size(800, 400, P2D)
12+
end
13+
14+
def setup
15+
sketch_title 'Circles From Three Moving Points'
16+
color_mode(HSB, 360, 100, 100, 100)
17+
@c = rand(360)
18+
@points = (0..2).map { Point.new(rand(width), rand(height)) }
19+
background 0
20+
end
21+
22+
def draw
23+
fill(0, 0, 0)
24+
noStroke
25+
rect(0, 0, width, height) if (frame_count % 8_000).zero?
26+
@points.each do |point|
27+
# change direction sometimes
28+
point.set_dir rand(-PI..PI) if rand > 0.96
29+
point.update
30+
point.check_edges
31+
end
32+
# set the style of the circle
33+
@dc = map1d(millis, 0..150_000, 0..360) # slowly changes hue
34+
stroke((@c + @dc) % 360, 50, 100, 5)
35+
no_fill
36+
# verifies if there is a circle and draw it
37+
return if collinear(@points[0].pos, @points[1].pos, @points[2].pos)
38+
draw_circle @points
39+
end
40+
41+
def draw_circle(pts)
42+
# find the bisectors of 2 sides
43+
mp = []
44+
mp[0] = bisector(pts[0].pos, pts[1].pos)
45+
mp[1] = bisector(pts[1].pos, pts[2].pos)
46+
center_point = center(mp) # find the center of the circle
47+
# calculate the radius
48+
radius = center_point.dist(pts[2].pos)
49+
# if not collinear display circle
50+
ellipse(center_point.x, center_point.y, 2 * radius, 2 * radius)
51+
end
52+
53+
def bisector(a, b)
54+
midpoint = (a + b) / 2.0 # middle of AB
55+
theta = atan2(b.y - a.y, b.x - a.x) # inclination of AB
56+
PBisector.new(midpoint, theta - HALF_PI)
57+
end
58+
59+
def collinear(a, b, c)
60+
(a - b).cross(b - c).zero?
61+
end
62+
63+
def center(bisector)
64+
# equation of the first bisector (ax - y = -b)
65+
eq = bisector.map do |mp|
66+
a = tan mp.angle
67+
v = mp.vector
68+
Vect.new(a, -1, -1 * (v.y - v.x * a))
69+
end
70+
# calculate x and y coordinates of the circumcenter
71+
ox = (eq[1].y * eq[0].z - eq[0].y * eq[1].z) /
72+
(eq[0].x * eq[1].y - eq[1].x * eq[0].y)
73+
oy = (eq[0].x * eq[1].z - eq[1].x * eq[0].z) /
74+
(eq[0].x * eq[1].y - eq[1].x * eq[0].y)
75+
Vec2D.new(ox,oy)
76+
end
77+
78+
class Point
79+
include Processing::Proxy
80+
attr_accessor :pos, :velocity, :acceleration
81+
82+
def initialize(x, y)
83+
@pos = Vec2D.new(x, y)
84+
@velocity = Vec2D.new
85+
@acceleration = Vec2D.random
86+
end
87+
88+
# change direction
89+
def set_dir(angle)
90+
# direction of the acceleration is defined by the new angle
91+
@acceleration = Vec2D.from_angle(angle)
92+
dif = acceleration.angle_between velocity
93+
dif = map1d(dif, 0..PI, 0.1..0.001)
94+
@acceleration *= dif
95+
end
96+
97+
# update position
98+
def update
99+
@velocity += acceleration
100+
velocity.set_mag(1.5) { velocity.mag > 1.5 } # limit velocity
101+
@pos += velocity
102+
end
103+
104+
def check_edges
105+
pos.x = constrain(pos.x, 0, width)
106+
pos.y = constrain(pos.y, 0, height)
107+
end
108+
end

0 commit comments

Comments
 (0)