简体   繁体   English

在旋转的矩形中迭代网格正方形

[英]Iterate grid squares in a rotated rectangle

Given a rectangle with a defined width, height, x coordinate, and y coordinate is applied to a grid and rotated.给定一个具有定义宽度、高度、x 坐标和 y 坐标的矩形,将其应用于网格并旋转。

How can I find and iterate through all the cells inside the rectangle?如何找到并遍历矩形内的所有单元格?

Example image with the rectangle in black and desired cells in red.示例图像,矩形为黑色,所需单元格为红色。

示例图片

Preferred solution in Javascript but I'm happy to accept anything I can port. Javascript 中的首选解决方案,但我很乐意接受我可以移植的任何内容。

THIS WORKS NOW现在可以使用
Basically, find the corners, loop through all the squares between those corners and grab only the ones that have the right angles between the square and the containing rectangle corners, compared to the angles between the corners of the containing rectangle.基本上,找到角,遍历这些角之间的所有正方形,并仅抓住正方形和包含矩形角之间的直角的那些,与包含矩形的角之间的角度相比。
Angle from top corner to square in question > angle from top corner to right corner (and the same for the other corners, except the bottom right corner, which has an additional case) Angle from top corner to square in question angle from top corner to right corner的角度(其他角相同,除了右下角,它有一个额外的情况)

use the arrow keys to rotate the rectangle使用箭头键旋转矩形

 function drawRect (angle) { let rotated = rotateRect(30, 21, angle) // Rectangle is rotated around its center let newHTML = "" rotated.forEach(square=>{ newHTML += `<div class="square" style="left: ${square.x * 10}px; top: ${square.y * 10}px"></div>` }) document.body.innerHTML = newHTML + "<div>Use the Left and Right Arrow Keys</div>" } let angle = 1 drawRect(angle) document.addEventListener("keydown", event=>{ if (event.key == "ArrowRight") { angle += 0.1 } if (event.key == "ArrowLeft") { angle -= 0.1 } drawRect(angle) }) function rotateRect(width, height, rotate /* in radians */) { // Call the center of the rectangle [0,0] rotate = Math.round(rotate * 1000) / 1000 while (rotate <= 0) rotate += Math.PI * 2 let fourCorners = [] fourCorners.push({x: Math.cos(Math.atan2(-height, -width) + rotate) * distance(width/2, height/2), y: Math.sin(Math.atan2(-height, -width) + rotate) * distance(width/2, height/2)}) fourCorners.push({x: Math.cos(Math.atan2(-height, width) + rotate) * distance(width/2, height/2), y: Math.sin(Math.atan2(-height, width) + rotate) * distance(width/2, height/2)}) fourCorners.push({x: Math.cos(Math.atan2(height, width) + rotate) * distance(width/2, height/2), y: Math.sin(Math.atan2(height, width) + rotate) * distance(width/2, height/2)}) fourCorners.push({x: Math.cos(Math.atan2(height, -width) + rotate) * distance(width/2, height/2), y: Math.sin(Math.atan2(height, -width) + rotate) * distance(width/2, height/2)}) for (let i = 1; i < rotate / (Math.PI / 2); i++) { fourCorners.unshift(fourCorners.pop()) } // let leftCorner = fourCorners.sort((a, b)=>ax-bx)[0] // let rightCorner = fourCorners.sort((a, b)=>bx-ax)[0] // let topCorner = fourCorners.sort((a, b)=>ay-by)[0] // let bottomCorner = fourCorners.sort((a, b)=>by-ay)[0] let topCorner = fourCorners[0] let rightCorner = fourCorners[1] let bottomCorner = fourCorners[2] let leftCorner = fourCorners[3] let yMin = topCorner.y let xMax = rightCorner.x let yMax = bottomCorner.y let xMin = leftCorner.x let t_l_angle = Math.atan2(topCorner.y - leftCorner.y, topCorner.x - leftCorner.x) let t_r_angle = Math.atan2(rightCorner.y - topCorner.y, rightCorner.x - topCorner.x) let b_r_angle = Math.atan2(bottomCorner.y - rightCorner.y, bottomCorner.x - rightCorner.x) let b_l_angle = Math.atan2(leftCorner.y - bottomCorner.y, leftCorner.x - bottomCorner.x) let coveredSquares = [] for (let x = Math.ceil(xMin); x < Math.floor(xMax); x++) { for (let y = Math.ceil(yMin); y < Math.floor(yMax); y++) { let local_t_l_angle = Math.atan2(y - leftCorner.y, x - leftCorner.x) let local_t_r_angle = Math.atan2(y - topCorner.y, x+1 - topCorner.x) let local_b_r_angle = Math.atan2(y+1 - rightCorner.y, x+1 - rightCorner.x) let local_b_l_angle = Math.atan2(y+1 - bottomCorner.y, x - bottomCorner.x) if ( (local_t_l_angle > t_l_angle) && (local_t_r_angle > t_r_angle) && (local_b_r_angle > b_r_angle || local_b_r_angle < b_r_angle - Math.PI) && (local_b_l_angle > b_l_angle) ) { coveredSquares.push({x, y}) } } } console.log(coveredSquares) return coveredSquares } function distance(x, y) { return Math.sqrt((x*x)+(y*y)) }
 body { }.square { position: absolute; background-color: red; width: 9px; height: 9px; z-index: 1000; transform: translate(150px, 150px); }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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