Skip to content

Commit 2b4816b

Browse files
committed
lenny explorer
1 parent 1e7a94d commit 2b4816b

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# lenny_explorer.rb
2+
require 'toxiclibs'
3+
java_import 'toxi.geom.Circle'
4+
java_import 'toxi.geom.Rect'
5+
load_library :lenny
6+
7+
attr_reader :path
8+
9+
def settings
10+
size(600, 600)
11+
end
12+
13+
def setup
14+
sketch_title 'Lenny Explorer'
15+
no_fill
16+
# @path = Path.new(
17+
# RectBoundary.new(Rect.new(10, 10, width - 20, height - 20)),
18+
# 10,
19+
# 0.03,
20+
# 3_000
21+
# )
22+
@path = Path.new(
23+
CircularBoundary.new(Circle.new(width / 2, height / 2, 250)),
24+
10,
25+
0.03,
26+
3_000
27+
)
28+
end
29+
30+
def draw
31+
background(255)
32+
50.times { path.grow }
33+
path.render(g)
34+
end
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require_relative 'lib/boundary'
2+
require_relative 'lib/path'
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Duck typing Boundary
2+
class CircularBoundary
3+
attr_reader :circle
4+
5+
def initialize(circle)
6+
@circle = circle
7+
end
8+
9+
def contains_point(vec)
10+
circle.containsPoint(vec)
11+
end
12+
13+
def centroid
14+
circle # Circle can DuckType as Vec2D
15+
end
16+
end
17+
18+
# Duck typing Boundary
19+
class RectBoundary
20+
attr_reader :rectangle
21+
22+
def initialize(rectangle)
23+
@rectangle = rectangle
24+
end
25+
26+
def contains_point(vec)
27+
rectangle.containsPoint(vec)
28+
end
29+
30+
def centroid
31+
rectangle.getCentroid
32+
end
33+
end
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
java_import 'toxi.geom.Line2D'
2+
3+
# Stores and manipulates the path
4+
class Path
5+
attr_reader :path, :last, :bounds, :cut, :theta, :delta, :speed, :searches
6+
7+
def initialize(bounds, speed, delta, history)
8+
@bounds = bounds
9+
@speed = speed
10+
@delta = delta
11+
@theta = 0
12+
@path = (0..history).map { bounds.centroid.copy }
13+
@searches = 0
14+
@last = TVec2D.new(path.first)
15+
end
16+
17+
def grow
18+
@delta = rand(-0.2..0.2) if rand < 0.1
19+
if !intersecting?
20+
move
21+
else
22+
search
23+
end
24+
end
25+
26+
def move
27+
@last = path.first
28+
path.pop
29+
@theta += delta
30+
path.unshift last.add(TVec2D.new(speed, theta).cartesian)
31+
@searches = 0
32+
end
33+
34+
def search
35+
@theta += delta
36+
path[0] = last.add(TVec2D.new(speed, theta).cartesian)
37+
@searches += 1
38+
end
39+
40+
def render(gfx)
41+
gfx.begin_shape
42+
path.map { |vec| gfx.curve_vertex(vec.x, vec.y) }
43+
gfx.end_shape
44+
end
45+
46+
def intersecting?
47+
return true unless bounds.contains_point(path.first)
48+
49+
if searches < 100
50+
a = Line2D.new(path[0], path[1])
51+
(3...path.length).each do |i|
52+
b = Line2D.new(path[i], path[i - 1])
53+
@cut = a.intersect_line(b)
54+
return true if cut.getType == Line2D::LineIntersection::Type::INTERSECTING
55+
end
56+
end
57+
false
58+
end
59+
end

0 commit comments

Comments
 (0)