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;
		}
	}
})