metaball-pull-example.js

total 0
used 0
limit 0
/* title: Meta Ball Example categories: tangents files: head point stroke ../point_src/point-content.js ../point_src/pointlist.js ../point_src/events.js ../point_src/automouse.js ../point_src/distances.js ../point_src/dragging.js ../point_src/functions/clamp.js ../point_src/curve-extras.js ../point_src/mirror.js ../point_src/stage.js ../point_src/text/label.js ../point_src/intersections.js --- In this example we perform _meta ball_ sticky like points using tangent arcs. To ensure we draw or stroke neatly, we carefully draw the pen in the correct point to point conigious walk. */ class MainStage extends Stage { canvas='playspace' mounted(){ this.pointA = new Point({x:200,y:300, radius:70}) this.pointB = new Point({x:500,y:300, radius:100}) this.dragging.addPoints(this.pointA, this.pointB) // this.events.wake() this.lines = [] this.rLength = 200 this.connected = false; /* The distance for activating meta ball */ this.edgeDistance = 2 /* the gap size between the two meta-ball arcs. If the arcs are closer than the minimum, a _break_ occurs. */ this.tangentMinDistance = 2 /* the multipler for the tangent arc size. Smaller results in a _tighter_ meta-ball. Larger (1) results in _stretchier_ meta-ball. */ this.rLengthMultiplier = .7 this.pointColor = '#050505' } draw(ctx){ this.clear(ctx) ctx.strokeStyle = 'purple' ctx.lineWidth = 3 let a = this.pointA; let b = this.pointB; /* This can be static, but scaling to distance add a nice looking variant. */ this.rLength = a.distanceTo(b) * this.rLengthMultiplier let ts = getTangents(a,b, this.rLength) if(ts == undefined) { /* No tagents. Too far to too close. */ if(this.pointColor){ a.pen.fill(ctx, {color: this.pointColor}) b.pen.fill(ctx, {color: this.pointB.color}) } a.pen.circle(ctx) b.pen.circle(ctx, {color: this.pointB.color}) return } /* If the edges of our points are touching, we activate the meta balling */ let edgeDistance = a.distanceTo(b) - a.radius - b.radius; if(edgeDistance < this.edgeDistance) { this.connected = true } if(ts.o3 && ts.o4) { let dist = ts.o3.distanceTo(ts.o4) let v = dist - (this.rLength * 2) if(v < this.tangentMinDistance) { /* touching arcs, */ this.connected = false } } if(this.connected) { return this.drawArcs(ctx, ts) } else { if(this.pointColor) { a.pen.fill(ctx, {width: 2, color: this.pointColor}) b.pen.fill(ctx, {width: 2, color: this.pointColor}) } a.pen.circle(ctx, {width: 2}) b.pen.circle(ctx, {color: this.pointB.color}) } } drawArcs(ctx, ts){ let a = this.pointA; let b = this.pointB; let color = 'green' let [t1, t2] = ts.a let [t3, t4] = ts.b /* Touch points. */ // t1.pen.fill(ctx, 'red') // top left // t2.pen.fill(ctx, 'orange') // bottom left // t3.pen.fill(ctx, 'green') // top right // t4.pen.fill(ctx, 'lime') // bottom left let o4 = ts.o4 , o3 = ts.o3 , r3 = ts.r3 ; const t2Angle = twoPointsAngle(o4, t2) const t4Angle = twoPointsAngle(o4, t4) const t3Angle = twoPointsAngle(o3, t3) const t1Angle = twoPointsAngle(o3, t1) // t1.pen.arc(ctx, t2, 'red') ctx.beginPath() // The left meta ball a.draw.arc(ctx, a.distanceTo(t1), a.directionTo(t1), a.directionTo(t2)) /* Mini Lesson. When draing a line we want to move the pen to each point correctly. If you have an arc drawing _right to left_: ctx.arc(o4.x, o4.y, r3, t4Angle, t2Angle, 1); and want to perform the same _left to right_, flip the angles and the drawing direction: ctx.arc(o4.x, o4.y, r3, t2Angle, t4Angle, 0); */ // Bottom line ctx.arc(o4.x, o4.y, r3, t2Angle, t4Angle, 0); // The right meta ball. b.draw.arc(ctx, b.distanceTo(t3), b.directionTo(t4), b.directionTo(t3), 1) // top Line ctx.arc(o3.x, o3.y, r3, t3Angle, t1Angle, 0); if(this.pointColor) { ctx.fillStyle = this.pointColor ctx.fill() } ctx.stroke() // ctx.strokeStyle = 'grey' } } let getTangents = function(a, b, rLength){ let r1 = a.radius let r2 = b.radius let r3 = rLength // Then build the new protractor points. let c = a.copy().update({ radius: r1 + r3 }) let d = b.copy().update({ radius: r2 + r3 }) let o34 = getCircleCircleIntersections(c, d) if(o34 === false || o34.length == 0) { return } let o3 = new Point(o34[1]) let o4 = new Point(o34[0]) // let [o3, o4] = o34 let o1 = a let o2 = b // join points o1 to o3, o3 to o2, o2 to o4, o4 to o1 let asLine = (x,y)=>{let l = new Line(x, y); l.doTips=false; return l} let lineA = asLine(a, o3) let lineB = asLine(o3, b) let lineC = asLine(b, o4) let lineD = asLine(o4, a) let lines = [lineA, lineB, lineC, lineD] let t1, t2, t3, t4; let o1LineAInter = checkPointIntersectionEdge(lineA, a) if(o1LineAInter) { t1 = new Point(o1LineAInter[0]) // o1LineAInter.forEach(p=>t1.pen.fill(ctx, 'green')) } let o1LineBInter = checkPointIntersectionEdge(lineD, a) if(o1LineBInter) { t2 = new Point(o1LineBInter[0]) // o1LineAInter.forEach(p=>(new Point(p)).pen.fill(ctx, 'green')) } let o2LineAInter = checkPointIntersectionEdge(lineB, b) if(o2LineAInter) { t3 = new Point(o2LineAInter[0]) // o1LineAInter.forEach(p=>(new Point(p)).pen.fill(ctx, 'green')) } let o2LineBInter = checkPointIntersectionEdge(lineC, b) if(o2LineBInter) { t4 = new Point(o2LineBInter[0]) // o2LineBInter.forEach(p=>(new Point(p)).pen.fill(ctx, 'green')) } return { a: [t1, t2] , b: [t3, t4] , lines , o1, o2, o3, o4 , r3 } } const twoPointsAngleRaw = function(origin, target) { /*given two points, return the relative angle (in radians), of target from the origin. For example if the target was left of the origin, this would be a -Math.PI */ const { x: x1, y: y1, radius: r1 } = origin; const { x: x2, y: y2, radius: r2 } = target; // Calculate distance between centers const dx = x2 - x1; const dy = y2 - y1; const dist = Math.sqrt(dx * dx + dy * dy); // Calculate the angle between the points const angle = Math.atan2(dy, dx); return angle } const twoPointsAngle = function(origin, target) { let dist = new Point(target.distance2D(origin)) return dist.atan2() } ;stage = MainStage.go();
Run
Meta Data
title Meta Ball Example
imports ()
files ('head', 'point', 'stroke', '../point_src/point-content.js', '../point_src/pointlist.js', '../point_src/events.js', '../point_src/automouse.js', '../point_src/distances.js', '../point_src/dragging.js', '../point_src/functions/clamp.js', '../point_src/curve-extras.js', '../point_src/mirror.js', '../point_src/stage.js', '../point_src/text/label.js', '../point_src/intersections.js')
unused_keys ()
unknown_keys ('categories',)
categories ['tangents']
filepath_exists True
path metaball-pull-example.js
filepath metaball-pull-example.js
clean_files ('../point_src/core/head.js', '../point_src/pointpen.js', '../point_src/compass.js', '../point_src/center.js', '../point_src/point-content.js', '../point_src/pointdraw.js', '../point_src/relative-xy.js', '../point_src/pointcast.js', '../point_src/point.js', '../point_src/setunset.js', '../point_src/stroke.js', '../point_src/pointlistdraw.js', '../point_src/pointlistgradient.js', '../point_src/pointlistshape.js', '../point_src/pointlistgenerator.js', '../point_src/unpack.js', '../point_src/pointlist.js', '../point_src/events.js', '../point_src/automouse.js', '../point_src/distances.js', '../point_src/protractor.js', '../point_src/text/beta.js', '../point_src/dragging.js', '../point_src/functions/clamp.js', '../point_src/curve-extras.js', '../point_src/mirror.js', '../point_src/stage-hooks.js', '../point_src/functions/resolve.js', '../point_src/stage.js', '../point_src/text/label.js', '../point_src/intersections.js')
markdown {'html': '<hr />\n<p>In this example we perform <em>meta ball</em> sticky like points using tangent arcs.\nTo ensure we draw or stroke neatly, we carefully draw the pen in the correct\npoint to point conigious walk.</p>', 'content': 'title: Meta Ball Example\ncategories: tangents\nfiles:\n head\n point\n stroke\n ../point_src/point-content.js\n ../point_src/pointlist.js\n ../point_src/events.js\n ../point_src/automouse.js\n ../point_src/distances.js\n ../point_src/dragging.js\n ../point_src/functions/clamp.js\n ../point_src/curve-extras.js\n ../point_src/mirror.js\n ../point_src/stage.js\n ../point_src/text/label.js\n ../point_src/intersections.js\n\n---\n\nIn this example we perform _meta ball_ sticky like points using tangent arcs.\nTo ensure we draw or stroke neatly, we carefully draw the pen in the correct\npoint to point conigious walk.'}