Reputation: 63
I'm trying to draw a line from the edges of the two circles in HTML5 canvas. So, I know the coordinates of the centers of two circles and their radius.
Please help!
P.S. Sorry for my english :)
UPDATE:
I'm trying this, but how to know angle?
from_line_x = circle1.x + circle1.radius * Math.cos(Math.PI * angle);
from_line_y = circle1.y + cirlce1.radius * Math.sin(Math.PI * angle);
to_line_x = circle2.x - circle2.radius * Math.cos(Math.PI * angle);
to_line_y = circle2.y - circle2.radius * Math.sin(Math.PI * angle);
UPDATE2:
I think I found how to find the angle. But as a circle drawn randomly, the line is drawn is not always true. How then should look algorithm?
Sorry for my english again.
Upvotes: 2
Views: 6201
Reputation: 11
Had the same problem so I made these functions based on sketch. connectingPts takes the two circle's coordinates {x: x, y: y, r: radius} and returns a 2 element array of the coordinates of the line segment connecting the two circles from their edges.
function connectingPts(t1, t2) {
let p1, p2;
if (t1.x < t2.x) {
p1 = { ...t1 };
p2 = { ...t2 };
} else {
p1 = { ...t2 };
p2 = { ...t1 };
}
let dx = Math.abs(p1.x - p2.x);
let dy = Math.abs(p1.y - p2.y);
let alpha = radToDeg(Math.atan(dy / dx));
let beta = 90 - alpha;
return [
rotatePt(
{ ...p1, x: p1.x + p1.r },
p1,
(p2.y < p1.y ? 360 : alpha * 2) - alpha,
),
rotatePt(
{ ...p2, x: p2.x + p2.r },
p2,
(p2.y > p1.y ? 270 - 2 * beta : 90) + beta,
),
];
}
function rotatePt(p, o, deg) {
let res = { ...p };
let _x = res.x - o.x;
let _y = res.y - o.y;
res.x = _x * Math.cos(degToRad(deg)) - _y * Math.sin(degToRad(deg));
res.y = _x * Math.sin(degToRad(deg)) + _y * Math.cos(degToRad(deg));
res.x += o.x;
res.y += o.y;
return res;
}
function degToRad(deg) {
return (deg * Math.PI) / 180;
}
function radToDeg(rad) {
return (rad * 180) / Math.PI;
}
Upvotes: 0
Reputation: 19294
3 steps solutions :
- build all your random circle coordinates (x,y,r).
- draw all lines in between their center as you see fit.
- draw all circles.
(!)
code is very easy :
http://jsbin.com/qutahatu/1/edit?js,output
var circles = [];
function createCircles(cnt) {
circles = [];
for (var i=0; i<cnt; i++) {
var x = 5+ Math.random() *300;
var y = 5+ Math.random() *300;
var r = 20 + Math.random() *6;
circles.push({x:x,y:y,r:r});
}
}
function drawLines() {
var cnt= circles.length;
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(circles[0].x, circles[0].y);
for (var i=1; i<cnt; i++) {
ctx.lineTo(circles[i].x, circles[i].y);
}
ctx.stroke();
}
function drawCircles() {
var cnt= circles.length;
ctx.fillStyle = '#4A8';
for (var i=0; i<cnt; i++) {
ctx.beginPath();
ctx.arc(circles[i].x, circles[i].y, circles[i].r, 0, 6.282);
ctx.fill();
}
}
createCircles(4);
drawLines();
drawCircles();
Upvotes: 3
Reputation: 13089
Here's a solution that will achieve what you've asked for.
I've declared 3 'classes' to make things clearer to read. First, I define a generic shape class. Next, I define a basic circle class. Finally, I define a vec2 class. You could easily extend this as I have done, and add other shapes that inherit from the shape class - i.e square triangle, etc.
I create 10 circles at random positions and radii. I then draw a line between each circle and the one following it. I didn't bother with the 'wrap-around' case, so I draw 10 circles and 9 lines (I dont draw from circle 9 to circle 0)
I've used some of the code Tamura left, hence the familiar dimensions and id of the canvas.
<!doctype html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e)}
window.addEventListener('load', onDocLoaded, false);
var shapeList = [];
function onDocLoaded()
{
var i, n=10;
var canvas = byId('myCanvas');
for (i=0; i<n; i++)
{
shapeList[i] = new circle_t(Math.random()*578, Math.random()*400, Math.random()*30 + 20);
shapeList[i].draw(canvas);
}
for (i=0; i<n-1; i++)
draw_line2(shapeList[i].origX, shapeList[i].origY, shapeList[i].radius, shapeList[i+1].origX, shapeList[i+1].origY, shapeList[i+1].radius);
}
var shape_t = function(x,y)
{
this.origX = (x==undefined ? 0 : x);
this.origY = (y==undefined ? 0 : y);
}
shape_t.prototype =
{
origX:0, origY:0, typeString:'shape',
setPos: function(x,y){this.x=x;this.y=y;},
setType: function(typeString){this.typeString = typeString;},
toString: function(){return this.typeString + " - " + this.origX + "," + this.origY;},
draw: function(canElem){},
};
function circle_t(x,y,radius)
{
this.origX = (x==undefined ? 0 : x);
this.origY = (y==undefined ? 0 : y);
this.radius = (radius==undefined ? 10 : radius);
this.setType("circle");
}
circle_t.prototype = new shape_t();
circle_t.prototype.constructor = circle_t;
circle_t.prototype.draw = function(canElem, color)
{
var ctx = canElem.getContext('2d');
var col = 'black';
if (color != undefined)
col = color;
drawCircle(this.origX, this.origY, this.radius, ctx, col);
}
circle_t.prototype.setRadius = function(radius)
{
if (radius != undefined)
this.radius = radius;
}
function drawCircle(x, y, radius, ctx, col)
{
ctx.save();
if (col == undefined)
col = 'black';
ctx.strokeStyle = col;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.arc(x,y,radius,(Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
// define a vec2 class to make vector maths easier (simpler to read)
function vec2(x,y)
{
this.length = function()
{
return Math.sqrt((this.x * this.x) + (this.y*this.y));
}
this.normalize = function()
{
var scale = this.length();
this.x /= scale;
this.y /= scale;
}
this.x = x;
this.y = y;
}
function draw_line2(center1_x, center1_y, radius1, center2_x, center2_y, radius2)
{
var betweenVec = new vec2(center2_x - center1_x, center2_y - center1_y);
betweenVec.normalize();
var p1x = center1_x + (radius1 * betweenVec.x);
var p1y = center1_y + (radius1 * betweenVec.y);
var p2x = center2_x - (radius2 * betweenVec.x);
var p2y = center2_y - (radius2 * betweenVec.y);
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(p1x,p1y);
context.lineTo(p2x,p2y);
context.stroke();
}
</script>
</head>
<body>
<canvas id="myCanvas" width="578" height="400"></canvas>
</body>
</html>
See here for a live demo: http://jsfiddle.net/YYjYL/
Upvotes: 6
Reputation: 1798
Here is the JSFIDDLE link: http://jsfiddle.net/WfF3v/1/. Is that what you want?
Below is the JS code:
function draw_circle(center_x, center_y){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = center_x;
var centerY = center_y;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
}
function draw_line(center1_x, center1_y, center2_x, center2_y) {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(center1_x, center1_y);
context.lineTo(center2_x, center2_y);
context.stroke();
}
draw_circle(100,100);
draw_circle(300,200);
draw_line(100,100,300,200);
Upvotes: 1