Skip to content

Instantly share code, notes, and snippets.

@enjalot
Last active August 12, 2021 04:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save enjalot/ce4c4409fb80559de2bd to your computer and use it in GitHub Desktop.
Save enjalot/ce4c4409fb80559de2bd to your computer and use it in GitHub Desktop.
perpendicular tangent on path
{"description":"perpendicular tangent on path","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"pingpong","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"ajax-caching":true,"thumbnail":"http://i.imgur.com/jEajpwo.png","inline-console":false,"controls":{"Amplitude Top":100,"tang":100,"tangent":52,"tangent at":50,"tangent at ":50,"tangent at percent":59}}
var height = 150;
var points = [
{x: 100, y: 100},
{x: 146, y: 114},
{x: 200, y: 75},
{x: 250, y: 90}
]
// lets use percentage of the length to determine where we take tangent;
var tangentAt = tributary.control({name: "tangent at percent", min: 0, max: 100, step: 1 })
var line = d3.svg.line()
.x(function(d) {
return d.x
})
.y(function(d) {
return d.y
})
.interpolate("cardinal")
//.interpolate("basis")
var svg = d3.select("svg")
var path = svg.append("path")
.attr("d", line(points))
.style({
fill: "none",
stroke: "#000",
"stroke-width": 2
})
// we get the DOM node
var pathNode = path.node();
var tangent = getTangent(pathNode, tangentAt);
vectorScale = 100;
tangent.v.x *= vectorScale
tangent.v.y *= vectorScale
console.log(tangent)
var perp = rotate2d(tangent.v, 90);
svg.append("line")
.attr({
x1: tangent.p.x,
y1: tangent.p.y,
x2: tangent.p.x + tangent.v.x,
y2: tangent.p.y + tangent.v.y,
stroke: "#e15555",
"stroke-width": 2
})
svg.append("line")
.attr({
x1: tangent.p.x,
y1: tangent.p.y,
x2: tangent.p.x + perp.x,
y2: tangent.p.y + perp.y,
stroke: "#5f55e1",
"stroke-width": 2
})
var circles = svg.selectAll("circle")
.data(points)
.enter().append("circle")
.attr({
cx: function(d) { return d.x },
cy: function(d) { return d.y },
r: 5,
fill: "none",
stroke: "#6d6d6d"
})
var node = path.node()
var samples = getSamples(node, 49);
/*
var rects = svg.selectAll("rect")
.data(samples)
.enter().append("rect")
.attr({
x: function(d) { return d.x },
y: function(d) { return d.y },
width: 1,
height: function(d) { return height - d.y }
})
*/
function getSamples(path, num) {
var len = path.getTotalLength()
var p;
var result = []
for(var i = 0; i < num; i++) {
p = path.getPointAtLength(i * len/num);
result.push({
p: p,
t: getTangent(path, i/num)
});
}
return result
}
function getTangent(path, percent) {
// returns a normalized vector that describes the tangent
// at the point that is found at *percent* of the path's length
var fraction = percent/100;
if(fraction < 0) fraction = 0;
if(fraction > 0.99) fraction = 1;
var len = path.getTotalLength();
var point1 = path.getPointAtLength(fraction * len - 0.1);
var point2 = path.getPointAtLength(fraction * len + 0.1);
console.log("p", point2.x, point2.y)
var vector = { x: point2.x - point1.x, y: point2.y - point1.y }
var magnitude = Math.sqrt(vector.x*vector.x + vector.y*vector.y);
vector.x /= magnitude;
vector.y /= magnitude;
console.log("vector", vector)
return {p: point1, v: vector };
}
function rotate2d(vector, angle) {
//rotate a vector
angle *= Math.PI/180; //convert to radians
return {
x: vector.x * Math.cos(angle) - vector.y * Math.sin(angle),
y: vector.x * Math.sin(angle) + vector.y * Math.cos(angle)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment