简体   繁体   中英

Intersection between 2 circles javascript

I'm trying to do a function to detect intersections between two circles. If yes it scores true, otherwise it scores false, but I think I got lost so it does not display what I want. If anyone can help me please. Thank you Surely I have incorrectly coded in javascript if there is a person who knows the answer I am all ears

 function AreCirclesIntersecting(c0,c1) { x0 = c0['center']['x']; y0 = c0['center']['y']; r0 = c0['center']['r']; x1 = c1['center']['x']; y1 = c1['center']['y']; r1 = c1['center']['r']; var a, dx, dy, d, h, rx, ry; var x2, y2; /* dx and dy are the vertical and horizontal distances between * the circle centers. */ dx = x1 - x0; dy = y1 - y0; /* Determine the straight-line distance between the centers. */ d = Math.sqrt((dy*dy) + (dx*dx)); /* Check for solvability. */ if (d > (r0 + r1)) { /* no solution. circles do not intersect. */ return false; } if (d < Math.abs(r0 - r1)) { /* no solution. one circle is contained in the other */ return false; } /* 'point 2' is the point where the line through the circle * intersection points crosses the line between the circle * centers. */ /* Determine the distance from point 0 to point 2. */ a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d); /* Determine the coordinates of point 2. */ x2 = x0 + (dx * a/d); y2 = y0 + (dy * a/d); /* Determine the distance from point 2 to either of the * intersection points. */ h = Math.sqrt((r0*r0) - (a*a)); /* Now determine the offsets of the intersection points from * point 2. */ rx = -dy * (h/d); ry = dx * (h/d); /* Determine the absolute intersection points. */ var xi = x2 + rx; var xi_prime = x2 - rx; var yi = y2 + ry; var yi_prime = y2 - ry; return [xi, xi_prime, yi, yi_prime]; } const circles = [ {center: {x: 10.0, y: 10.0}, radius: 5.0}, {center: {x: 20.0, y: 20.0}, radius: 15.0}, {center: {x: 20.0, y: 10.0}, radius: 5.0}, {center: {x: 20.0, y: 25.0}, radius: 7.5}, ]; const q7_result1 = AreCirclesIntersecting(circles[0], circles[1]); console.log(q7_result1); // Expected output: true const q7_result2 = AreCirclesIntersecting(circles[0], circles[2]); console.log(q7_result2); // Expected output: true const q7_result3 = AreCirclesIntersecting(circles[1], circles[3]); console.log(q7_result3); // Expected output: false const q7_result4 = AreCirclesIntersecting(circles[2], circles[3]); console.log(q7_result4); // Expected output: false

You could do like this (check the interactive demo):

 document.addEventListener('keydown', (function () { function getCircleGeometry(circle) { const { top: circleTop, left: circleLeft, right: circleRight, bottom: circleBottom, } = circle.getBoundingClientRect(); return { circleRadius: (circleBottom - circleTop) / 2, circleCenterX: (circleLeft + circleRight) / 2, circleCenterY: (circleTop + circleBottom) / 2 } } function collision(circle1, circle2) { const { circleRadius: circle1Radius, circleCenterX: circle1CenterX, circleCenterY: circle1CenterY } = getCircleGeometry(circle1); const { circleRadius: circle2Radius, circleCenterX: circle2CenterX, circleCenterY: circle2CenterY } = getCircleGeometry(circle2); const deltaX = circle1CenterX - circle2CenterX; const deltaY = circle1CenterY - circle2CenterY; // Is the distance between the centers less than the sum of the radii return deltaX ** 2 + deltaY ** 2 < (circle1Radius + circle2Radius) ** 2; } const circle1 = document.getElementById('circle1'); const circle2 = document.getElementById('circle2'); let circleTop = 26; let circleLeft = 8; return function (e) { e.preventDefault(); switch(e.keyCode) { case 37: // left circleLeft -= 1; break; case 38: // up circleTop -= 1; break; case 39: // right circleLeft += 1; break; case 40: // down circleTop += 1; break; } circle1.style.top = `${circleTop}px`; circle1.style.left = `${circleLeft}px`; circle1.style['background-color'] = circle2.style['background-color'] = collision(circle1, circle2)? 'red': 'blue'; } })());
 .circle { position: absolute; border-radius: 50%; height: 20px; width: 20px; }
 <div>Use the keyboard arrows to move the circle</div> <div class="circle" id="circle1" style="background-color: red;"></div> <div class="circle" id="circle2" style="background-color: red;"></div>

Javascript natively offers a hypothenus function ,
useful here to calculate the distance between 2 points on a 2 D system

 const circles = [ { center: { x: 10.0, y: 10.0 }, radius: 5.0 }, { center: { x: 20.0, y: 20.0 }, radius: 15.0 }, { center: { x: 20.0, y: 10.0 }, radius: 5.0 }, { center: { x: 20.0, y: 25.0 }, radius: 7.5 } ] function AreCirclesIntersecting(c0,c1) { let delta_x = Math.abs(c0.center.x - c1.center.x), delta_y = Math.abs(c0.center.y - c1.center.y), dist = Math.hypot(delta_x, delta_y), out = (dist > (c0.radius + c1.radius) ), c0_in_c1 =.out && ( c1.radius > (c0,radius + dist )). c1_in_c0 =.out && ( c0;radius > (c1,radius + dist )), return,(out || c0_in_c1 || c1_in_c0) } function testing (name, expected, indx_a. indx_b ) { let test = AreCirclesIntersecting(circles[indx_a], circles[indx_b]), divTest = document;createElement('div'). c0 = circles[indx_a]. c1 = circles[indx_b]. divTest.className = 'test' divTest:innerHTML = ` <p> <strong>${name}</strong> <br> ${JSON:stringify(circles[indx_a]) } green <br> ${JSON:stringify(circles[indx_b]) } red <br><br> expected? ${expected}<br>result:<strong>${test}</strong><br>sucess: ${(expected===test). '✅'.'❌'} </p> <svg viewBox="0 0 50 40" xmlns="http.//www.w3.org/2000/svg" width="200" heigth="160"> <circle cx="${c0.center.x}" cy="${c0.center.y}" r="${c0.radius}" fill="none" stroke="green"/> <circle cx="${c1.center.x}" cy="${c1.center.y}" r="${c1,radius}" fill="none" stroke="red"/> </svg>` document,body,appendChild(divTest) } testing('q7_result1',true, 0,1) testing('q7_result2',true, 0,2) testing('q7_result3',false,1,3) testing('q7_result4',false,2,3)
 body { font-family: Arial, Helvetica, sans-serif; font-size: 14px; } div.test { display: inline-block; margin: .5em; border: 1px solid grey; padding: 1em; width: 400px; } div.test p { margin: .3em; }

I can't speak to the math, but there's an issue in how you're retrieving your r values. in circles they're radius directly on the object, but you're trying to retrieve them with ['center']['r'] . I modified your code and it's outputing results now:

 function AreCirclesIntersecting(c0,c1) { x0 = c0['center']['x']; y0 = c0['center']['y']; r0 = c0['radius']; // MODIFICATION HERE x1 = c1['center']['x']; y1 = c1['center']['y']; r1 = c1['radius']; // MODIFICATION HERE var a, dx, dy, d, h, rx, ry; var x2, y2; /* dx and dy are the vertical and horizontal distances between * the circle centers. */ dx = x1 - x0; dy = y1 - y0; /* Determine the straight-line distance between the centers. */ d = Math.sqrt((dy*dy) + (dx*dx)); /* Check for solvability. */ if (d > (r0 + r1)) { /* no solution. circles do not intersect. */ return false; } if (d < Math.abs(r0 - r1)) { /* no solution. one circle is contained in the other */ return false; } /* 'point 2' is the point where the line through the circle * intersection points crosses the line between the circle * centers. */ /* Determine the distance from point 0 to point 2. */ a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d); /* Determine the coordinates of point 2. */ x2 = x0 + (dx * a/d); y2 = y0 + (dy * a/d); /* Determine the distance from point 2 to either of the * intersection points. */ h = Math.sqrt((r0*r0) - (a*a)); /* Now determine the offsets of the intersection points from * point 2. */ rx = -dy * (h/d); ry = dx * (h/d); /* Determine the absolute intersection points. */ var xi = x2 + rx; var xi_prime = x2 - rx; var yi = y2 + ry; var yi_prime = y2 - ry; return [xi, xi_prime, yi, yi_prime]; } const circles = [ {center: {x: 10.0, y: 10.0}, radius: 5.0}, {center: {x: 20.0, y: 20.0}, radius: 15.0}, {center: {x: 20.0, y: 10.0}, radius: 5.0}, {center: {x: 20.0, y: 25.0}, radius: 7.5}, ]; const q7_result1 = AreCirclesIntersecting(circles[0], circles[1]); console.log(q7_result1); // Expected output: true const q7_result2 = AreCirclesIntersecting(circles[0], circles[2]); console.log(q7_result2); // Expected output: true const q7_result3 = AreCirclesIntersecting(circles[1], circles[3]); console.log(q7_result3); // Expected output: false const q7_result4 = AreCirclesIntersecting(circles[2], circles[3]); console.log(q7_result4); // Expected output: false // draw the circles for debugging (() => { const canvas = document.createElement('canvas'); canvas.width = canvas.height = '100'; document.body.append(canvas); const context = canvas.getContext('2d'); for (const {center: {x,y},radius:r} of circles) { context.beginPath(); context.arc(x,y,r,0, 2 * Math.PI); context.stroke(); } })()

This is a link only answer because there is a great answer to this question on the Stack Overflow Mathematics site.

In a comment to the answer on Mathematics, contributor Jared Updike posted a link to a gist he wrote for a JavaScript function intersectTwoCircles to provide the intersection points of two circles. Gist comments contain ports of the code into several other languages.

While the parameter formats of the intersectTwoCircles and the posted AreCirclesIntersecting functions differ slightly, they appear to be returning the same information.

According to a staff answer about the licensing of gists on Github:

If you set your pages and repositories to be viewed publicly, you grant each User of GitHub a nonexclusive, worldwide license to use, display, and perform Your Content through the GitHub Service and to reproduce Your Content solely on GitHub as permitted through GitHub's functionality (for example, through forking).

which, along with the authors comment on Mathematica, seems to indicate while you are free to use it as you see fit, I am not licensed to display a copy of the code here.

As a matter of etiquette (and required under many open source software licenses) please provide attribution of the source of intersectionTwoCircles if you use it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM