Fix corner finding algo for firing arc cone coverage

This commit is contained in:
Catalin Mititiuc 2024-03-22 21:52:02 -07:00
parent 9f8c563c98
commit 17e6864d69
2 changed files with 76 additions and 53 deletions

100
index.js
View File

@ -46,7 +46,7 @@ let getPointCoords = (x, y) => {
let svgns = "http://www.w3.org/2000/svg",
svg = document.querySelector('svg'),
rect = document.querySelector('rect#map');
map = document.querySelector('rect#map');
const COLUMN_COUNT = 33,
ROW_COUNT = 25,
@ -108,24 +108,24 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
svg.appendChild(point);
}));
rect.addEventListener('mousemove', e => {
var rect = e.target.getBoundingClientRect();
var pointerX = e.clientX - rect.left;
var pointerY = e.clientY - rect.top;
map.addEventListener('mousemove', e => {
let boundingRect = e.target.getBoundingClientRect();
let pointerX = e.clientX - boundingRect.left;
let pointerY = e.clientY - boundingRect.top;
let [maxXpx, maxYpx] = [e.target.width, e.target.height].map(v => v.baseVal.value);
// console.log('x', `${toFixed(x / rect.width * maxX)}"`, 'y', `${toFixed(y / rect.height * maxY)}"`);
// console.log('x', `${toFixed(x / boundingRect.width * maxX)}"`, 'y', `${toFixed(y / boundingRect.height * maxY)}"`);
let p = document.querySelector('polygon.firing-arc.active');
let activeFiringArc = document.querySelector('polygon.firing-arc.active');
// TODO: handle exactly horizontal and vertical lines
if (p) {
let {x: x1px, y: y1px} = p.points[1];
if (activeFiringArc) {
let {x: x1px, y: y1px} = activeFiringArc.points[0];
let [x2px, y2px] = [
pointerX / rect.width * maxXpx,
pointerY / rect.height * maxYpx
pointerX / boundingRect.width * maxXpx,
pointerY / boundingRect.height * maxYpx
];
let xDiff = x2px - x1px;
@ -142,7 +142,7 @@ rect.addEventListener('mousemove', e => {
console.log('angle:', `${toFixed(radToDeg(angle))}\u00B0`, `${angle}rad`);
let arcAngle = FIRING_ARC_SIZE[p.dataset.size];
let arcAngle = FIRING_ARC_SIZE[activeFiringArc.dataset.size];
let distance = Math.sqrt((x2px - x1px)**2 + (y2px - y1px)**2);
let yDelta = distance * Math.cos(angle) * Math.tan(arcAngle);
let xDelta = distance * Math.sin(angle) * Math.tan(arcAngle);
@ -179,8 +179,6 @@ rect.addEventListener('mousemove', e => {
} else {
cornerPoints = [[maxXpx, maxYpx], [0, maxYpx]];
}
points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2} ${cornerPoints[0]} ${cornerPoints[1]}`;
} else if (xDiff > 0 && yDiff < 0) {
if ((newY1 == 0 && newY2 == maxYpx) || (newY1 == maxYpx && newY2 == 0)) {
cornerPoints = [[maxXpx, 0], [maxXpx, maxYpx]];
@ -188,7 +186,7 @@ rect.addEventListener('mousemove', e => {
cornerPoints = [[0, 0], [maxXpx, 0]];
}
points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2} ${cornerPoints[0]} ${cornerPoints[1]}`;
// points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2} ${cornerPoints[0]} ${cornerPoints[1]}`;
} else if (xDiff < 0 && yDiff > 0) {
if ((newY1 == 0 && newY2 == maxYpx) || (newY1 == maxYpx && newY2 == 0)) {
cornerPoints = [[0, maxYpx], [0, 0]];
@ -196,7 +194,7 @@ rect.addEventListener('mousemove', e => {
cornerPoints = [[maxXpx, maxYpx], [0, maxYpx]];
}
points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2} ${cornerPoints[0]} ${cornerPoints[1]}`;
// points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2} ${cornerPoints[0]} ${cornerPoints[1]}`;
} else {
if ((newY1 == 0 && newY2 == maxYpx) || (newY1 == maxYpx && newY2 == 0)) {
cornerPoints = [[0, maxYpx], [0, 0]];
@ -204,10 +202,15 @@ rect.addEventListener('mousemove', e => {
cornerPoints = [[0, 0], [maxXpx, 0]];
}
points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2} ${cornerPoints[0]} ${cornerPoints[1]}`;
// points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2} ${cornerPoints[0]} ${cornerPoints[1]}`;
}
points = `${x1px},${y1px} ${newX1},${newY1} ${cornerPoints[1]} ${cornerPoints[0]} ${newX2},${newY2}`;
} else if (orthogonalEdgeConditions.some(e => e)) {
let cornerPoint;
let cornerPoints = [];
// console.log('x1px', x1px, 'y1px', y1px, 'x2px', x2px, 'y2px', y2px);
console.log('xDiff', xDiff, 'yDiff', yDiff);
if (newX1 == 0 || newX1 == maxXpx) {
cornerPoint = [newX1, newY2];
@ -215,12 +218,57 @@ rect.addEventListener('mousemove', e => {
cornerPoint = [newX2, newY1];
}
points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2} ${cornerPoint}`;
if (newX1 == 0 || newX1 == maxXpx) {
console.log(newX1, newY1, 'nearest corner point', newX1, yDiff > 0 ? maxYpx : 0);
} else {
console.log(newX1, newY1, 'nearest corner point', xDiff > 0 ? maxXpx : 0, newY1);
}
if (newX2 == 0 || newX2 == maxXpx) {
console.log(newX2, newY2, 'nearest corner point', newX2, yDiff > 0 ? maxYpx : 0);
} else {
console.log(newX2, newY2, 'nearest corner point', xDiff > 0 ? maxXpx : 0, newY2);
}
let cp1, cp2;
console.log('x1px, y1px', x1px, y1px);
console.log('newX1, newY1', newX1, newY1);
console.log('newX2, newY2', newX2, newY2);
if (newX1 == 0 || newX1 == maxXpx) {
cp1 = [newX1, yDiff > 0 ? maxYpx : 0];
} else {
cp1 = [xDiff > 0 ? maxXpx : 0, newY1];
}
if (newX2 == 0 || newX2 == maxXpx) {
cp2 = [newX2, yDiff > 0 ? maxYpx : 0];
} else {
cp2 = [xDiff > 0 ? maxXpx : 0, newY2];
}
console.log('cp1', cp1, 'cp2', cp2);
if (cp1[0] == cp2[0] && cp1[1] == cp2[1]) {
cornerPoints.push(cp1);
} else {
cornerPoints.push(cp1);
cornerPoints.push([xDiff > 0 ? maxXpx : 0, yDiff > 0 ? maxYpx : 0])
cornerPoints.push(cp2);
}
console.log(`${cornerPoints.join(' ')}`);
// points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2}`;
points = `${x1px},${y1px} ${newX1},${newY1} ${cornerPoints.join(' ')} ${newX2},${newY2}`;
console.log('points', points);
} else {
points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2}`;
points = `${x1px},${y1px} ${newX1},${newY1} ${newX2},${newY2}`;
}
p.setAttributeNS(null, 'points', points);
activeFiringArc.setAttributeNS(null, 'points', points);
}
});
@ -247,9 +295,7 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener('
`.firing-arc[data-troop-number="${troopNumber}"][data-troop-allegiance="${troopAllegiance}"]`
);
if (existingArcs.length > 0) {
existingArcs.forEach(el => el.remove());
}
existingArcs.forEach(el => el.remove());
let counter = document.querySelector(
`circle.counter[data-troop-number="${troopNumber}"][data-troop-allegiance="${troopAllegiance}"]`
@ -258,13 +304,13 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener('
if (counter) {
let arcLayer = document.getElementById('firing-arcs');
let placeFiringArcListener = e => {
let firingArcPlacementListener = e => {
document.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active'));
document.querySelector('circle#point').style.display = '';
rect.removeEventListener('click', placeFiringArcListener);
document.querySelector('circle#point').style.pointerEvents = 'auto';
map.removeEventListener('click', firingArcPlacementListener);
};
rect.addEventListener('click', placeFiringArcListener);
map.addEventListener('click', firingArcPlacementListener);
let pivotPoint = [counter.cx.baseVal.value, counter.cy.baseVal.value];
let firingArc = document.createElementNS(svgns, 'polygon');
@ -277,7 +323,7 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener('
arcLayer.prepend(firingArc);
document.querySelector('circle#point').style.display = 'none';
document.querySelector('circle#point').style.pointerEvents = 'none';
}
}
}));

View File

@ -7,8 +7,7 @@ body {
}
circle#point {
fill: black;
opacity: 0.1;
fill: transparent;
}
circle.counter[data-troop-allegiance="liao"] {
@ -33,8 +32,8 @@ rect#map {
opacity: 0;
}
polygon {
opacity: 0.33;
polygon.firing-arc {
opacity: 0.1;
}
button.set-firing-arc img {
@ -47,24 +46,6 @@ line.firing-arc {
opacity: 0.1;
}
polyline.firing-arc {
stroke: black;
stroke-width: 5px;
fill: none;
}
polygon#sml-arc {
fill: red;
}
polygon#med-arc {
fill: blue;
}
polygon#lrg-arc {
fill: green;
}
image#img1 {
transform: scale(3.41) rotate(-0.15deg);
/* opacity: 0.33; */
@ -89,10 +70,6 @@ image#img2 {
transform: scale(0.26) translate(-2in, -2in);
}
/* use[href="#point"] {
pointer-events: none;
} */
#asterisk {
font-size: 30;
}