Avoid ovrelapping of points in technology radar - d3.js
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
Related
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
p5js- Uncaught TypeError: Cannot read property 'eats' of undefined (sketch: line 76)
Can someone please help me with what I'm doing wrong here. I'm completely new to programming, and am currently learning p5js at university. I'm trying to create 'cells' floating around in space, and when they hit each other they combine together. It works for a minute but then I get an error "Uncaught TypeError: Cannot read property 'eats' of undefined (sketch: line 76)" This is my code: function Cell(x, y, r) { this.x = x; this.y = y; this.r = r; this.speedx = random(-1, 1); this.speedy = random(-1, 1); this.width2 = 0.5; this.col = color(255); this.show = function() { fill(this.col); ellipse(this.x, this.y, this.r * 2); } this.move = function() { this.x = this.x + this.speedx; this.y = this.y + this.speedy; } this.bounce = function() { if (this.x > width || this.x < 0) { this.speedx = -this.speedx; } if (this.y > height || this.y < 0) { this.speedy = -this.speedy; } } // this.changeColor = function (){ //this.col = color(random(255), random (255), random(255)); //} this.eats = function(other) { var d = dist(this.x, this.y, other.x, other.y); if (d < this.r + other.r) { var sum = PI * this.r * this.r + PI * other.r * other.r; this.r = sqrt(sum / PI); //this.r += other.r; return true; } else { return false; } } // this.intersects = function(other){ // var d= dist(this.x, this.y, other.x, other.y); //if (d < this.r + other.r) { //var sum = PI * this.r * this.r + PI * other.r * other.r; //this.r = sqrt(sum / PI); //this.r += other.r; //return true; //} else { //return false; //} //} } var cells = []; function setup() { createCanvas(600, 600); for (var i = 0; i < 50; i++) { cells[i] = new Cell(random(width), random(height), 10); } } function draw() { background(0); for (var i = cells.length - 1; i >= 0; i--) { cells[i].show(); cells[i].move(); cells[i].bounce(); for (var j = cells.length - 1; j >= 0; j--) { if (j != i && cells[i].eats(cells[j])) { // cells[i].changeColor(); // cells[j].changeColor(); cells.splice(j, 1); } } } }
You are removing cells from cells array using cells.splice(j, 1);. So when it checks for that on next loop, its throwing error.
Random generator Rand9() using Rand3()
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();
WP7 SDK Pedometer
How to Create Pedometer in WP7 ?? i need create one Pedometer to study But i don't how to do Pedometer ? M = Math.Sqrt(args.X * args.X + args.Y * args.Y + args.Z * args.Z); if (Tec == true) { if (M >= 2) { if (Magnitude == true) { counter = counter + 1; Magnitude = false; } } else { Magnitude = true; } }
This works for me: private bool hasChanged; private int counter; private void checkIsMouvement(SensorReadingEventArgs<AccelerometerReading> e) { float x = e.get_SensorReading().get_Acceleration().X; float y = e.get_SensorReading().get_Acceleration().Y; float z = e.get_SensorReading().get_Acceleration().Z; double oldValue = ((x_old * x) + (y_old * y)) + (z_old * z); double oldValueSqrT = Math.Abs(Math.Sqrt((double) (((x_old * x_old) + (y_old * y_old)) + (z_old * z_old)))); double newValue = Math.Abs(Math.Sqrt((double) (((x * x) + (y * y)) + (z * z)))); oldValue /= oldValueSqrt * newValue; if ((oldValue <= 0.994) && (oldValue > 0.9)) { if (!hasChanged) { hasChanged = true; counter++; //here the counter } else { hasChanged = false; } } x_old = x; y_old = y; z_old = z; }