Line intersection demo
by Fernando van Loenhout
HTML
<script type="text/template" id="dynamic-line">
<g>
<line
:x1="point1.x"
:y1="point1.y"
:x2="point2.x"
:y2="point2.y"
:stroke="color"
stroke-width="3"
/>
</g>
</script>
<div id="app" @mousemove="mousemove">
<pre style="pointer-events: none; position: absolute; user-select: none; opacity: 0.5">You can drag the points to move them!
{{ { points, intersectionPoint } }}</pre>
<svg height="500" width="500">
<dynamic-line
v-for="(line, index) in lines"
:point1="line[0]" :point2="line[1]"
:color="index ? 'red' : 'blue'"
></dynamic-line>
<ellipse
v-for="(point, index) in points"
:key="index"
:cx="point.x"
:cy="point.y"
rx=10
ry=10
:fill="index > 1 ? 'red' : 'blue'"
@mousedown="clickedPoint = point"
@mouseup="clickedPoint = undefined"
></ellipse>
<ellipse
v-if="!intersectionPoint.isParallel"
:cx="intersectionPoint.point.x"
:cy="intersectionPoint.point.y"
rx=10
ry=10
:fill="intersectionPoint.intersection ? 'green' : 'rgba(255, 0, 255, 0.2)'"
style="pointer-events: none;"
></ellipse>
</svg>
</div>
Vue
Vue.component('dynamic-line', {
template: '#dynamic-line',
props: {
point1: Object,
point2: Object,
color: String,
},
})
new Vue({
el: "#app",
data() {
const points = [
{
x: 100,
y: 200,
},
{
x: 300,
y: 200,
},
{
x: 200,
y: 100,
},
{
x: 200,
y: 300,
},
]
return {
points,
lines: [[points[0], points[1]],[points[2], points[3]]],
clickedPoint: undefined,
};
},
computed: {
intersectionPoint() {
const a = this.points[0];
const b = this.points[1];
const c = this.points[2];
const d = this.points[3];
return this.computeIntersection(a, b, c, d);
},
},
methods: {
mousemove(evt) {
if (this.clickedPoint) {
this.clickedPoint.x = evt.clientX;
this.clickedPoint.y = evt.clientY;
}
},
computeIntersection(a, b, c, d) {
const h1 = this.computeH(a, b, c, d);
const h2 = this.computeH(c, d, a, b);
const isParallel = isNaN(h1) || isNaN(h2);
const f = {x: d.x-c.x, y: d.y-c.y }
return {
intersection: h1 >= 0 && h1 <= 1 && h2 >= 0 && h2 <= 1,
isParallel,
point: isParallel ? undefined :
// C + F*h
{
x: c.x + f.x * h1,
y: c.y + f.y * h1,
},
}
},
computeH(a, b, c, d) {
// E = B-A = ( Bx-Ax, By-Ay )
const e = {x: b.x-a.x, y: b.y-a.y }
// F = D-C = ( Dx-Cx, Dy-Cy )
const f = {x: d.x-c.x, y: d.y-c.y }
// P = ( -Ey, Ex )
const p = {x: -e.y, y: e.x}
// h = ( (A-C) * P ) / ( F * P )
const intersection = f.x*p.x+f.y*p.y;
if(intersection === 0) {
// Paralel lines
return NaN;
}
return ( (a.x - c.x) * p.x + (a.y - c.y) * p.y) / intersection;
}
}
})