Fix corner finding algo for firing arc cone coverage

This commit is contained in:
Catalin Constantin Mititiuc 2025-06-16 22:41:28 -07:00
parent d5ae4253c8
commit 015bf03921
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", let svgns = "http://www.w3.org/2000/svg",
svg = document.querySelector('svg'), svg = document.querySelector('svg'),
rect = document.querySelector('rect#map'); map = document.querySelector('rect#map');
const COLUMN_COUNT = 33, const COLUMN_COUNT = 33,
ROW_COUNT = 25, ROW_COUNT = 25,
@ -108,24 +108,24 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
svg.appendChild(point); svg.appendChild(point);
})); }));
rect.addEventListener('mousemove', e => { map.addEventListener('mousemove', e => {
var rect = e.target.getBoundingClientRect(); let boundingRect = e.target.getBoundingClientRect();
var pointerX = e.clientX - rect.left; let pointerX = e.clientX - boundingRect.left;
var pointerY = e.clientY - rect.top; let pointerY = e.clientY - boundingRect.top;
let [maxXpx, maxYpx] = [e.target.width, e.target.height].map(v => v.baseVal.value); 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 // TODO: handle exactly horizontal and vertical lines
if (p) { if (activeFiringArc) {
let {x: x1px, y: y1px} = p.points[1]; let {x: x1px, y: y1px} = activeFiringArc.points[0];
let [x2px, y2px] = [ let [x2px, y2px] = [
pointerX / rect.width * maxXpx, pointerX / boundingRect.width * maxXpx,
pointerY / rect.height * maxYpx pointerY / boundingRect.height * maxYpx
]; ];
let xDiff = x2px - x1px; let xDiff = x2px - x1px;
@ -142,7 +142,7 @@ rect.addEventListener('mousemove', e => {
console.log('angle:', `${toFixed(radToDeg(angle))}\u00B0`, `${angle}rad`); 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 distance = Math.sqrt((x2px - x1px)**2 + (y2px - y1px)**2);
let yDelta = distance * Math.cos(angle) * Math.tan(arcAngle); let yDelta = distance * Math.cos(angle) * Math.tan(arcAngle);
let xDelta = distance * Math.sin(angle) * Math.tan(arcAngle); let xDelta = distance * Math.sin(angle) * Math.tan(arcAngle);
@ -179,8 +179,6 @@ rect.addEventListener('mousemove', e => {
} else { } else {
cornerPoints = [[maxXpx, maxYpx], [0, maxYpx]]; cornerPoints = [[maxXpx, maxYpx], [0, maxYpx]];
} }
points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2} ${cornerPoints[0]} ${cornerPoints[1]}`;
} else if (xDiff > 0 && yDiff < 0) { } else if (xDiff > 0 && yDiff < 0) {
if ((newY1 == 0 && newY2 == maxYpx) || (newY1 == maxYpx && newY2 == 0)) { if ((newY1 == 0 && newY2 == maxYpx) || (newY1 == maxYpx && newY2 == 0)) {
cornerPoints = [[maxXpx, 0], [maxXpx, maxYpx]]; cornerPoints = [[maxXpx, 0], [maxXpx, maxYpx]];
@ -188,7 +186,7 @@ rect.addEventListener('mousemove', e => {
cornerPoints = [[0, 0], [maxXpx, 0]]; 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) { } else if (xDiff < 0 && yDiff > 0) {
if ((newY1 == 0 && newY2 == maxYpx) || (newY1 == maxYpx && newY2 == 0)) { if ((newY1 == 0 && newY2 == maxYpx) || (newY1 == maxYpx && newY2 == 0)) {
cornerPoints = [[0, maxYpx], [0, 0]]; cornerPoints = [[0, maxYpx], [0, 0]];
@ -196,7 +194,7 @@ rect.addEventListener('mousemove', e => {
cornerPoints = [[maxXpx, maxYpx], [0, maxYpx]]; 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 { } else {
if ((newY1 == 0 && newY2 == maxYpx) || (newY1 == maxYpx && newY2 == 0)) { if ((newY1 == 0 && newY2 == maxYpx) || (newY1 == maxYpx && newY2 == 0)) {
cornerPoints = [[0, maxYpx], [0, 0]]; cornerPoints = [[0, maxYpx], [0, 0]];
@ -204,10 +202,15 @@ rect.addEventListener('mousemove', e => {
cornerPoints = [[0, 0], [maxXpx, 0]]; 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)) { } else if (orthogonalEdgeConditions.some(e => e)) {
let cornerPoint; 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) { if (newX1 == 0 || newX1 == maxXpx) {
cornerPoint = [newX1, newY2]; cornerPoint = [newX1, newY2];
@ -215,12 +218,57 @@ rect.addEventListener('mousemove', e => {
cornerPoint = [newX2, newY1]; 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 { } else {
points = `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2}`; console.log(newX1, newY1, 'nearest corner point', xDiff > 0 ? maxXpx : 0, newY1);
} }
p.setAttributeNS(null, 'points', points); 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}`;
}
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}"]` `.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( let counter = document.querySelector(
`circle.counter[data-troop-number="${troopNumber}"][data-troop-allegiance="${troopAllegiance}"]` `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) { if (counter) {
let arcLayer = document.getElementById('firing-arcs'); let arcLayer = document.getElementById('firing-arcs');
let placeFiringArcListener = e => { let firingArcPlacementListener = e => {
document.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active')); document.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active'));
document.querySelector('circle#point').style.display = ''; document.querySelector('circle#point').style.pointerEvents = 'auto';
rect.removeEventListener('click', placeFiringArcListener); map.removeEventListener('click', firingArcPlacementListener);
}; };
rect.addEventListener('click', placeFiringArcListener); map.addEventListener('click', firingArcPlacementListener);
let pivotPoint = [counter.cx.baseVal.value, counter.cy.baseVal.value]; let pivotPoint = [counter.cx.baseVal.value, counter.cy.baseVal.value];
let firingArc = document.createElementNS(svgns, 'polygon'); let firingArc = document.createElementNS(svgns, 'polygon');
@ -277,7 +323,7 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener('
arcLayer.prepend(firingArc); 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 { circle#point {
fill: black; fill: transparent;
opacity: 0.1;
} }
circle.counter[data-troop-allegiance="liao"] { circle.counter[data-troop-allegiance="liao"] {
@ -33,8 +32,8 @@ rect#map {
opacity: 0; opacity: 0;
} }
polygon { polygon.firing-arc {
opacity: 0.33; opacity: 0.1;
} }
button.set-firing-arc img { button.set-firing-arc img {
@ -47,24 +46,6 @@ line.firing-arc {
opacity: 0.1; 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 { image#img1 {
transform: scale(3.41) rotate(-0.15deg); transform: scale(3.41) rotate(-0.15deg);
/* opacity: 0.33; */ /* opacity: 0.33; */
@ -89,10 +70,6 @@ image#img2 {
transform: scale(0.26) translate(-2in, -2in); transform: scale(0.26) translate(-2in, -2in);
} }
/* use[href="#point"] {
pointer-events: none;
} */
#asterisk { #asterisk {
font-size: 30; font-size: 30;
} }