Skip to content

Commit 0dd235d

Browse files
committed
fix: enhance entry positioning with collision detection and fallback mechanism
1 parent 84feba6 commit 0dd235d

File tree

1 file changed

+71
-5
lines changed

1 file changed

+71
-5
lines changed

mkdocs_tech_radar/templates/radar_inline.html

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,11 @@ <h2>{{ title }}</h2>
531531
.attr("fill", textPrimary);
532532
});
533533

534-
// Function to get position for an entry
534+
// Function to get position for an entry with collision detection
535+
const usedPositions = [];
536+
const minDistance = 30; // Minimum distance between points
537+
const maxAttempts = 50; // Maximum attempts to find a non-overlapping position
538+
535539
function getEntryPosition(entry) {
536540
const quadrantIndex = entry.quadrant;
537541
const ringIndex = entry.ring;
@@ -540,13 +544,75 @@ <h2>{{ title }}</h2>
540544
const baseAngle = quadrantIndex * Math.PI / 2;
541545
const quadrantAngle = Math.PI / 2;
542546

543-
// Random angle within the quadrant
544-
const angle = baseAngle + (Math.random() - 0.5) * quadrantAngle * 0.8;
547+
// Calculate ring boundaries
548+
const innerRadius = ringIndex > 0 ? ringRadii[ringIndex - 1] : 0;
549+
const outerRadius = ringRadii[ringIndex];
550+
551+
let bestPosition = null;
552+
let attempts = 0;
553+
554+
while (attempts < maxAttempts) {
555+
// Generate random angle within the quadrant
556+
const angle = baseAngle + (Math.random() - 0.5) * quadrantAngle * 0.8;
557+
558+
// Generate random radius within the ring
559+
const entryRadius = innerRadius + (outerRadius - innerRadius) * (0.2 + Math.random() * 0.6);
560+
561+
const candidatePosition = {
562+
x: center.x + entryRadius * Math.cos(angle - Math.PI / 2),
563+
y: center.y + entryRadius * Math.sin(angle - Math.PI / 2)
564+
};
565+
566+
// Check for collisions with existing positions
567+
let hasCollision = false;
568+
for (const usedPos of usedPositions) {
569+
const distance = Math.sqrt(
570+
Math.pow(candidatePosition.x - usedPos.x, 2) +
571+
Math.pow(candidatePosition.y - usedPos.y, 2)
572+
);
573+
if (distance < minDistance) {
574+
hasCollision = true;
575+
break;
576+
}
577+
}
578+
579+
if (!hasCollision) {
580+
bestPosition = candidatePosition;
581+
break;
582+
}
583+
584+
attempts++;
585+
}
586+
587+
// If we couldn't find a collision-free position, use grid-based fallback
588+
if (!bestPosition) {
589+
bestPosition = getGridBasedPosition(quadrantIndex, ringIndex);
590+
}
591+
592+
// Store the position for future collision detection
593+
usedPositions.push(bestPosition);
594+
return bestPosition;
595+
}
596+
597+
// Fallback grid-based positioning for when collision detection fails
598+
function getGridBasedPosition(quadrantIndex, ringIndex) {
599+
const entriesInQuadrantRing = config.entries.filter(e =>
600+
e.quadrant === quadrantIndex && e.ring === ringIndex
601+
);
602+
const entryIndex = entriesInQuadrantRing.length;
603+
604+
// Calculate angle for the quadrant
605+
const baseAngle = quadrantIndex * Math.PI / 2;
606+
const quadrantAngle = Math.PI / 2;
607+
608+
// Distribute entries evenly within the quadrant
609+
const angleStep = quadrantAngle * 0.8 / Math.max(entriesInQuadrantRing.length + 1, 4);
610+
const angle = baseAngle - quadrantAngle * 0.4 + angleStep * (entryIndex + 1);
545611

546-
// Random radius within the ring
612+
// Calculate ring boundaries
547613
const innerRadius = ringIndex > 0 ? ringRadii[ringIndex - 1] : 0;
548614
const outerRadius = ringRadii[ringIndex];
549-
const entryRadius = innerRadius + (outerRadius - innerRadius) * (0.2 + Math.random() * 0.6);
615+
const entryRadius = innerRadius + (outerRadius - innerRadius) * 0.5;
550616

551617
return {
552618
x: center.x + entryRadius * Math.cos(angle - Math.PI / 2),

0 commit comments

Comments
 (0)