mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-01 02:38:43 -05:00
Add port of Metaball script by Hiroyuki Sato to Examples.
This commit is contained in:
parent
357e6f2db8
commit
877e9f324c
1 changed files with 116 additions and 0 deletions
116
examples/Tools/MetaBalls.html
Normal file
116
examples/Tools/MetaBalls.html
Normal file
|
@ -0,0 +1,116 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Example</title>
|
||||
<script type="text/javascript">var root = '../../'</script>
|
||||
<script type="text/javascript" src="../../src/load.js"></script>
|
||||
<script type="text/paperscript" canvas="canvas">
|
||||
// Ported from original Metaball script by SATO Hiroyuki
|
||||
// http://park12.wakwak.com/~shp/lc/et/en_aics_script.html
|
||||
document.currentStyle = {
|
||||
fillColor: 'black'
|
||||
};
|
||||
|
||||
var handle_len_rate = 2.4,
|
||||
circlePaths = [],
|
||||
circlePath,
|
||||
radius = 50;
|
||||
circlePaths.push(new Path.Circle(document.bounds.center, 100));
|
||||
function onMouseDown(event) {
|
||||
circlePath = null;
|
||||
for (var i = 0, l = circlePaths.length; i < l; i++) {
|
||||
var path = circlePaths[i];
|
||||
if (path.position.getDistance(event.point) < 50)
|
||||
circlePath = path;
|
||||
}
|
||||
if (!circlePath) {
|
||||
circlePath = new Path.Circle(event.point, 50);
|
||||
circlePaths.push(circlePath);
|
||||
}
|
||||
generateConnections(circlePaths);
|
||||
}
|
||||
|
||||
function onMouseDrag(event) {
|
||||
circlePath.position = event.point;
|
||||
generateConnections(circlePaths);
|
||||
}
|
||||
|
||||
function generateConnections(paths) {
|
||||
for (var i = 0, l = paths.length; i < l; i++) {
|
||||
for(var j = i - 1; j >= 0; j--){
|
||||
var path = metaball(paths[i], paths[j], 0.5, handle_len_rate, 300);
|
||||
if (path) {
|
||||
path.removeOn({
|
||||
drag: true,
|
||||
down: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------
|
||||
function metaball(ball1, ball2, v, handle_len_rate, maxDistance){
|
||||
var center1 = ball1.position,
|
||||
center2 = ball2.position,
|
||||
radius1 = ball1.bounds.width / 2,
|
||||
radius2 = ball2.bounds.width / 2,
|
||||
pi2 = Math.PI / 2,
|
||||
d = center1.getDistance(center2),
|
||||
u1, u2;
|
||||
|
||||
if (radius1 == 0 || radius2 == 0)
|
||||
return;
|
||||
|
||||
if(d > maxDistance || d <= Math.abs(radius1 - radius2)) {
|
||||
return;
|
||||
} else if (d < radius1 + radius2) { // case circles are overlapping
|
||||
u1 = Math.acos((radius1 * radius1 + d * d - radius2 * radius2) / (2 * radius1 * d));
|
||||
u2 = Math.acos((radius2 * radius2 + d * d - radius1 * radius1) / (2 * radius2 * d));
|
||||
} else {
|
||||
u1 = 0;
|
||||
u2 = 0;
|
||||
}
|
||||
|
||||
var angle1 = (center2 - center1).getAngleInRadians(),
|
||||
angle2 = Math.acos((radius1 - radius2) / d),
|
||||
angle1a = angle1 + u1 + (angle2 - u1) * v,
|
||||
angle1b = angle1 - u1 - (angle2 - u1) * v,
|
||||
angle2a = angle1 + Math.PI - u2 - (Math.PI - u2 - angle2) * v,
|
||||
angle2b = angle1 - Math.PI + u2 + (Math.PI - u2 - angle2) * v;
|
||||
p1a = center1 + getVector(angle1a, radius1),
|
||||
p1b = center1 + getVector(angle1b, radius1),
|
||||
p2a = center2 + getVector(angle2a, radius2),
|
||||
p2b = center2 + getVector(angle2b, radius2),
|
||||
// define handle length by the distance between both ends of the curve to draw
|
||||
d2 = Math.min(v * handle_len_rate, p1a.getDistance(p2a) / (radius1 + radius2));
|
||||
|
||||
d2 *= Math.min(1, d * 2 / (radius1 + radius2)); // case circles are overlapping
|
||||
radius1 *= d2;
|
||||
radius2 *= d2;
|
||||
|
||||
var path = new Path([p1a, p2a, p2b, p1b]);
|
||||
path.style = ball1.style;
|
||||
path.closed = true;
|
||||
var segments = path.segments;
|
||||
segments[0].handleOut = getVector(angle1a - pi2, radius1);
|
||||
segments[1].handleIn = getVector(angle2a + pi2, radius2);
|
||||
segments[2].handleOut = getVector(angle2b - pi2, radius2);
|
||||
segments[3].handleIn = getVector(angle1b + pi2, radius1);
|
||||
return path;
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
function getVector(radians, length) {
|
||||
return new Point({
|
||||
// Convert radians to degrees:
|
||||
angle: radians * 180 / Math.PI,
|
||||
length: length
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id='canvas' width=1024 height=768></canvas>
|
||||
</body>
|
Loading…
Reference in a new issue