Random generator Rand9() using Rand3() - algorithm

How can I generate a number between 1 and 9 using a function which generate a number between 1 and 3? The probability to obtain any number between 1 and 9 must be the same, so rand3()+rand3()+rand3() is not a good solution.

Try cartesian-like product:
Rand9() = 3 * (Rand3() - 1) + Rand3()
With 3 * (Rand3() - 1) you make sub-intervals 1-3, 4-6 and 7-9 equally likely. With + Rand3() you will then choose equally on that sub-interval.
Written as a product:
3 * (Rand3() - 1) + Rand3() -> {1, 4, 7} X {+1,+2,+3} -> {1,2,3,4,5,6,7,8,9}

The main idea of the solution is to build 3*3 matrix.
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
function init() {
const rand3 = generateMathRandom(3);
let randFunc = rand3;
const start = 9;
const end = 10;
let i = start;
console.time('---start');
while (i < end) {
randFunc = generateRandom(i, 3, rand3);
healthCheck(i, randFunc);
i++;
}
console.timeEnd('---start');
i = start;
console.time('---start-math');
while (i < end) {
randFunc = generateMathRandom(i);
healthCheck(i, randFunc);
i++;
}
console.timeEnd('---start-math');
}
function generateMathRandom(range) {
return function () {
return Math.floor(Math.random() * range);
}
}
// range - target random range number : e.g 9
// lowerRange - base random range number : e.g 3
// func - function which generate random with the range of lowerRange : e.g rand3
function generateRandom(range, lowerRange, func) {
return function () {
const results = [];
let times = 1;
let matRange = lowerRange;
let mat = Math.sqrt(range);
while(mat > lowerRange) {
mat = Math.sqrt(mat);
times ++;
matRange *= lowerRange;
}
const noneStart = Math.floor(matRange * matRange / range) * range;
for (let i = 0; i < matRange; i++) {
results.push([]);
for (let j = 0; j < matRange; j++) {
const num = i * matRange + j;
if (num < noneStart)
results[i].push(num % range);
else
results[i].push(-1);
}
}
while (true) {
const row = new Array(times).fill(1).map(n => func()).reduce((a, c) => a * lowerRange + c, 0);
const col = new Array(times).fill(1).map(n => func()).reduce((a, c) => a * lowerRange + c, 0);
if (!results[row]) {
debugger;
}
if (results[row][col] == undefined) {
debugger;
}
if (results[row][col] === -1) continue;
return results[row][col];
}
}
}
function healthCheck(range, func = null, count = 100000) {
const funcToCheck = func || rand[range] || null;
if (!funcToCheck) {
console.log('Function is not provided');
return;
}
const health = new Array(range).fill(0);
const checkCount = count - count % range; // To do correct check.
for (let i = 0; i < checkCount; i++) {
health[funcToCheck()]++;
}
const result = health.map((cnt, index) => ({
_value: index,
rate: (cnt / checkCount * 100).toFixed(5)
}));
// console.log('Random result:', result);
let minRate = 100, maxRate = 0;
for (let i = 0; i < range; i++) {
minRate = Math.min(Number(result[i].rate), minRate);
maxRate = Math.max(Number(result[i].rate), maxRate);
}
console.log('Random health<' + range + '>: ' + healthOutput(range, maxRate - minRate));
}
function healthOutput(range, rangeOffset) {
const healthThreshold = 2; // It should be lower for the best Alghorithms
const threshold = healthThreshold;
if (rangeOffset < threshold * 0.2) {
return 'The Super! -> ' + rangeOffset.toFixed(5);
} else if (rangeOffset < threshold * 0.5) {
return 'The Best! --> ' + rangeOffset.toFixed(5);
} else if (rangeOffset < threshold * 1) {
return 'Good work! -> ' + rangeOffset.toFixed(5);
} else if (rangeOffset < threshold * 2) {
return 'Not bad! ---> ' + rangeOffset.toFixed(5);
}
return 'Worst! -----> ' + rangeOffset.toFixed(5);
}
init();

Related

Mix vertex and curveVertex in a shape?

I am trying to create a shape with both straight lines and curved parts. I want all points to connect and then to fill the interior with a color. I cannot seem to locate this information or a way to do it in a single shape. Is there a way to do this? For example a rectangle with an inverted curve on each end? I can do it with arcs and lines like the below code but I have to think there is an easier way using beginShape somehow or something similar? Also even using the lines and arcs, I am not sure how to fill it.
arc(200, 200, 150, 150, radians(0), radians(90), OPEN);
arc(200, 200, 50, 50, radians(0), radians(90), OPEN);
let x1 = 200 + Math.cos(radians(0)) * 25;
let y1 = 200 + Math.sin(radians(0)) * 25;
let x2 = 200 + Math.cos(radians(90)) * 25;
let y2 = 200 + Math.sin(radians(90)) * 25;
let x3 = 200 + Math.cos(radians(0)) * 75;
let y3 = 200 + Math.sin(radians(0)) * 75;
let x4 = 200 + Math.cos(radians(90)) * 75;
let y4 = 200 + Math.sin(radians(90)) * 75;
line(x1, y1, x3, y3)
line(x2, y2, x4, y4)
This should answer part of your question experimentally. As you can see by playing with the sketch below, if there is a single curveVertex() in the shape all of the vertices created with vertex() will also be treated as curveVertex() type vertices.
I think you should be able to achieve your goal with bezierVertex().
const InteractionThreshold = 5;
const SqInteractionThreshold = InteractionThreshold * InteractionThreshold;
function lineEditor(p) {
let controlPoints = [{
x: 50,
y: 50,
type: 'vertex'
},
{
x: 250,
y: 250,
type: 'vertex'
},
];
p.setup = () => {
p.createCanvas(300, 300);
p.rectMode(p.RADIUS);
p.ellipseMode(p.RADIUS);
p.noFill();
p.noLoop();
};
p.draw = () => {
p.background(200);
p.beginShape();
for (let i = 0; i < controlPoints.length; i++) {
let pt = controlPoints[i];
switch (pt.type) {
case 'vertex':
p.vertex(pt.x, pt.y);
break;
case 'curve':
p.curveVertex(pt.x, pt.y);
break;
}
}
p.endShape();
p.push();
p.stroke('green');
p.drawingContext.setLineDash([5, 15]);
p.beginShape();
for (let i = 0; i < controlPoints.length; i++) {
let pt = controlPoints[i];
p.vertex(pt.x, pt.y);
}
p.endShape();
p.drawingContext.setLineDash([]);
p.pop();
p.push();
p.fill("red");
p.noStroke();
for (let i = 0; i < controlPoints.length; i++) {
let pt = controlPoints[i];
switch (pt.type) {
case 'curve':
p.circle(pt.x, pt.y, 4);
break;
case 'vertex':
p.push();
p.translate(pt.x, pt.y);
p.rotate(p.PI / 4);
p.square(0, 0, 4);
p.pop();
break;
}
}
p.pop();
};
let dragging;
p.mousePressed = function() {
// is the mouse over a point
let closest = getClosest(p.mouseX, p.mouseY);
if (closest && closest.sqdist < SqInteractionThreshold) {
dragging = closest.ix;
}
};
p.mouseReleased = function() {
dragging = undefined;
};
p.mouseDragged = function() {
if (dragging !== undefined) {
controlPoints[dragging].x = p.constrain(p.mouseX, 0, p.width);
controlPoints[dragging].y = p.constrain(p.mouseY, 0, p.height);
p.redraw();
}
};
p.mouseClicked = function() {
if (p.keyIsDown(p.SHIFT)) {
// is the mouse over a point
let closest = getClosest(p.mouseX, p.mouseY);
if (closest && closest.sqdist < SqInteractionThreshold) {
let pt = controlPoints[closest.ix];
switch (pt.type) {
case 'vertex':
pt.type = 'curve';
break;
case 'curve':
pt.type = 'vertex';
break;
}
p.redraw();
}
}
}
p.doubleClicked = function() {
if (p.keyIsDown(p.SHIFT)) {
if (controlPoints.length > 2) {
// delete
let closest = getClosest(p.mouseX, p.mouseY);
if (closest && closest.sqdist < SqInteractionThreshold) {
controlPoints.splice(closest.ix, 1);
p.redraw();
}
}
} else {
// insert
let closest = getClosestSegment(p.mouseX, p.mouseY);
if (closest.error < InteractionThreshold) {
controlPoints.splice(closest.end, 0, {
x: p.mouseX,
y: p.mouseY,
type: 'vertex'
});
p.redraw();
}
}
};
function getClosest(x, y) {
let closest;
for (let i = 0; i < controlPoints.length; i++) {
let dx = x - controlPoints[i].x;
let dy = y - controlPoints[i].y;
let sqdist = dx * dx + dy * dy;
if (!closest || sqdist < closest.sqdist) {
closest = {
sqdist,
ix: i
};
}
}
return closest;
}
function getClosestSegment(x, y) {
let closest;
for (let i = 0; i < controlPoints.length - 1; i++) {
let start = controlPoints[i];
let end = controlPoints[i + 1];
let angle = p.atan2(end.y - start.y, end.x - start.x);
let len = p.dist(start.x, start.y, end.x, end.y);
// convert [mouseX, mouseY] to a position relative to start
let vec = p.createVector(x - start.x, y - start.y);
vec = p.createVector(
p.cos(angle) * vec.x + p.sin(angle) * vec.y, -p.sin(angle) * vec.x + p.cos(angle) * vec.y,
);
let error;
if (vec.x < 0) {
error = p.dist(0, 0, vec.x, vec.y);
} else if (vec.x > len) {
error = p.dist(len, 0, vec.x, vec.y);
} else {
// There is no X error, only consider the Y
error = p.abs(vec.y);
}
if (!closest || error < closest.error) {
closest = {
error,
start: i,
end: i + 1
};
}
}
return closest;
}
}
let lineEditorSketch = new p5(lineEditor);
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

Determine the next point on the Bézier curve based on the straight-line distance from the previous point

I need to keep the same distance between the balls on the Bézier curve. Now I'm using a simple iteration of possible positions on the curve, adding some step amount for each iteration until position with required distance, greater or equal, is found.
It works, but can be resource-intensive when there are a large amount of balls. CodeSandbox
class TestScene extends Phaser.Scene {
create() {
// prettier-ignore
const curve = new Phaser.Curves.QuadraticBezier(
[
55, 310,
40, 0,
250, 310
]
);
const graphicsLayer = this.add.graphics({
lineStyle: {
width: 2,
color: 0x0000ff
}
});
curve.draw(graphicsLayer);
const balls = this.initBalls(6);
this.curve = curve;
this.balls = balls;
}
initBalls(quantity) {
const balls = [];
for (let i = 0; i < quantity; i++) {
const ball = this.add.circle(0, 0, 12, 0x00ff00);
ball.t = 0;
balls.push(ball);
}
return balls;
}
calcNextBallT(previous) {
const ballDiameter = previous.radius * 2;
const curve = this.curve;
const curveLen = curve.getLength();
const previousPos = new Phaser.Math.Vector2(previous);
const previousT = previous.t;
const startingT = (1 / curveLen) * ballDiameter + previousT;
const step = 1 / 1000;
let nextT = startingT;
let nextPos;
let currentDistance = 0;
while (nextT >= 0 && nextT <= 1) {
nextPos = curve.getPointAt(nextT);
currentDistance = previousPos.distance(nextPos);
if (currentDistance >= ballDiameter) {
break;
}
nextT += step;
}
return nextT;
}
update() {
const {
curve,
balls
} = this;
if (!curve || !balls) {
return;
}
const speed = 1;
const curveLen = curve.getLength();
const step = (1 / curveLen) * speed;
balls.forEach((ball, index, array) => {
let nextT = ball.t;
if (index === 0) {
nextT += step;
if (nextT > 1) {
nextT = 0;
}
} else {
const previous = array[index - 1];
nextT = this.calcNextBallT(previous);
}
ball.t = nextT;
ball.copyPosition(curve.getPointAt(nextT));
});
}
}
const game = new Phaser.Game({
width: 320,
height: 320,
powerPreference: 'low-power',
audio: {
noAudio: true
},
scene: [TestScene]
});
<script src="https://unpkg.com/phaser#3.55.2/dist/phaser.min.js"></script>
I think maybe there is a mathematical or algorithmic solution. Something like finding the intersection of a larger circle with a curve, but as I understood it is impossible.
Is there a better way to determine the next point on the Bézier curve based on the straight-line distance from the previous point?
UPDATE 1: A solution using Binary Search, as suggested by #MBo, shows good stability with an average of 5-10 iterations, even with varying curves and ball sizes. CodeSandbox
class TestScene extends Phaser.Scene {
init() {
this.input.on('drag', (pointer, gameObject, dragX, dragY) => {
gameObject.setPosition(dragX, dragY);
});
this.iters = [];
}
create() {
// prettier-ignore
const p0 = this.add.circle(55, 310, 4, 0xffff00),
p1 = this.add.circle(40, 5, 4, 0xffff00),
p2 = this.add.circle(250, 310, 4, 0xffff00);
const curve = new Phaser.Curves.QuadraticBezier(p0, p1, p2);
const graphicsLayer = this.add.graphics({
lineStyle: {
width: 2,
color: 0x0000ff
}
});
curve.draw(graphicsLayer);
const curveDragHandler = () => {
curve.updateArcLengths();
graphicsLayer.clear();
curve.draw(graphicsLayer);
};
[p0, p1, p2].forEach((p) => {
p.setDepth(10).setInteractive();
this.input.setDraggable(p);
p.on('drag', curveDragHandler);
});
const balls = this.initBalls(3, 50);
const text = this.add.text(0, 0, '', {
color: 'yellow'
});
this.curve = curve;
this.balls = balls;
this.text = text;
}
initBalls(quantity, diameter) {
const radius = diameter / 2;
const balls = [];
for (let i = 0; i < quantity; i++) {
const ball = this.add.circle(0, 0, radius, 0x00ff00);
ball.t = 0;
balls.push(ball);
}
return balls;
}
calcNextBallT(previous) {
const ballDiameter = previous.radius * 2;
const curve = this.curve;
const previousPos = new Phaser.Math.Vector2(previous);
const previousT = previous.t;
let nextT = 1;
let lowT = previousT;
let highT = 1;
let iter = 1;
const skip = previousPos.distance(curve.getEndPoint()) <= ballDiameter;
while (lowT <= highT && !skip) {
nextT = lowT + (highT - lowT) / 2;
const nextPos = curve.getPointAt(nextT);
const currentDistance = previousPos.distance(nextPos);
if (fuzzySame(currentDistance, ballDiameter)) {
break;
}
if (currentDistance > ballDiameter) {
highT = nextT;
} else {
lowT = nextT;
}
iter++;
}
if (!skip) {
this.iters.push(iter);
}
return nextT;
}
update() {
const {
curve,
balls
} = this;
if (!curve || !balls) {
return;
}
const speed = 1;
const curveLen = curve.getLength();
const step = (1 / curveLen) * speed;
balls.forEach((ball, index, array) => {
let nextT = ball.t;
if (index === 0) {
nextT += step;
if (nextT > 1) {
const average = findAverage(this.iters).toFixed(2);
const maximum = findMaximum(this.iters);
this.text.setText(`Average: ${average}\nMaximum: ${maximum}`);
this.iters = [];
nextT = 0;
}
} else {
const previous = array[index - 1];
nextT = this.calcNextBallT(previous);
}
ball.t = nextT;
ball.copyPosition(curve.getPointAt(nextT));
});
}
}
const fuzzySame = (num1, num2) => {
const tolerance = 0.2;
return num1 >= num2 - tolerance && num1 <= num2 + tolerance;
};
const findAverage = (array) => {
const len = array.length;
let total = 0;
array.forEach((num) => (total += num));
return total / len;
};
const findMaximum = (array) => {
return [...array].sort((a, b) => b - a)[0];
};
const game = new Phaser.Game({
width: 320,
height: 320,
powerPreference: 'low-power',
audio: {
noAudio: true
},
scene: [TestScene]
});
<script src="https://unpkg.com/phaser#3.55.2/dist/phaser.min.js"></script>
Instead of straight iterations use binary search over t range.
Math solution requires solving equation of 6-th degree (for cubic curve) - there is no closed formula, so one needs to use numerical methods (iterations again)

How to access a value in a array

I need to access the wall array inside the C variable. I can find what c is, but not what any specific value of c. I probably made a mistake of how to access the value from this array, but I tried to do c[3], and it always says undefined. This is the full program link https://editor.p5js.org/Meowmeow/sketches/b4AhGA4xH.
function index(i, j) {
if (i < 0 || j < 0 || i > cols - 1 || j > cols - 1) {
return -1;
}
return i + j * cols
}
function Cell(i, j) {
this.visited = false;
this.i = i;
this.j = j;
this.walls = [true, true, true, true];
this.checkNeighbors = function() {
var neighbors = []
var top = grid[index(i, j - 1)]
var right = grid[index(i + 1, j)]
var left = grid[index(i - 1, j)]
var bottom = grid[index(i, j + 1)]
var Wall = this.walls;
var wall=[]
wall.push(i,j,Wall)
if (top && !top.visited) {
neighbors.push(top);
}
if (right && !right.visited) {
neighbors.push(right);
}
if (bottom && !bottom.visited) {
neighbors.push(bottom);
}
if (left && !left.visited) {
neighbors.push(left);
}
if (neighbors.length > 0) {
var r = floor(random(0, neighbors.length))
return neighbors[r];
} else {
return undefined;
}
}
this.highlight = function() {
var x = this.i * w;
var y = this.j * w;
noStroke();
fill(0, 0, 255, 100)
rect(x, y, w, w);
}
this.show = function() {
var x = this.i * w;
var y = this.j * w;
stroke(255);
noFill();
if (this.walls[0]) {
line(x, y, x + w, y);
}
if (this.walls[1]) {
line(x + w, y, x + w, y + w);
}
if (this.walls[2]) {
line(x + w, y + w, x, y + w);
}
if (this.walls[3]) {
line(x, y + w, x, y);
}
if (this.visited) {
fill(255, 0, 255, 100);
noStroke();
rect(x, y, w, w);
}
}
};
function removeWalls(a, b) {
var x = a.i - b.i;
if (x === 1) {
a.walls[3] = false;
b.walls[1] = false;
} else if (x === -1) {
a.walls[1] = false;
b.walls[3] = false;
}
var y = a.j - b.j;
if (y === 1) {
a.walls[0] = false;
b.walls[2] = false;
} else if (y === -1) {
a.walls[2] = false;
b.walls[0] = false;
}
}
function draw() {
background(51);
for (var i = 0; i < grid.length; i++) {
grid[i].show()
}
//Step One
current.visited = true;
current.highlight();
var next = current.checkNeighbors()
if (next) {
next.visited = true;
//Step 2
stack.push(current);
check.push(current)
//Step 3
removeWalls(current, next)
{}
//Step 4
current = next;
} else if (stack.length > 0) {
current = stack.pop();
}
if (stack[0] === undefined) {
fill(0, 105, 100)
rect(0, 0, w, w)
rect(width - w, height - w, w, w)
frameRate(8)
var c = check.find(cell => cell.i == ~~(k/w) && cell.j == ~~(m/w));
console.log(c)
if(c===undefined)
I'm not sure if I needed to put in this much of the code, but I didn't want to leave anything important out.
You're definitely on the right track.
I would just finish that check to see if a cell has been found before attempting to access the walls property. For example:
if(c===undefined){
console.log('no cell found');
}else{
console.log('i',c.i,'j', c.j,'walls', c.walls);
}
as you press the arrow keys you should see different cell row/col indices and walls.

Recursive division does not guarantee a path

I implemented the algorithm from the answer in here Maze (recursive division) algorithm design.
but I ran into a problem that there isn't always a path from start(+) to finish(-)
like this image.
also there is another problem that the start(+) or finish(-) node will be surrounded by wall see start node (+)
but I think it's easy to fix.
remove the walls around that node [x-1][y], [x][y+1], [x+1][y] and [x][y-1].
I don't know if it's the right fix or not.
that's my maze class
class Maze {
private G: INode[][];
private rows: number;
private cols: number;
constructor(G: INode[][]) {
this.G = G.map((row) =>
row.map((node) => ({
...node,
isWall: false,
}))
);
this.rows = this.G.length;
this.cols = this.G[0].length;
// border walls
for (let i = 0; i < this.rows; i++) {
this.G[i][0].isWall = true;
this.G[i][this.cols - 1].isWall = true;
}
for (let i = 0; i < this.cols; i++) {
this.G[0][i].isWall = true;
this.G[this.rows - 1][i].isWall = true;
}
}
private rand(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
private isNodeStartOrFinish(row: number, col: number) {
return this.G[row][col].isStart || this.G[row][col].isFinish;
}
// call perfectMaze to get the generate the maze
public perfectMaze() {
this.divide(true, 1, this.cols - 2, 1, this.rows - 2);
}
private divide(
h: boolean,
minX: number,
maxX: number,
minY: number,
maxY: number
) {
if (h) {
if (maxX - minX < 2) return;
const y = Math.floor(this.rand(minY, maxY) / 2) * 2;
this.addHWall(minX, maxX, y);
this.divide(!h, minX, maxX, minY, y - 1);
this.divide(!h, minX, maxX, y + 1, maxY);
} else {
if (maxY - minY < 2) return;
const x = Math.floor(this.rand(minX, maxX) / 2) * 2;
this.addVWall(minY, maxY, x);
this.divide(!h, minX, x - 1, minY, maxY);
this.divide(!h, x + 1, maxX, minY, maxY);
}
}
private addHWall(minX: number, maxX: number, y: number) {
const hole = Math.floor(this.rand(minX, maxX) / 2) * 2 + 1;
for (let i = minX; i <= maxX; i++) {
if (i !== hole && !this.isNodeStartOrFinish(y, i)) {
this.G[y][i].isWall = true;
}
}
}
private addVWall(minY: number, maxY: number, x: number) {
const hole = Math.floor(this.rand(minY, maxY) / 2) * 2 + 1;
for (let i = minY; i <= maxY; i++) {
if (i !== hole && !this.isNodeStartOrFinish(i, x)) {
this.G[i][x].isWall = true;
}
}
}
public getMaze() {
return this.G;
}
}
okay i was stupid
i didn't remove the wall when i === hole
in the addHWall and addVWall methods
you must delete the wall if i === hole otherwise the wall will be added again
private addHWall(minX: number, maxX: number, y: number) {
const hole = Math.floor(this.rand(minX, maxX) / 2) * 2 + 1;
for (let i = minX; i <= maxX; i++) {
if (i === hole || this.isNodeStartOrFinish(y, i)) {
this.G[y][i].isWall = false;
} else {
this.G[y][i].isWall = true;
}
}
}
the same with addVWall
if (i === hole || this.isNodeStartOrFinish(i, x)) {
this.G[y][i].isWall = false;
} else {
this.G[i][x].isWall = true;
}
and i ended up deleting the walls around the start and finish node still don't know if it's the right solution or not

Avoid ovrelapping of points in technology radar

I am creating my own technology radar, for this I have downloaded the code from : https://github.com/trecenti/tech-radar
I have customized it as per my needs. In this I have modified "tech-radar.min.js" file to make it as per my requirements.
Now, one thing I am still unable to modify that is overlapping of points in the circle. As per my study the placement of points are according to the title of the point and chance.integer function.
I want to modify in a way so that points will not overlap.
Code of my index file is :
<body>
<div id="radar">
</div>
<div id="ref-table"></div>
</body>
<script>
var adopt = new tr.models.Cycle('Adopt', 0);
var trial = new tr.models.Cycle('Trial', 1);
var assess = new tr.models.Cycle('Assess', 2);
var hold = new tr.models.Cycle('Hold', 3);
var radar = new tr.models.Radar();
var toolsQuadrant = new tr.models.Quadrant('Tools');
var techniquesQuadrant = new tr.models.Quadrant('Techniques');
var platformsQuadrant = new tr.models.Quadrant('Platforms');
var languageFramework = new tr.models.Quadrant('Languages & Frameworks');
toolsQuadrant.add([
new tr.models.Blip('D3', adopt),
new tr.models.Blip('Dependency Management for JavaScript', adopt, true),
new tr.models.Blip('Ansible', trial, true),
new tr.models.Blip('Calabash', trial, true),
new tr.models.Blip('Chaos Monkey', trial, true),
new tr.models.Blip('Gatling', trial),
new tr.models.Blip('Grunt.js', trial, true),
new tr.models.Blip('Hystrix', trial),
new tr.models.Blip('Icon fonts', trial),
new tr.models.Blip('Librarian-puppet and Librarian-Chef', trial),
new tr.models.Blip('Logstash & Graylog2', trial),
new tr.models.Blip('Moco', trial, true),
new tr.models.Blip('PhantomJS', trial),
new tr.models.Blip('Prototype On Paper', trial, true),
new tr.models.Blip('SnapCI', trial, true),
new tr.models.Blip('Snowplow Analytics & Piwik', trial),
new tr.models.Blip('Cloud-init', assess, true),
new tr.models.Blip('Docker', assess, true),
new tr.models.Blip('Octopus', assess),
new tr.models.Blip('Sensu', assess, true),
new tr.models.Blip('Travis for OSX/iOS', assess, true),
new tr.models.Blip('Visual regression testing tools', assess, true),
new tr.models.Blip('Xamarin', assess, true),
new tr.models.Blip('Ant', hold, true),
new tr.models.Blip('Heavyweight test tools', hold),
new tr.models.Blip('TFS', hold)
]);
techniquesQuadrant.add([
new tr.models.Blip('Capturing client-side JavaScript errors', adopt),
new tr.models.Blip('Continuous delivery for mobile devices', adopt),
new tr.models.Blip('Mobile testing on mobile networks', adopt),
new tr.models.Blip('Segregated DOM plus node for JS Testing', adopt, true),
new tr.models.Blip('Windows infrastructure automation', adopt),
new tr.models.Blip('Capture domain events explicitily', trial, true),
new tr.models.Blip('Client and server rendering with same code', trial, true),
new tr.models.Blip('HTML5 storage instead of cookies', trial),
new tr.models.Blip('Instrument all the things', trial, true),
new tr.models.Blip('Masterless Chef/Puppet', trial, true),
new tr.models.Blip('Micro-services', trial),
new tr.models.Blip('Perimeterless enterprise', trial),
new tr.models.Blip('Provisioning testing', trial, true),
new tr.models.Blip('Structured logging', trial, true),
new tr.models.Blip('Bridging physical and digital worlds with simple hardware', assess, true),
new tr.models.Blip('Collaborative analytics and data science', assess),
new tr.models.Blip('Datensparsamkeit', assess, true),
new tr.models.Blip('Development environments in the cloud', assess),
new tr.models.Blip('Focus on mean time to recovery', assess),
new tr.models.Blip('Machine image as a build artifact', assess),
new tr.models.Blip('Tangible interaction', assess, true),
new tr.models.Blip('Cloud lift and shift', hold, true),
new tr.models.Blip('Ignoring OWASP Top 10', hold, true),
new tr.models.Blip('Siloed metrics', hold, true),
new tr.models.Blip('Velocity as productivity', hold, true)
]);
platformsQuadrant.add([
new tr.models.Blip('Elastic Search', adopt),
]);
languageFramework.add([
new tr.models.Blip('Clojure', adopt, true),
]);
radar.setFirstQuadrant(toolsQuadrant);
radar.setSecondQuadrant(techniquesQuadrant);
radar.setThirdQuadrant(platformsQuadrant);
radar.setFourthQuadrant(languageFramework);
var radarGraph = new tr.graphing.Radar(1080, radar);
radarGraph.init('#radar').plot();
var refTable = new tr.graphing.RefTable(radar);
refTable.init('#ref-table').render();
</script>
and tech-radar.min.js file is :
var tr = tr || {};
tr.models = {}, tr.graphing = {}, tr.util = {}, tr.graphing.Radar = function(t, n) {
function r() {
return Math.round(t / 2)
}
function e() {
p.append("line").attr("x1", r()).attr("y1", 0).attr("x2", r()).attr("y2", t).attr("stroke-width", 14), p.append("line").attr("x1", 0).attr("y1", r()).attr("x2", t).attr("y2", r()).attr("stroke-width", 14)
}
function a(t, n) {
var e = (l.sequence(t.length), l.sum(t.length)),
a = l.sum(n);
return r() - r() * a / e
}
function u(t) {
t.forEach(function(n, e) {
p.append("circle").attr("cx", r()).attr("cy", r()).attr("r", a(t, e))
})
}
function c(t) {
var n;
n = Math.round(r() / t.length), t.forEach(function(n, e) {
p.append("text").attr("class", "line-text").attr("stroke", "#000000").attr("stroke-width", "0.3").attr("y", r() + 4).attr("x", r() - a(t, e) + 10).text(n.name()), p.append("text").attr("class", "line-text").attr("stroke", "#000000").attr("stroke-width", "0.3").attr("y", r() + 4).attr("x", r() + a(t, e) - 10).attr("text-anchor", "end").text(n.name())
})
}
function o(t, n, r, e) {
var a, u, c, o, i, s;
return a = 13, u = n - a, c = t - a + 1, o = t + a + 1, i = n + a - a / 2.5, s = t + 1 + "," + u + " " + c + "," + i + " " + o + "," + i, (e || p).append("polygon").attr("points", s).attr("class", r).attr("stroke-width", 1.5)
}
function i(t, n, r, e) {
return (e || p).append("circle").attr("cx", t).attr("cy", n).attr("class", r).attr("stroke-width", 1.5).attr("r", 10)
}
function s(t, n, e, u, c) {
var s;
s = n.blips(), t.forEach(function(n, f) {
var d, l, I;
d = a(t, f), l = f == t.length - 1 ? 0 : a(t, f + 1);
var I = s.filter(function(t) {
return t.cycle() == n
});
I.forEach(function(t) {
var a, s, f = t.name().split(""),
I = f.reduce(function(t, n) {
return t + n.charCodeAt(0)
}, 0);
/*var randomNumber = chance.integer({
min: 7,
max: 42
});
var evenNumber = randomNumber * 2;
console.log(evenNumber);*/
chance = new Chance(I * n.name().length * t.number()), a = Math.PI * chance.integer({
min: 13,
max: 85
}) / 180, s = chance.floating({
min: l + 25,
max: d - 10
});
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u,
v = p.append("g").attr("class", "blip-group").attr("id","diagram"+t.number()).attr("onmouseover", "mouseoverfunction("+t.number()+")").attr("onmouseout", "mouseoutfunction("+t.number()+")");
t.isNew() ? o(m, y, c, v) : i(m, y, c, v), h.push(function() {
/* var n;
n = p.append("div").attr("x", m + 15).attr("y", y + 4).attr("class", "blip-name").attr("text-anchor", "left").text(t.name()), v.on("mouseover", function() {
n.style("display", "block")
}).on("mouseout", function() {
n.style("display", "none")
})*/
document.body.innerHTML +='<div class="d3-tip blip-name" id='+t.number()+' style="position:absolute;top:'+(y-15)+'px;left:'+m+'px;">'+t.name()+'</div>';
}), v.append("text").attr("x", m).attr("y", y + 4).attr("id","point"+t.number()).attr("class", "blip-text").attr("text-anchor", "middle").text(t.number())
})
})
}
function f(n) {
function r(t, n, r, e, a) {
p.append("text").attr("x", r).attr("y", e).attr("class", a).attr("text-anchor", n).text(t)
}
r(n.I.name(), "end", t - 10, 10, "first"), r(n.II.name(), "start", 10, 10, "second"), r(n.III.name(), "start", 10, t - 10, "third"), r(n.IV.name(), "end", t - 10, t - 10, "fourth")
}
var d, l, p, h;
return h = [], l = new tr.util.Fib, d = {}, d.svg = function() {
return p
}, d.init = function(t) {
return p = d3.select(t || "body").append("svg"), d
}, d.plot = function() {
var r, a;
r = n.cycles().reverse(), a = n.quadrants(), p.attr("width", t).attr("height", t), u(r), e(), c(r), n.hasQuadrants() && (f(a), s(r, a.I, 1, -1, "first"), s(r, a.II, -1, -1, "second"), s(r, a.III, -1, 1, "third"), s(r, a.IV, 1, 1, "fourth")), h.forEach(function(t) {
t()
})
}, d
}, tr.graphing.RefTable = function(t) {
function n() {
var n = {};
t.cycles().map(function(t) {
return {
order: t.order(),
name: t.name()
}
}).sort(function(t, n) {
return t.order === n.order ? 0 : t.order < n.order ? -1 : 1
}).forEach(function(t) {
n[t.name] = []
});
var r = [],
e = t.quadrants();
return Object.keys(e).forEach(function(t) {
r = r.concat(e[t].blips())
}), r.forEach(function(t) {
n[t.cycle().name()].push(t)
}), n
}
var r, e = {};
return e.init = function(t) {
return r = document.querySelector(t || "body"), e
}, e.render = function() {
var t = n(),
/*e = '<table class="radar-ref-table">';
Object.keys(t).forEach(function(n) {
e += '<tr class="radar-ref-status-group"><td colspan="3">' + n + "</td></tr>", t[n].forEach(function(t) {
var newValue = t.isNew();
if(newValue==true){
var newText = '<span class="newText" style="background-color: rgba(179,32,89,.3);color: #0000;padding: 0 4px;border-radius: 2px; margin-left: 3px;">new</span>';
}else{
var newText = '';
}
e += "<tr onmouseover='mouseoverfunction("+t.number()+")' onmouseout='mouseoutfunction("+t.number()+")' onclick='onclickfunction("+t.number()+")' id=table"+t.number()+"><td>" + t.number() + "</td><td>" + t.name() + newText +"</td></tr>"
e += "<tr class='description-row' id=description"+t.number()+" style='display:none;'><td style='border-top:1px solid;'> </td><td style='border-top:1px solid;'>" + t.description() + "</td></tr>"
})
}),
e += "</table>", r.innerHTML = e*/
e = '<div class="radar-ref-table accordion">';
Object.keys(t).forEach(function(n) {
if(n=='Adopt'){
tooltipText = 'Abopt description';
}
if(n=='Trial'){
tooltipText = 'Trial description';
}
if(n=='Assess'){
tooltipText = 'Assess description';
}
if(n=='Hold'){
tooltipText = 'Hold description';
}
e += '<div class="radar-ref-status-group">' + n + "<div class='tooltip'><span class='tooltip-icon'>?</span><span class='tooltiptext'>"+tooltipText+"</span></div></div>", t[n].forEach(function(t) {
var newValue = t.isNew();
if(newValue=='true'){
var newText = '<span class="newText" style="background-color: rgba(179,32,89,.3);color: #0000;padding: 0 4px;border-radius: 2px; margin-left: 3px;">new</span>';
}else{
var newText = '';
}
e += "<div onmouseover='mouseoverfunction("+t.number()+")' onmouseout='mouseoutfunction("+t.number()+")' id=table"+t.number()+"><a class='accordion-section-title' href='#accordion-"+t.number()+"'>"+t.number()+ ". " + t.name() + newText +"</a>"
e += "<div id='accordion-"+t.number()+"' class='accordion-section-content '><p>"+t.description()+"</p></div></div>"
})
}),
e += "</div>", r.innerHTML = e
}, e
}, tr.models.Blip = function(t, n, r, e) {
var a, u;
return a = {}, u = -1, a.name = function() {
return t
}, a.description = function() {
return e || ""
}, a.isNew = function() {
return r
}, a.cycle = function() {
return n
}, a.number = function() {
return u
}, a.setNumber = function(t) {
u = t
}, a
}, tr.models.Cycle = function(t, n) {
var r = {};
return r.name = function() {
return t
}, r.order = function() {
return n
}, r
}, tr.models.Quadrant = function(t) {
var n, r;
return n = {}, r = [], n.name = function() {
return t
}, n.add = function(t) {
Array.isArray(t) ? r = r.concat(t) : r.push(t)
}, n.blips = function() {
return r.slice(0)
}, n
}, tr.models.Radar = function() {
function t(t) {
t.forEach(function(t) {
t.setNumber(++u)
})
}
function n() {
var t = [];
for (var n in a) a.hasOwnProperty(n) && null != a[n] && t.push(a[n]);
return t
}
function r() {
return n().reduce(function(t, n) {
return t.concat(n.blips())
}, [])
}
var e, a, u;
return u = 0, a = {
I: null,
II: null,
III: null,
IV: null
}, e = {}, e.setFirstQuadrant = function(n) {
a.I = n, t(a.I.blips())
}, e.setSecondQuadrant = function(n) {
a.II = n, t(a.II.blips())
}, e.setThirdQuadrant = function(n) {
a.III = n, t(a.III.blips())
}, e.setFourthQuadrant = function(n) {
a.IV = n, t(a.IV.blips())
}, e.hasQuadrants = function() {
return !!(a.I || a.II || a.III || a.IV)
}, e.cycles = function() {
var t, n;
n = [], t = {}, r().forEach(function(n) {
t[n.cycle().name()] = n.cycle()
});
for (var e in t) t.hasOwnProperty(e) && n.push(t[e]);
return n.slice(0).sort(function(t, n) {
return t.order() - n.order()
})
}, e.quadrants = function() {
return a
}, e
}, tr.util.Fib = function() {
var t = {};
return t.sequence = function(t) {
for (var n = [0, 1], r = 2; t > r; r++) n[r] = n[r - 2] + n[r - 1];
return n
}, t.sum = function(n) {
return 0 === n ? 0 : 1 === n ? 1 : t.sequence(n + 1).reduce(function(t, n) {
return t + n
}, 0)
}, t
};
If somebody have the idea about that code, please help me to avoid this overlapping. As I am not a javascript expert, an expert can solve it.
You can download the code from https://github.com/trecenti/tech-radar . Just run the index.html file which is inside example folder in your browser and try avoiding the overlapping of points.
It will be a great as I have already spent too many hours on it but no luck.
Thanks
I have modified the JS file to avoid overlapping of points. To do this just open your "tech-radar.min.js" file and file the below code :
d = a(t, f), l = f == t.length - 1 ? 0 : a(t, f + 1);
var I = s.filter(function(t) {
return t.cycle() == n
});
I.forEach(function(t) {
var a, s, f = t.name().split(""),
I = f.reduce(function(t, n) {
return t + n.charCodeAt(0)
}, 0);
/*var randomNumber = chance.integer({
min: 7,
max: 42
});
var evenNumber = randomNumber * 2;
console.log(evenNumber);*/
chance = new Chance(I * n.name().length * t.number()), a = Math.PI * chance.integer({
min: 13,
max: 85
}) / 180, s = chance.floating({
min: l + 25,
max: d - 10
});
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u,
Now, replace the above code with the below mentioned :
//new variables for workaround solution - BEGIN
aa = 0, bb = 0, cc = 0, dd = 0,
aa1 = 1, bb1 = 1, cc1 = 1, dd1 = 1,
ee = 0, ff = 0, gg = 0, hh = 0,
ee1 = 1, ff1 = 1, gg1 = 1, hh1 = 1,
ii = 0, jj = 0, kk = 0, ll = 0,
ii1 = 1, jj1 = 1, kk1 = 1, ll1 = 1,
oo = 0, pp = 0, qq = 0, rr = 0,
oo1 = 1, pp1 = 1, qq1 = 1, rr1 = 1,
xy1 = 20, xy2 = 20, xy3 = 30, xy4 = 50,
xy5 = 20, xy6 = 40, xy7 = 30, xy8 = 50,
xy9 = 50, xy10 = 40, xy11 = 30, xy12 = 50,
xy13 = 50, xy14 = 40, xy15 = 30, xy16 = 50,
yz1 = 300, yz2 = 250, yz3 = 250, yz4 = 200;
//new variables for workaround solution - END
d = a(t, f), l = f == t.length - 1 ? 10 : a(t, f + 1);
var I = s.filter(function(t) {
return t.cycle() == n
});
//New loop - BEGIN
I.forEach(function(t) {
if (c == "first" && n.name()== "Hold")
{
aa = aa + 1;
}
else if (c == "first" && n.name()== "Assess")
{
bb = bb + 1;
}
else if (c == "first" && n.name()== "Trial")
{
cc = cc + 1;
}
else if (c == "first" && n.name()== "Adopt")
{
dd = dd + 1;
}
else if (c == "second" && n.name()== "Hold")
{
ee = ee + 1;
}
else if (c == "second" && n.name()== "Assess")
{
ff = ff + 1;
}
else if (c == "second" && n.name()== "Trial")
{
gg = gg + 1;
}
else if (c == "second" && n.name()== "Adopt")
{
hh = hh + 1;
}
else if (c == "third" && n.name()== "Hold")
{
ii = ii + 1;
}
else if (c == "third" && n.name()== "Assess")
{
jj = jj + 1;
}
else if (c == "third" && n.name()== "Trial")
{
kk = kk + 1;
}
else if (c == "third" && n.name()== "Adopt")
{
ll = ll + 1;
}
else if (c == "fourth" && n.name()== "Hold")
{
oo = oo + 1;
}
else if (c == "fourth" && n.name()== "Assess")
{
pp = pp + 1;
}
else if (c == "fourth" && n.name()== "Trial")
{
qq = qq + 1;
}
else if (c == "fourth" && n.name()== "Adopt")
{
rr = rr + 1;
}
})
//New loop - END
I.forEach(function(t) {
var a, s, f = t.name().split(""),
I = f.reduce(function(t, n) {
return t + n.charCodeAt(0)
}, 0);
// New conditional statements - BEGIN
if (c == "first" && n.name()== "Hold")
{
if (aa1 == 1)
{
s = ((l + d) / 2) + 10;
}
else if (aa1 == 2)
{
s = (l + d) / 2;
}
else if (aa1 == 3)
{
s = ((l + d) / 2) - 10;
}
a = xy1 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy1 = xy1 + (yz1 / aa);
aa1 = aa1 + 1;
if (aa1 > 3)
{
aa1 = 1;
}
}
else if (c == "first" && n.name()== "Assess")
{
if (bb1 == 1)
{
s = ((l + d) / 2) + 10;
}
else if (bb1 == 2)
{
s = (l + d) / 2;
}
else if (bb1 == 3)
{
s = ((l + d) / 2) - 10;
}
a = xy2 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy2 = xy2 + (yz2 / bb);
bb1 = bb1 + 1;
if (bb1 > 3)
{
bb1 = 1;
}
}
else if (c == "first" && n.name()== "Trial")
{
if (cc1 == 1)
{
s = ((l + d) / 2) + 30;
}
else if (cc1 == 2)
{
s = (l + d) / 2;
}
else if (cc1 == 3)
{
s = ((l + d) / 2) - 30;
}
a = xy3 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy3 = xy3 + (yz2 / cc);
cc1 = cc1 + 1;
if (cc1 > 3)
{
cc1 = 1;
}
}
else if (c == "first" && n.name()== "Adopt")
{
if (dd1 == 1)
{
s = ((l + d) / 2) + 30;
}
else if (dd1 == 2)
{
s = (l + d) / 2;
}
else if (dd1 == 3)
{
s = ((l + d) / 2) - 30;
}
a = xy4 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy4 = xy4 + (yz4 / dd);
dd1 = dd1 + 1;
if (dd1 > 3)
{
dd1 = 1;
}
}
else if (c == "second" && n.name()== "Hold")
{
if (ee1 == 1)
{
s = ((l + d) / 2) + 10;
}
else if (ee1 == 2)
{
s = (l + d) / 2;
}
else if (ee1 == 3)
{
s = ((l + d) / 2) - 10;
}
a = xy5 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy5 = xy5 + (yz1 / ee);
ee1 = ee1 + 1;
if (ee1 > 3)
{
ee1 = 1;
}
}
else if (c == "second" && n.name()== "Assess")
{
if (ff1 == 1)
{
s = ((l + d) / 2) + 10;
}
else if (ff1 == 2)
{
s = (l + d) / 2;
}
else if (ff1 == 3)
{
s = ((l + d) / 2) - 10;
}
a = xy6 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy6 = xy6 + (yz2/ ff);
ff1 = ff1 + 1;
if (ff1 > 3)
{
ff1 = 1;
}
}
else if (c == "second" && n.name()== "Trial")
{
if (gg1 == 1)
{
s = ((l + d) / 2) + 30;
}
else if (gg1 == 2)
{
s = (l + d) / 2;
}
else if (gg1 == 3)
{
s = ((l + d) / 2) - 30;
}
a = xy7 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy7 = xy7 + (yz3 / gg);
gg1 = gg1 + 1;
if (gg1 > 3)
{
gg1 = 1;
}
}
else if (c == "second" && n.name()== "Adopt")
{
if (hh1 == 1)
{
s = ((l + d) / 2) + 30;
}
else if (hh1 == 2)
{
s = (l + d) / 2;
}
else if (hh1 == 3)
{
s = ((l + d) / 2) - 30;
}
a = xy8 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy8 = xy8 + (yz4 / hh);
hh1 = hh1 + 1;
if (hh1 > 3)
{
hh1 = 1;
}
}
else if (c == "third" && n.name()== "Hold")
{
if (ii1 == 1)
{
s = ((l + d) / 2) + 10;
}
else if (ii1 == 2)
{
s = (l + d) / 2;
}
else if (ii1 == 3)
{
s = ((l + d) / 2) - 10;
}
a = xy9 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy9 = xy9 + (yz1 / ii);
ii1 = ii1 + 1;
if (ii1 > 3)
{
ii1 = 1;
}
}
else if (c == "third" && n.name()== "Assess")
{
if (jj1 == 1)
{
s = ((l + d) / 2) + 10;
}
else if (jj1 == 2)
{
s = (l + d) / 2;
}
else if (jj1 == 3)
{
s = ((l + d) / 2) - 10;
}
a = xy10 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy10 = xy10 + (yz2 / jj);
jj1 = jj1 + 1;
if (jj1 > 3)
{
jj1 = 1;
}
}
else if (c == "third" && n.name()== "Trial")
{
if (kk1 == 1)
{
s = ((l + d) / 2) + 30;
}
else if (kk1 == 2)
{
s = (l + d) / 2;
}
else if (kk1 == 3)
{
s = ((l + d) / 2) - 30;
}
a = xy11 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy11 = xy11 + (yz3 / kk);
kk1 = kk1 + 1;
if (kk1 > 3)
{
kk1 = 1;
}
}
else if (c == "third" && n.name()== "Adopt")
{
if (ll1 == 1)
{
s = ((l + d) / 2) + 30;
}
else if (ll1 == 2)
{
s = (l + d) / 2;
}
else if (ll1 == 3)
{
s = ((l + d) / 2) - 30;
}
a = xy12 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy12 = xy12 + (yz4 / ll);
ll1 = ll1 + 1;
if (ll1 > 3)
{
ll1 = 1;
}
}
else if (c == "fourth" && n.name()== "Hold")
{
if (oo1 == 1)
{
s = ((l + d) / 2) + 10;
}
else if (oo1 == 2)
{
s = (l + d) / 2;
}
else if (oo1 == 3)
{
s = ((l + d) / 2) - 10;
}
a = xy13 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy13 = xy13 + (yz1 / oo);
oo1 = oo1 + 1;
if (oo1 > 3)
{
oo1 = 1;
}
}
else if (c == "fourth" && n.name()== "Assess")
{
if (pp1 == 1)
{
s = ((l + d) / 2) + 10;
}
else if (pp1 == 2)
{
s = (l + d) / 2;
}
else if (pp1 == 3)
{
s = ((l + d) / 2) - 10;
}
a = xy14 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy14 = xy14 + (yz2 / pp);
pp1 = pp1 + 1;
if (pp1 > 3)
{
pp1 = 1;
}
}
else if (c == "fourth" && n.name()== "Trial")
{
if (qq1 == 1)
{
s = ((l + d) / 2) + 30;
}
else if (qq1 == 2)
{
s = (l + d) / 2;
}
else if (qq1 == 3)
{
s = ((l + d) / 2) - 30;
}
a = xy15 / 180;
m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy15 = xy15 + (yz3 / qq) ;
qq1 = qq1 + 1;
if (qq1 > 3)
{
qq1 = 1;
}
}
else if (c == "fourth" && n.name()== "Adopt")
{
if (rr1 == 1)
{
s = ((l + d) / 2) + 30;
}
else if (rr1 == 2)
{
s = (l + d) / 2;
}
else if (rr1 == 3)
{
s = ((l + d) / 2) - 30;
}
a = xy16 / 180;
var m = r() + s * Math.cos(a) * e,
y = r() + s * Math.sin(a) * u;
xy16 = xy16 + (yz4 / rr);
rr1 = rr1 + 1;
if (rr1 > 3)
{
rr1 = 1;
}
}
Once you replace the code as mentioned above, just look at the points they are not overlapping to each other.
This is a lengthy approach, anyone can optimize it but it will solve the overlapping issue.
I am using the above mentioned approach which can help someone to get rid of this overlapping. But if anybody has an idea of any other better approach to avoid this overlapping, please share.
Thanks

Resources