Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
let width = 800
let height = 400
var intersects = [];
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
function randomPoint() {
return {x:(Math.random()*(width - 100)) + 50, y:(Math.random()*(height - 100)) + 50}
}
function randomCentered(point) {
return {x:(Math.random() * 100) - 50 + point.x, y:(Math.random() * 100) - 50 + point.y}
}
function randomPoly(point) {
return {p1:randomCentered(point), p2:randomCentered(point), p3:randomCentered(point)}
}
var polygons = []
for (i=0; i<4; i++) {
let point = randomPoint()
polygons.push(randomPoly(point))
}
let polygonEdges = [
{x:0, y:0},
{x:0, y:height},
{x:width, y:height},
{x:width, y:0}
];
let polygonSegments = [
{pa: polygonEdges[0], pb: polygonEdges[1], xab: 0, yab: -height},
{pa: polygonEdges[1], pb: polygonEdges[2], xab: -width, yab: 0},
{pa: polygonEdges[2], pb: polygonEdges[3], xab: 0, yab: height},
{pa: polygonEdges[3], pb: polygonEdges[0], xab: width, yab: 0},
]
polygons.forEach(function(p) {
svg.append("line").style("stroke", "black")
.attr("x1", p.p1.x)
.attr("x2", p.p2.x)
.attr("y1", p.p1.y)
.attr("y2", p.p2.y);
svg.append("line").style("stroke", "black")
.attr("x1", p.p2.x)
.attr("x2", p.p3.x)
.attr("y1", p.p2.y)
.attr("y2", p.p3.y);
svg.append("line").style("stroke", "black")
.attr("x1", p.p3.x)
.attr("x2", p.p1.x)
.attr("y1", p.p3.y)
.attr("y2", p.p1.y);
polygonEdges.push(p.p1);
polygonEdges.push(p.p2);
polygonEdges.push(p.p3);
var xab = p.p2.x-p.p1.x;
var yab = p.p2.y-p.p1.y;
var a = yab/xab;
var b = p.p1.y - (a * p.p1.x);
polygonSegments.push({pa: p.p1, pb: p.p2, xab: xab, yab: yab, a:a, b:b});
xab = p.p3.x-p.p2.x;
yab = p.p3.y-p.p2.y;
a = yab/xab;
b = p.p2.y - (a * p.p2.x);
polygonSegments.push({pa: p.p2, pb: p.p3, xab: xab, yab: yab, a:a, b:b});
xab = p.p1.x-p.p3.x;
yab = p.p1.y-p.p3.y;
a = yab/xab;
b = p.p3.y - (a * p.p3.x);
polygonSegments.push({pa: p.p3, pb: p.p1, xab: xab, yab: yab, a:a, b:b});
})
let visor = svg.append("circle")
.attr("r", 5)
.attr("fill", "red")
.attr("class", "visor");
var w = d3.select(window).on("mousemove", mouseMove);
function getIntersection(ray,segment){
// RAY in parametric: Point + Delta*T1
var r_px = ray.pa.x;
var r_py = ray.pa.y;
var r_dx = ray.xab;
var r_dy = ray.yab;
// SEGMENT in parametric: Point + Delta*T2
var s_px = segment.pa.x;
var s_py = segment.pa.y;
var s_dx = segment.xab;
var s_dy = segment.yab;
console.log(r_px+" "+r_py+" "+r_dx+" "+r_dy+" "+s_px+" "+s_py+" "+s_dx+" "+s_dy)
// Are they parallel? If so, no intersect
var r_mag = Math.sqrt(r_dx*r_dx+r_dy*r_dy);
var s_mag = Math.sqrt(s_dx*s_dx+s_dy*s_dy);
if(r_dx/r_mag==s_dx/s_mag && r_dy/r_mag==s_dy/s_mag){
// Unit vectors are the same.
return null;
}
var T2 = (r_dx*(s_py-r_py) + r_dy*(r_px-s_px))/(s_dx*r_dy - s_dy*r_dx);
var T1 = (s_px+s_dx*T2-r_px)/r_dx;
// Must be within parametic whatevers for RAY/SEGMENT
if(T1<0) return null;
if(T2<0 || T2>1) return null;
// Return the POINT OF INTERSECTION
return {
x: r_px+r_dx*T1,
y: r_py+r_dy*T1,
param: T1
};
}
function mouseMove() {
var x = d3.event.x;
var y = d3.event.y;
intersects = [];
for(var i=0;i<polygonEdges.length;i++){
var p = polygonEdges[i]
var xab = p.x-x;
var yab = p.y-y;
var a = yab/xab;
var b = p.y - (a * p.x);
var angle = Math.atan2(yab,xab);
var ray = {pa: {x:x, y:y}, pb: {x:p.x, y:p.y}, xab: xab, yab: yab, a:a, b:b, angle:angle}
angle += 0.00001;
var dx = Math.cos(angle);
var dy = Math.sin(angle);
a = dy/dx;
b = y - (a * x);
var ray2 = {pa:{x:x,y:y},pb:{x:x+dx,y:y+dy}, xab:dx, yab:dy, a:a, b:b, angle:angle};
angle -= 0.00002;
var dx = Math.cos(angle);
var dy = Math.sin(angle);
a = dy/dx;
b = y - (a * x);
var ray3 = {pa:{x:x,y:y},pb:{x:x+dx,y:y+dy}, xab:dx, yab:dy, a:a, b:b, angle:angle};
var closestIntersect1 = null;
var closestIntersect2 = null;
var closestIntersect3 = null;
for(var j=0;j<polygonSegments.length;j++){
var intersect = getIntersection(ray,polygonSegments[j]);
if(!intersect) continue;
if(!closestIntersect1 || intersect.param<closestIntersect1.param) {
closestIntersect1=intersect;
}
intersect = getIntersection(ray2,polygonSegments[j]);
if(!intersect) continue;
if(!closestIntersect2 || intersect.param<closestIntersect2.param) {
closestIntersect2=intersect;
}
intersect = getIntersection(ray3,polygonSegments[j]);
if(!intersect) continue;
if(!closestIntersect3 || intersect.param<closestIntersect3.param) {
closestIntersect3=intersect;
}
}
if(closestIntersect1) intersects.push(closestIntersect1);
if(closestIntersect2) intersects.push(closestIntersect2);
if(closestIntersect3) intersects.push(closestIntersect3);
}
svg.select(".visor")
.attr("cx", x)
.attr("cy", y);
drawLinesOfSight(d3.event.x, d3.event.y);
}
let linesOfSight = svg.selectAll(".lineOfSight").data(polygonEdges)
linesOfSight.enter()
.append("line")
.attr("class", "lineOfSight")
.style("stroke", "red")
.attr("x1", 0)
.attr("x2", function(d) { return d.x; })
.attr("y1", 0)
.attr("y2", function(d) { return d.y; });
function drawLinesOfSight(x, y) {
svg.selectAll(".lineOfSight").data(intersects)
.enter().append("line")
.attr("class", "lineOfSight")
.style("stroke", "red")
.attr("x1", x)
.attr("x2", function(d) {
return d.x;
if (d.x >= width || d.x <= 0) return d.x;
var diff = x - d.x;
let limit = (diff > 0) ? 0 : width;
return limit
})
.attr("y1", y)
.attr("y2", function(d) {
return d.y;
if (d.x >= width || d.x <= 0) return d.y;
var diff = x - d.x;
let limit = (diff > 0) ? 0 : width;
var xab = d.x-x;
var yab = d.y-y;
var a = yab/xab;
var b = d.y - (a * d.x);
return (a * limit + b)
//return d.y;
});
svg.selectAll(".lineOfSight").data(intersects)
.attr("x1", x)
.attr("x2", function(d) {
return d.x;
if (d.x >= width || d.x <= 0) return d.x;
var diff = x - d.x;
let limit = (diff > 0) ? 0 : width;
return limit
})
.attr("y1", y)
.attr("y2", function(d) {
return d.y;
if (d.x >= width || d.x <= 0) return d.y;
var diff = x - d.x;
let limit = (diff > 0) ? 0 : width;
var xab = d.x-x;
var yab = d.y-y;
var a = yab/xab;
var b = d.y - (a * d.x);
return (a * limit + b)
//return d.y;
});
svg.selectAll(".lineOfSight").data(intersects).exit().remove()
}
</script>
</body>
https://d3js.org/d3.v4.js