It is important that the circle is filled using concentric passes
Non puoi disegnare nulla di "perfetto" usando "passaggi concentrici" sul sistema di coordinate cartesiane, che è in definitiva ciò che devi fare. I pixel non sono allineati con i cerchi con passaggio N. Tuttavia, puoi fare una buona approssimazione. E il metodo che usi dovrebbe dipendere dal tuo obiettivo finale.
... because i also update some metadata in the cells as I get them in
groups (each one corresponding to a circumference).
Questo suona come se avessi bisogno di operare punto per punto su tutti i punti in cui potrebbe essere parte del cerchio, determinando la "relazione con il centro" di ognuno mentre vai .
Quindi, quello che finirai con è qualcosa di molto simile alla soluzione di heltonbiker , ma che dipinge e / o imposta metadati per ogni punto al suo passaggio. Potresti volere due funzioni:
// a simple distance function
var distanceFrom = function(x, y, cx, cy) {
return Math.sqrt(
Math.pow(cx - x, 2) + Math.pow(cy - y, 2)
);
};
// something to determine the "value" of a pixel, based on the circle center
var getValue = function(x, y) {
// in your real application, these three vars will be parameters ...
var radius = 7;
var center_x = 7;
var center_y = 7;
var d = distanceFrom(x, y, center_x, center_y);
if (d <= radius) {
return d / radius;
} else {
return 1; // white/off
}
}; // getValue()
E un semplice loop ... da qualche parte in un metodo con nome appropriato:
// something that loops through all the relevant pixels.
// ... this does NOT need to look at every pixel. it only
// needs to look at the pixels within the box that bounds
// your circle.
for (var y = 0; y < 15; y++) {
for (var x = 0; x < 15; x++) {
paint(x, y, getValue(x, y));
}
}
Vedi questo violino , ingrandito di 32 per mostrare i "pixel".
Pensochepuoivederedalrisultatocheicerchiconcentriciforzanolecorrispondenzetrapixelecerchichesonosemplicementebrutti.L'approcciopixelperpixelnonsologarantiscecheognipixelsiavalutatoedisegnato,macheognipixelpossaessereassociatoalcerchiooalraggiopiùrilevanti.
Sestaicercandounoschemanonagradiente,devisoloaggiornarelafunzionevalore:
//alternating/concentric-ishcircles....vargetValue=function(x,y){varradius=7;varcenter_x=7;varcenter_y=7;vard=distanceFrom(x,y,center_x,center_y);if(d<=radius){returnMath.floor(d)%2===0?0:0.5;}else{return1;//white/off}};//getValue()
Visibile come violino qui . Ed ecco cosa produce:
E,naturalmente,sestaicercandodicolorareunsingolo"cerchio" che sia compatibile con le tue altre cerchie, potresti iniziare con l'approccio non ottimizzato della scansione dell'intera area del cerchio e disegnare solo i pixel di cui floored o arrotondato la distanza dal centro corrisponde a un raggio intero (o pavimentato / arrotondato).
var getValue = function(x, y) {
var radius = 7;
var center_x = 7;
var center_y = 7;
// the radius of the "circle" we're drawing (should be parametized)
var draw_only = 5;
var d = distanceFrom(x, y, center_x, center_y);
// the new condition is tacked on here:
if (d <= radius && Math.floor(d) === draw_only) {
return Math.floor(d) % 2 === 0 ? 0 : 0.5;
} else {
return 1; // white/off
}
}; // getValue()
Non è efficiente , ma gli anelli che disegna dovrebbero essere allineati con quelli dell'esempio con i colori alternati:
Vedi il violino .
Se stai cercando di fare quello che ho fatto nell'ultimo esempio, disegnando solo un singolo anello alla volta, può potenzialmente essere ottimizzato (per cerchi di grandi dimensioni) camminando attorno al cerchio e processando blocchi di pixel che sono "probabilmente" sta per essere colorato. Qualcosa simile a questo codice totalmente non testato ...
// radius of the circle we want to draw
var radius = 5;
for (var deg = 0; deg < 360; deg++) {
var radians = 2 * Math.PI * deg/360;
var focus_x = Math.floor(radius * Math.cos(radians));
var focus_y = Math.floor(radius * Math.sin(radians));
// i'm not sure how much "fuzz" you need ... play with it:
var x1 = focus_x - 2;
var x2 = focus_x + 2;
var y1 = focus_y - 2;
var y2 = focus_y + 2;
for (var y = y1; y < y2; y++) {
for (var x = x1; x < x2; x++) {
paint(x, y, getValue(x, y), radius); // again, radius needs to be parametized
}
}
}
Dichiarazione di non responsabilità: Né la presente risposta né il violino associato hanno lo scopo di dimostrare l'uso corretto o corretto di canvas HTML5 .