開発環境
- macOS Sierra - Apple (OS)
- Emacs (Text Editor)
- JavaScript (プログラミング言語)
- JavaScript Library
- Safari(Web browser)
- 参考書籍
- JavaScript 第6版 (David Flanagan(著)、村上 列(翻訳)、オライリージャパン)
- JavaScriptリファレンス 第6版(David Flanagan(著)、木下 哲也(翻訳)、オライリージャパン)
アルゴリズムパズル(Anany Levitin (著)、Maria Levitin (著)、黒川 洋 (翻訳)、松崎 公紀 (翻訳)、オライリージャパン)の中級パズル、64.(八角形の作成 (Creating Octagons))をJavaScriptで。
64.(八角形の作成 (Creating Octagons))
コード(Emacs)
HTML5
<div id="graph0"></div> <label for="n0">点の個数: n = </label> <input id="n0" type="number" min="8" step="8" value="40"> <button id="polygons">八角形を生成して描画</button> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.min.js" integrity="sha256-5idA201uSwHAROtCops7codXJ0vja+6wbBrZdQ6ETQc=" crossorigin="anonymous"></script> <script src="sample64.js"></script>
JavaScript
{
'use strict';
Array.range = function (start, end, step) {
var nums = [],
i;
if (step === 0) {
throw {
name: 'ValueError',
message: 'range() arg 3 must not be zero',
};
}
if (step === undefined) {
step = 1;
}
if (end === undefined) {
end = start;
start = 0;
}
if (step > 0) {
for (i = start; i < end; i += step) {
nums.push(i);
}
} else {
for (i = start; i > end; i += step) {
nums.push(i);
}
}
return nums;
};
let points,
svg,
width = 600,
height = 600,
padding = 50,
div_graph = document.querySelector('#graph0'),
input_n = document.querySelector('#n0'),
input_polygons = document.querySelector('#polygons');
let getPoints = (n) => {
let points = Array.range(n).map(
() => [Math.random() * (width - 1) + 1,
Math.random() * (height - 1) + 1]
);
points.sort((p1, p2) => {
let x1 = p1[0],
x2 = p2[0];
if (x1 === x2) {
return p1[1] - p2[1];
}
return x1 - x2;
});
return points;
};
let drawPoints = () => {
let n = parseInt(input_n.value, 10);
points = getPoints(n),
div_graph.innerHTML = '';
svg = d3.select('#graph0')
.append('svg')
.attr('width', width)
.attr('height', height);
svg.selectAll('circle')
.data(points)
.enter()
.append('circle')
.attr('cx', (d) => d[0])
.attr('cy', (d) => d[1])
.attr('r', 2)
.attr('fill', 'green');
};
let getLineFunc = (p1, p2) => {
let x1 = p1[0],
x2 = p2[0];
if (x1 === x2) {
throw {
name: '',
message: '',
};
}
let a = (p2[1] - p1[1]) / (x2 - x1);
return (x) => a * x - a * x1 + p1[1];
};
let drawPolygons = () => {
let polygons = [],
color = 'blue';
let polygon = [];
console.log(points);
points.forEach((p, i) => {
if (i % 8 === 7) {
let p0 = polygon.shift(),
func = getLineFunc(p0, p);
let ps1 = polygon.filter((p) => func(p[0])< p[1]),
ps2 = polygon.filter((p) => func(p[0])> p[1]);
ps1.sort((p1, p2) => p1[0] - p2[0]);
ps2.sort((p1, p2) => p2[0] - p1[0]);
polygons.push([p0].concat(ps1).concat([p]).concat(ps2));
polygon = [];
} else {
polygon.push(p);
}
});
console.log(polygons);
points = polygons.reduce((p1, p2) => p1.concat(p2), []);
svg.selectAll('line')
.data(points)
.enter()
.append('line')
.attr('x1', (d) => d[0])
.attr('y1', (d) => d[1])
.attr('x2', (d, i) => points[i + (i % 8 === 7 ? -7 : 1)][0])
.attr('y2', (d, i) => points[i + (i % 8 === 7 ? -7 : 1)][1])
.attr('stroke', (d, i) => {
if (i % 8 === 0) {
color =
color === 'red' ? 'green' :
color === 'green' ? 'blue' : 'red';
}
return color;
});
};
input_n.onchange = drawPoints;
polygons.onclick = drawPolygons;
drawPoints();
drawPolygons();
}
0 コメント:
コメントを投稿