gpt4 book ai didi

javascript - 用六边形填充圆(不同的方法)

转载 作者:技术小花猫 更新时间:2023-10-29 12:34:20 25 4
gpt4 key购买 nike

作为我之前的approach似乎不起作用,而且解决方案会相当复杂,我决定尝试另一种可能更简单的方法。

这一次,在代码绘制任何六边形之前,它必须确定预定义的圆中可以容纳多少行和列,然后根据此结果开始绘制所有六边形。

到目前为止它有点工作,但正如我以前的方法一样,有时六边形会重叠,或者在圆的下部留下很大的间隙。

另一个问题是,如何将这些六边形格式化为网格?

请注意, Canvas 下方有一个小 slider ,可让您增加/减少圆的半径并重新绘制六边形。

var c_el = document.getElementById("myCanvas");
var ctx = c_el.getContext("2d");

var canvas_width = c_el.clientWidth;
var canvas_height = c_el.clientHeight;
var circle = {
r: 120, /// radius
pos: {
x: (canvas_width / 2),
y: (canvas_height / 2)
}
}

var hexagon = {
r: 20,
pos:{
x: 0,
y: 0
}
}

var hex_w = hexagon.r * 2;
var hex_h = Math.floor( Math.sqrt(3) * hexagon.r );
var hex_s = (3/2) * hexagon.r;

fill_CircleWithHex( circle );

function fill_CircleWithHex(circle){
drawCircle( circle );

var c_h = circle.r * 2; /// circle height ////
var c_w = c_h; //// circle width /////

var max_hex_H = Math.round( c_h / hex_h );

var row_sizes = []
for(var row= 0; row< max_hex_H; row++){

var d = circle.r - ( row* hex_h); //// distance from circle's center to the row's chord ////
var c = 2 * (Math.sqrt((circle.r*circle.r) - (d * d))); /// length of the row's chord ////
var row_length = Math.floor(c / (hexagon.r * 3));
row_sizes.push( row_length )
}

console.log("circle_r : "+circle.r);
console.log("hex_r : "+hexagon.r);
console.log("max_hex_H : "+max_hex_H);
console.log("max_hex_W : ", row_sizes)

for(var row = 0; row < row_sizes.length; row++){
var max_hex_W = row_sizes[row];

var x_offset = Math.floor((c_w - (max_hex_W * hex_w)) / 2);

for(var col = 1; col < max_hex_W; col++){
hexagon.pos.x = (col * hex_w) + (circle.pos.x - circle.r) + x_offset ;
hexagon.pos.y = (row * hex_h) + (circle.pos.y - circle.r);
ctx.fillText(row+""+col, hexagon.pos.x - 6, hexagon.pos.y+4);
drawHexagon(hexagon)
}
}
}

function drawHexagon(hex){
var angle_deg, angle_rad, cor_x, cor_y;
ctx.beginPath();
for(var c=0; c <= 5; c++){
angle_deg = 60 * c;
angle_rad = (Math.PI / 180) * angle_deg;
cor_x = hex.r * Math.cos(angle_rad); //// corner_x ///
cor_y = hex.r* Math.sin(angle_rad); //// corner_y ///
if(c === 0){
ctx.moveTo(hex.pos.x+ cor_x, hex.pos.y+cor_y);
}else{
ctx.lineTo(hex.pos.x+cor_x, hex.pos.y+cor_y);
}
}
ctx.closePath();
ctx.stroke();
}

function drawCircle( circle ){
ctx.beginPath();
ctx.arc(circle.pos.x, circle.pos.y, circle.r, 0, 2 * Math.PI);
ctx.stroke();
}


$(function() {
$( "#slider" ).slider({
max: 200,
min:0,
value:100,
create: function( event, ui ) {
$("#value").html( $(this).slider('value') );
},
change: function( event, ui ) {
$("#value").html(ui.value);
},
slide: function( event, ui){
$("#value").html(ui.value);
circle.r = ui.value;
ctx.clearRect(0,0, canvas_width, canvas_height);
fill_CircleWithHex(circle);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>

<canvas id="myCanvas" width="350" height="250" style="border:1px solid #d3d3d3;"> </canvas>
<div style="width: 200px; height: 40px;">
<div id="slider" style="position:relative; width: 150px; top: 4px;float: left;"></div> <div id="value" style="float: left;"> 0 </div>
</div>

最佳答案

以下解决了以圆的中点为中心的规则蜂窝结构的填充问题。常规方式:

  • 所有六边形的集合在围绕圆心旋转 60 度的情况下是对称的。

各个六边形的坐标表示六边形壳从中心算起的序数和从正午开始的顺时针序号。

随着圆圈的扩大,新的六边形壳不一定会作为一个整体被填满。虽然部分填充外壳的自由度产生了改进的解决方案,但它仍然不是最优的。对于 60 度以外的其他 Angular (即 120 度和 180 度),放宽旋转对称的规律性将允许更高的圆内部覆盖率。

我将研究此代码的下一次修订背后的数学(并可能找到一个定理来证明围绕圆的中点旋转对称是最优的必要条件)。

var c_el;
var ctx;
var canvas_width;
var canvas_height;
var circle;
var hexagon;
var hex_w;
var hex_h;
var hex_s;
var delta;

function drawHexagonAt ( po_ctr_hex, pn_circle, pn_sector ) {
var cur
;

cur = { x: po_ctr_hex.x - 0.5 * hexagon.r, y: po_ctr_hex.y - delta };

ctx.beginPath();
ctx.moveTo(cur.x, cur.y);
cur.x = cur.x + hexagon.r;
cur.y = cur.y;
ctx.lineTo(cur.x, cur.y);
cur.x = cur.x + hexagon.r / 2;
cur.y = cur.y + delta;
ctx.lineTo(cur.x, cur.y);
cur.x = cur.x - hexagon.r / 2;
cur.y = cur.y + delta;
ctx.lineTo(cur.x, cur.y);
cur.x = cur.x - hexagon.r;
cur.y = cur.y;
ctx.lineTo(cur.x, cur.y);
cur.x = cur.x - hexagon.r / 2;
cur.y = cur.y - delta;
ctx.lineTo(cur.x, cur.y);
cur.x = cur.x + hexagon.r / 2;
cur.y = cur.y - delta;
ctx.lineTo(cur.x, cur.y);
ctx.closePath();
ctx.stroke();

cur.x = cur.x + hexagon.r / 2;
cur.y = cur.y + delta;
ctx.fillText(pn_circle + "/" + pn_sector, cur.x-6, cur.y+4);
} // drawHexagonAt

function fill_CircleWithHex(circle){
drawCircle( circle );

var radacc2;
var iter = 0;
var sector = 0;
var i, j;
var ctr = { x: circle.pos.x , y: circle.pos.y };
var cur = { x: 0 , y: 0 };

delta = Math.floor(Math.sqrt(3) * 0.5 * hexagon.r);
radacc2 = hexagon.r * hexagon.r;
while ( (radacc2 < circle.r * circle.r) ) {
cur.x = ctr.x;
cur.y = ctr.y - iter * 2 * delta;

if (iter === 0) {
drawHexagonAt ( cur, 0, 0 );
}
else {
for ( var i=0; i < 6; i++ ) {
// j-loops -- next honeycomb
sector = 0;
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x + 1.5 * hexagon.r;
cur.y = cur.y + delta;
drawHexagonAt ( cur, iter, sector++ );
}
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x;
cur.y = cur.y + 2 * delta;
drawHexagonAt ( cur, iter, sector++ );
}
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x - 1.5 * hexagon.r;
cur.y = cur.y + delta;
drawHexagonAt ( cur, iter, sector++ );
}
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x - 1.5 * hexagon.r;
cur.y = cur.y - delta;
drawHexagonAt ( cur, iter, sector++ );
}
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x;
cur.y = cur.y - 2 * delta;
drawHexagonAt ( cur, iter, sector++ );
}
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x + 1.5 * hexagon.r;
cur.y = cur.y - delta;
drawHexagonAt ( cur, iter, sector++ );
}
} // i-loop -- meta-honeycomb
} // if -- Iteration 1 vs. n > 1

// radacc update
iter++;
radacc2 = ((2*iter + 1) * delta) * ((2*iter + 1) * delta) + hexagon.r * hexagon.r / 4;
} // while -- komplette Shells

//
// Partielle Shells
//
var proceed;
do {
cur.x = ctr.x;
cur.y = ctr.y - iter * 2 * delta;
proceed = false;

for ( var i=0; i < 6; i++ ) {
// j-loops -- next honeycomb
sector = 0;
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x + 1.5 * hexagon.r;
cur.y = cur.y + delta;
sector++
if ( Math.sqrt ( ( cur.x - ctr.x) * ( cur.x - ctr.x) + ( cur.y - ctr.y) * ( cur.y - ctr.y) ) + hexagon.r < circle.r ) {
drawHexagonAt ( cur, iter, sector );
proceed = true;
}
}
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x;
cur.y = cur.y + 2 * delta;
sector++
if ( Math.sqrt ( ( cur.x - ctr.x) * ( cur.x - ctr.x) + ( cur.y - ctr.y) * ( cur.y - ctr.y) ) + hexagon.r < circle.r ) {
drawHexagonAt ( cur, iter, sector );
proceed = true;
}
}
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x - 1.5 * hexagon.r;
cur.y = cur.y + delta;
sector++
if ( Math.sqrt ( ( cur.x - ctr.x) * ( cur.x - ctr.x) + ( cur.y - ctr.y) * ( cur.y - ctr.y) ) + hexagon.r < circle.r ) {
drawHexagonAt ( cur, iter, sector );
proceed = true;
}
}
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x - 1.5 * hexagon.r;
cur.y = cur.y - delta;
sector++
if ( Math.sqrt ( ( cur.x - ctr.x) * ( cur.x - ctr.x) + ( cur.y - ctr.y) * ( cur.y - ctr.y) ) + hexagon.r < circle.r ) {
drawHexagonAt ( cur, iter, sector );
proceed = true;
}
}
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x;
cur.y = cur.y - 2 * delta;
sector++
if ( Math.sqrt ( ( cur.x - ctr.x) * ( cur.x - ctr.x) + ( cur.y - ctr.y) * ( cur.y - ctr.y) ) + hexagon.r < circle.r ) {
drawHexagonAt ( cur, iter, sector );
proceed = true;
}
}
for ( var j=0; j < iter; j++ ) {
cur.x = cur.x + 1.5 * hexagon.r;
cur.y = cur.y - delta;
sector++
if ( Math.sqrt ( ( cur.x - ctr.x) * ( cur.x - ctr.x) + ( cur.y - ctr.y) * ( cur.y - ctr.y) ) + hexagon.r < circle.r ) {
drawHexagonAt ( cur, iter, sector );
proceed = true;
}
}
} // i-loop -- meta-honeycomb

iter++;
} while (proceed && (iter < 15));

} // fill_CircleWithHex


function drawCircle( circle ){
ctx.beginPath();
ctx.arc(circle.pos.x, circle.pos.y, circle.r, 0, 2 * Math.PI);
ctx.stroke();
}


$(function() {
$( "#slider" ).slider({
max: 200,
min:0,
value:100,
create: function( event, ui ) {
$("#value").html( $(this).slider('value') );
},
change: function( event, ui ) {
$("#value").html(ui.value);
},
slide: function( event, ui){
$("#value").html(ui.value);
circle.r = ui.value;
ctx.clearRect(0,0, canvas_width, canvas_height);
fill_CircleWithHex(circle);
}
});
});

$(document).ready(function () {
c_el = document.getElementById("myCanvas");
ctx = c_el.getContext("2d");

canvas_width = c_el.clientWidth;
canvas_height = c_el.clientHeight;

circle = {
r: 120, /// radius
pos: {
x: (canvas_width / 2),
y: (canvas_height / 2)
}
};

hexagon = {
r: 20,
pos:{
x: 0,
y: 0
}
};

hex_w = hexagon.r * 2;
hex_h = Math.floor( Math.sqrt(3) * hexagon.r );
hex_s = (3/2) * hexagon.r;

fill_CircleWithHex( circle );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>

<canvas id="myCanvas" width="350" height="250" style="border:1px solid #d3d3d3;"> </canvas>
<div style="width: 200px; height: 40px;">
<div id="slider" style="position:relative; width: 150px; top: 4px;float: left;"></div> <div id="value" style="float: left;"> 0 </div>
</div>

关于javascript - 用六边形填充圆(不同的方法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35649685/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com