Skip to content

Commit 1678d5b

Browse files
author
PSvils
committed
Initial commit - working implementations of L-Systems and DLAs.
1 parent 4b6f469 commit 1678d5b

13 files changed

+856
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/test/progen-test/bin

progen/dla/DLA.hx

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package progen.dla;
2+
import progen.dla.bounds.IBounds;
3+
4+
/**
5+
* DLA for generating weird structures of segments and points.
6+
* @author P Svilans
7+
*/
8+
9+
class DLA
10+
{
11+
12+
/**
13+
* The number of active points in the simulation.
14+
*/
15+
public var points:Array<DLAPoint>;
16+
17+
/**
18+
* Generated segments from the simulation.
19+
*/
20+
public var segments:Array<DLASegment>;
21+
22+
public var origin:IBounds;
23+
public var target:IBounds;
24+
25+
public var gravity:Float = 1.0;
26+
public var threshold:Float;
27+
public var motion:DLAPoint;
28+
29+
/**
30+
* Creates a DLA with the given origin and target bounds. Points will be spawned along the origin bound,
31+
* and will freeze once they come in range of the target bound. All generated segments are guaranteed to
32+
* be interconnected with one another (no islands).
33+
* @param origin Origin bound on which to spawn points.
34+
* @param target Bound that freezes points on contact.
35+
*/
36+
public function new(origin:IBounds, target:IBounds, gravity:Float = 1.0, threshold:Float = 10.0, motion:DLAPoint = null)
37+
{
38+
this.origin = origin;
39+
this.target = target;
40+
41+
this.gravity = gravity;
42+
this.threshold = threshold;
43+
this.motion = (motion != null) ? motion : new DLAPoint(10.0, 10.0);
44+
}
45+
46+
/**
47+
* Simulate a certain number of points to construct the DLA.
48+
* @param amount The amount of points to simulate.
49+
* @param iterations How many iterations before terminating.
50+
* @return If all points have been frozen, returns true. If some point haven't stuck to the DLA yet, returns false.
51+
*/
52+
public function construct(amount:Int = 500, iterations:Int = 1000):Bool
53+
{
54+
var joined:Array<DLAPoint> = new Array<DLAPoint>();
55+
points = [];
56+
segments = [];
57+
58+
for (i in 0...amount) points.push(origin.create(Math.random()));
59+
60+
for (i in 0...iterations)
61+
{
62+
for (point in points)
63+
{
64+
var d = target.distanceToBound(point);
65+
var o = target.getClosestVector(point);
66+
67+
point.x += o.x * gravity + Math.random() * motion.x - motion.x * 0.5;
68+
point.y += o.y * gravity + Math.random() * motion.y - motion.y * 0.5;
69+
70+
var minimumDistance:Float = Math.min(d * d + 1, threshold * threshold);
71+
var minimumPoint:DLAPoint = null;
72+
73+
for (set in joined)
74+
{
75+
var d = set.distance_2(point);
76+
77+
if (d < minimumDistance)
78+
{
79+
minimumDistance = d;
80+
minimumPoint = set;
81+
}
82+
}
83+
84+
if (minimumDistance < threshold * threshold && (minimumPoint != null || joined.length == 0))
85+
{
86+
point.isSet = true;
87+
88+
points.remove(point);
89+
joined.push(point);
90+
}
91+
92+
if (minimumPoint != null) segments.push(new DLASegment(point, minimumPoint));
93+
}
94+
95+
if (points.length == 0) return true;
96+
}
97+
98+
return false;
99+
}
100+
101+
}

progen/dla/DLAPoint.hx

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package progen.dla;
2+
3+
/**
4+
* Simple Point class to hold x/y values and attached segments.
5+
* @author P Svilans
6+
*/
7+
8+
class DLAPoint
9+
{
10+
11+
public var isSet:Bool;
12+
13+
public var x:Float;
14+
public var y:Float;
15+
16+
public var segments:Array<DLASegment>;
17+
18+
public function new(x:Float = 0.0, y:Float = 0.0)
19+
{
20+
this.x = x;
21+
this.y = y;
22+
23+
segments = new Array<DLASegment>();
24+
25+
isSet = false;
26+
}
27+
28+
/**
29+
* Finds the distance between this and another point.
30+
* @param point
31+
* @return The distance - surprise! :O
32+
*/
33+
public inline function distance(point:DLAPoint):Float
34+
{
35+
return Math.sqrt(distance_2( point));
36+
}
37+
38+
/**
39+
* Finds the distance squared between this and another point.
40+
* @param point
41+
* @return
42+
*/
43+
public inline function distance_2(point:DLAPoint):Float
44+
{
45+
var dx:Float = point.x - this.x;
46+
var dy:Float = point.y - this.y;
47+
48+
return dx * dx + dy * dy;
49+
}
50+
51+
/**
52+
* Clones this point.
53+
* @return
54+
*/
55+
public inline function clone():DLAPoint
56+
{
57+
return new DLAPoint(x, y);
58+
}
59+
60+
public function destroy():Void
61+
{
62+
for (segment in segments) segment.destroy();
63+
}
64+
65+
}

progen/dla/DLASegment.hx

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package progen.dla;
2+
3+
/**
4+
* A segment joining 2 points.
5+
* @author P Svilans
6+
*/
7+
8+
class DLASegment
9+
{
10+
11+
public var a:DLAPoint;
12+
public var b:DLAPoint;
13+
14+
public function new(a:DLAPoint, b:DLAPoint)
15+
{
16+
this.a = a;
17+
a.segments.push( this);
18+
19+
this.b = b;
20+
b.segments.push( this);
21+
}
22+
23+
public function destroy():Void
24+
{
25+
a.segments.remove( this);
26+
b.segments.remove( this);
27+
28+
a = null;
29+
b = null;
30+
}
31+
32+
}

progen/dla/bounds/CircleBounds.hx

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package progen.dla.bounds;
2+
import progen.dla.DLAPoint;
3+
4+
/**
5+
* ...
6+
* @author P Svilans
7+
*/
8+
9+
class CircleBounds extends DLAPoint implements IBounds
10+
{
11+
12+
public var gravity:Float;
13+
public var radius:Float;
14+
15+
public function new(radius:Float, x:Float = 0.0, y:Float = 0.0, gravity:Float = 1.0)
16+
{
17+
super(x, y);
18+
19+
this.gravity = gravity;
20+
this.radius = radius;
21+
}
22+
23+
/* INTERFACE progen.dla.bounds.IBounds */
24+
25+
public function center():DLAPoint
26+
{
27+
return this;
28+
}
29+
30+
public function create(t:Float):DLAPoint
31+
{
32+
var rads:Float = t * Math.PI * 2;
33+
34+
return new DLAPoint(Math.cos(rads) * radius + x, Math.sin(rads) * radius + y);
35+
}
36+
37+
public function getClosestVector(point:DLAPoint):DLAPoint
38+
{
39+
var dx = x - point.x;
40+
var dy = y - point.y;
41+
var d = Math.sqrt(dx * dx + dy * dy);
42+
dx = dx / d;
43+
dy = dy / d;
44+
45+
if (isWithinBounds(point)) return new DLAPoint(-dx * gravity, -dy * gravity);
46+
else return new DLAPoint(dx * gravity, dy * gravity);
47+
}
48+
49+
public function distanceToBound(point:DLAPoint):Float
50+
{
51+
var d = distance(point);
52+
53+
return radius - d;
54+
}
55+
56+
public function isWithinBounds(point:DLAPoint):Bool
57+
{
58+
var d = distance_2(point);
59+
if (d < radius * radius) return true;
60+
return false;
61+
}
62+
63+
}

progen/dla/bounds/IBounds.hx

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package progen.dla.bounds;
2+
import progen.dla.DLAPoint;
3+
4+
/**
5+
* ...
6+
* @author P Svilans
7+
*/
8+
9+
interface IBounds
10+
{
11+
12+
public var gravity:Float;
13+
14+
/**
15+
* Gets the center coordinates of the bound.
16+
* @return Center point.
17+
*/
18+
public function center():DLAPoint;
19+
20+
/**
21+
* Creates a point on the perimeter of this bound.
22+
* @param t 0.0 - 1.0 - distance along the bound on which to generate the point.
23+
* @return The point created.
24+
*/
25+
public function create(t:Float):DLAPoint;
26+
27+
public function getClosestVector(point:DLAPoint):DLAPoint;
28+
public function distanceToBound(point:DLAPoint):Float;
29+
public function isWithinBounds(point:DLAPoint):Bool;
30+
31+
}

progen/dla/bounds/PointBounds.hx

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package progen.dla.bounds;
2+
import progen.dla.DLAPoint;
3+
4+
/**
5+
* ...
6+
* @author P Svilans
7+
*/
8+
9+
class PointBounds extends DLAPoint implements IBounds
10+
{
11+
12+
public var gravity:Float;
13+
14+
public function new(x:Float = 0.0, y:Float = 0.0, gravity:Float = 1.0)
15+
{
16+
super(x, y);
17+
18+
this.gravity = gravity;
19+
}
20+
21+
/* INTERFACE progen.dla.bounds.IBounds */
22+
23+
public function center():DLAPoint
24+
{
25+
return this;
26+
}
27+
28+
public function create(t:Float):DLAPoint
29+
{
30+
return new DLAPoint(x, y);
31+
}
32+
33+
public function getClosestVector(point:DLAPoint):DLAPoint
34+
{
35+
var dx = x - point.x;
36+
var dy = y - point.y;
37+
var d = Math.sqrt( dx * dx + dy * dy);
38+
dx = dx / d;
39+
dy = dy / d;
40+
41+
return new DLAPoint(dx * gravity, dy * gravity);
42+
}
43+
44+
public function distanceToBound(point:DLAPoint):Float
45+
{
46+
return distance(point);
47+
}
48+
49+
public function isWithinBounds(point:DLAPoint):Bool
50+
{
51+
return false;
52+
}
53+
54+
}

0 commit comments

Comments
 (0)