Canvas Draws Points it should not draw - javascript

Consider the following snippet: Why are there visible points outside the rectangle?
Is the switching of the context color slower than the drawing of the rectangle?
const templateCanvas = document.getElementById( "template" );
const tctx = templateCanvas.getContext( "2d" );
tctx.fillStyle = "red";
tctx.fillRect( 300, 300, 200, 200 )
const canvas = document.getElementById( "canvas" );
const ctx = canvas.getContext( "2d" );
const max = {
x: 800,
y: 800
};
const sites = [];
const points = 10000;
for ( let i = 0; i < points; i++ ) sites.push( {
x: Math.floor( Math.random() * max.x ),
y: Math.floor( Math.random() * max.y )
} );
const c = ( alpha ) => 'rgba(255,0,0,' + alpha + ')';
const c2 = ( alpha ) => {
let colors = [
'rgba(78,9,12,' + alpha + ')',
'rgba(161,34,19,' + alpha + ')',
'rgba(171,95,44,' + alpha + ')',
'rgba(171,95,44,' + alpha + ')',
'rgba(252,160,67,' + alpha + ')'
]
return colors[ Math.round( Math.random() * colors.length ) ];
}
sites.forEach( p => {
let imgData = tctx.getImageData( p.x, p.y, 1, 1 ).data;
ctx.fillStyle = ( imgData[ 0 ] == 255 ) ? c2( 1 ) : c2( 0 );
ctx.fillRect( p.x, p.y, 2, 2 )
} );
<canvas id="canvas" width="800" height="800"></canvas>
<canvas id="template" width="800" height="800"></canvas>

I think what's happening is that your random color function sometimes returns an invalid color, because it's fetching from an undefined array element. That's caused by the use of Math.round() instead of Math.floor():
return colors[ Math.round( Math.random() * colors.length ) ];
Because of that, every once in a while a bad color expression will be used for the fill style, and that will be ignored by the canvas mechanism. Thus you get some dots outside the area covered by red pixels (the square).

Related

Making and connecting hexagons on a rectangle grid

I am creating a pathfinding application and I want to connect every hexgon(H) to its adjacent hexagons. The grid is a rectangle but it is populated with hexagons. The issue is the code right now to connect these hexagons is lengthy and extremely finicky. An example of what i am trying to achieve is:
The issue is that the connections between say one hexagon and its neighbours (range from 2-6 depending on their placement in the grid) is not working properly. An example of the code i am using right now to connect a hexagon with 6 neighbours is:
currentState.graph().addEdge(i, i + 1, 1);
currentState.graph().addEdge(i, i - HexBoard.rows + 1, 1);
currentState.graph().addEdge(i, i - HexBoard.rows, 1);
currentState.graph().addEdge(i, i + HexBoard.rows +1, 1);
currentState.graph().addEdge(i, i + HexBoard.rows , 1);
The graph is essetialy the grid, addEdge adds a connection from src ->dest with cost(c) in order. Is there any algorithm or way to make my code less bulky ? (right now it is polluted with if-else clauses)?
The site which inspired me :https://clementmihailescu.github.io/Pathfinding-Visualizer/#
EDIT : The problem is not in drawing hexagons (They are already SVGs), it in assigning them edges and connections.
Interesting problem... To set a solid foundation, here's a hexagon grid class that is neither lengthy nor finicky, based on a simple data structure of a linear array. A couple of notes...
The HexagonGrid constructor accepts the hexagon grid dimensions in terms of the number of hexagons wide (hexWidth) by number of hexagons high (hexHeight).
The hexHeight alternates by an additional hexagon every other column for a more pleasing appearance. Thus an odd number for hexWidth bookends the hexagon grid with the same number of hexagons in the first and last columns.
The length attribute represents the total number of hexagons in the grid.
Each hexagon is referenced by a linear index from 0..length.
The hexagonIndex method which takes (x,y) coordinates returns an the linear index based on an approximation of the closest hexagon. Thus, when near the edges of a hexagon, the index returned might be a close neighbor.
Am not totally satisfied with the class structure, but is sufficient to show the key algorithms involved in a linear indexed hexagon grid.
To aid in visualizing the linear indexing scheme, the code snippet displays the linear index value in the hexagon. Such an indexing scheme offers the opportunity to have a parallel array of the same length which represents the characteristics of each specific hexagon by index.
Also exemplified is the ability to translate from mouse coordinates to the hexagon index, by clicking on any hexagon, which will redraw the hexagon with a thicker border.
const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
class HexagonGrid {
constructor( hexWidth, hexHeight, edgeLength ) {
this.hexWidth = hexWidth;
this.hexHeight = hexHeight;
this.edgeLength = edgeLength;
this.cellWidthPair = this.hexHeight * 2 + 1;
this.length = this.cellWidthPair * ( hexWidth / 2 |0 ) + hexHeight * ( hexWidth % 2 );
this.dx = edgeLength * Math.sin( Math.PI / 6 );
this.dy = edgeLength * Math.cos( Math.PI / 6 );
}
centerOfHexagon( i ) {
let xPairNo = i % this.cellWidthPair;
return {
x: this.dx + this.edgeLength / 2 + ( i / this.cellWidthPair |0 ) * ( this.dx + this.edgeLength ) * 2 + ( this.hexHeight <= i % this.cellWidthPair ) * ( this.dx + this.edgeLength ),
y: xPairNo < this.hexHeight ? ( xPairNo + 1 ) * this.dy * 2 : this.dy + ( xPairNo - this.hexHeight ) * this.dy * 2
};
}
hexagonIndex( point ) {
let col = ( point.x - this.dx / 2 ) / ( this.dx + this.edgeLength ) |0;
let row = ( point.y - ( col % 2 === 0 ) * this.dy ) / ( this.dy * 2 ) |0;
let hexIndex = ( col / 2 |0 ) * this.cellWidthPair + ( col % 2 ) * this.hexHeight + row;
//console.log( `(${point.x},${point.y}): col=${col} row=${row} hexIndex=${hexIndex}` );
return ( 0 <= hexIndex && hexIndex < this.length ? hexIndex : null );
}
edge( i ) {
let topCheck = i % ( this.hexHeight + 0.5 );
return (
i < this.hexHeight
|| ( i + 1 ) % ( this.hexHeight + 0.5 ) === this.hexHeight
|| i % ( this.hexHeight + 0.5 ) === this.hexHeight
|| ( i + 1 ) % ( this.hexHeight + 0.5 ) === 0
|| i % ( this.hexHeight + 0.5 ) === 0
|| this.length - this.hexHeight < i
);
}
drawHexagon( ctx, center, lineWidth ) {
let halfEdge = this.edgeLength / 2;
ctx.lineWidth = lineWidth || 1;
ctx.beginPath();
ctx.moveTo( center.x - halfEdge, center.y - this.dy );
ctx.lineTo( center.x + halfEdge, center.y - this.dy );
ctx.lineTo( center.x + halfEdge + this.dx, center.y );
ctx.lineTo( center.x + halfEdge, center.y + this.dy );
ctx.lineTo( center.x - halfEdge, center.y + this.dy );
ctx.lineTo( center.x - halfEdge - this.dx, center.y );
ctx.lineTo( center.x - halfEdge, center.y - this.dy );
ctx.stroke();
}
drawGrid( ctx, topLeft ) {
ctx.font = '10px Arial';
for ( let i = 0; i < this.length; i++ ) {
let center = this.centerOfHexagon( i );
this.drawHexagon( ctx, { x: topLeft.x + center.x, y: topLeft.y + center.y } );
ctx.fillStyle = this.edge( i ) ? 'red' : 'black';
ctx.fillText( i, topLeft.x + center.x - 5, topLeft.y + center.y + 5 );
}
}
}
let myHexGrid = new HexagonGrid( 11, 5, 20 );
let gridLeftTop = { x: 20, y: 20 };
myHexGrid.drawGrid( ctx, gridLeftTop );
canvas.addEventListener( 'mousedown', function( event ) {
let i = myHexGrid.hexagonIndex( { x: event.offsetX - gridLeftTop.x, y: event.offsetY - gridLeftTop.y } );
if ( i !== null ) {
let center = myHexGrid.centerOfHexagon( i );
myHexGrid.drawHexagon( ctx, { x: gridLeftTop.x + center.x, y: gridLeftTop.y + center.y }, 3 );
}
} );
<canvas id=canvas width=1000 height=1000 />
A large benefit of the linear index is that it makes path searching easier, as each interior hexagon is surrounded by hexagons with relative indexes of -1, -6, -5, +1, +6, +5. For example, applying the relative indexes to hexagon 18 results in a list of surrounding hexagons of 17, 12, 13, 19, 24, 23.
As a bonus, the edge method indicates whether the hexagon is on the edge of the grid. (In the code snippet, the edge cells are identified by red text.) Highly recommend that edge cells not be part of the pathing (ie, they are unreachable) as this simplifies any path searching. Otherwise the pathing logic becomes very complex, as now if on an edge cell, the relative indexes indicating the surrounding hexagons no longer fully apply...

Js, HTML, and CSS to make matrix rainbow rain not working

https://codepen.io/deathshadow8123/pen/KKNaLXq That is my pen from codepen, however when I create an html doc, and put the js into a tag and the css into a tag it doesn't show up on the webpage I also put the in there. Pls help me I do not know how to make this work. Any ideas?
if you can't access codepen here is my code:
var w = c.width = window.innerWidth,
h = c.height = window.innerHeight,
ctx = c.getContext( '2d' ),
opts = {
chars: '\1234567890ìqwertyuiopè+asdfghjklòàù<zxcvbnm,.-|!"£$%&/()=?^QWERTYUIOPé*ASDFGHJKLç°§>ZXCVBNM;:_[]##€{}'.split(''), // every key in the italian keyboard layout. It sucks, we don't even have a backtick!
font: '12px monospace',
charSize: 14,
lineHeight: 14,
hueSpeed: 1,
repaintAlpha: .1,
stripesParXxY: .1,
stripeSpeed: .5,
beforeSpawning: 50
},
tick = 0,
endX = ( w / opts.charSize + 1 ) |0,
endY = ( h / opts.lineHeight + 1 ) |0,
sum = w + h,
stripes = [];
ctx.font = opts.font;
ctx.fillStyle = '#111';
ctx.fillRect( 0, 0, w, h );
function loop() {
window.requestAnimationFrame( loop );
tick += opts.hueSpeed;
ctx.fillStyle = 'rgba(0,0,0,alp)'.replace( 'alp', opts.repaintAlpha );
ctx.fillRect( 0, 0, w, h );
stripes.map( function( stripe ){ stripe.step(); } );
}
function Stripe(){
this.reset();
}
Stripe.prototype.reset = function() {
this.x = ( Math.random() * endX ) |0;
this.y = -Math.random() * opts.beforeSpawning;
}
Stripe.prototype.step = function() {
this.y += opts.stripeSpeed;
drawLetter( this.x, this.y|0 );
if( this.y > endX )
this.reset();
}
function drawLetter( x, y ){
x *= opts.charSize;
y *= opts.lineHeight;
ctx.fillStyle = 'hsl(hue,80%,50%)'.replace( 'hue', ( x + y ) / sum * 360 + tick );
ctx.fillText( opts.chars[ ( Math.random() * opts.chars.length ) |0 ], x, y );
}
for( var i = 0; i < endX*endX * opts.stripesParXxY; ++i )
stripes.push( new Stripe );
loop();
window.addEventListener( 'resize', function(){
w = c.width = window.innerWidth;
h = c.height = window.innerHeight;
ctx.fillStyle = '#111';
ctx.fillRect( 0, 0, w, h );
ctx.font = opts.font;
endX = ( w / opts.charSize + 1 ) |0;
endY = ( h / opts.lineHeight + 1 ) |0;
sum = w + h;
stripes.length = 0;
for( var i = 0; i < endX*endY * opts.stripesParXxY; ++i )
stripes.push( new Stripe );
})
canvas {
position: absolute;
top: 0;
left: 0;
}
<canvas id=c></canvas>
Once the DOM is loaded, you need to get a reference to your canvas DOM element at the top of your script or load handler function.
const c = document.getElementById("c");
Also its best to use quotes in your html.
e.g.
<canvas id="c"></canvas>
The problem of your code is that you have not put your canvas' id inside "", putting t
I have seen the code. There is a small error in html file and this is the cause of the project not working. It is simple, Just put your canvas id in "" doublequotes.
<canvas id="c"></canvas>
Thanks, Hope it helps

HTML5 Canvas Lines are not smooth?

As you can see in my image below my canvas pathing is kind of pixelated or like not smooth. I would like to know if there is a way to smooth them out?
Effective Code Block:
if (this.shade.color.topTrim) {
var toptrim = new Image();
toptrim.onload = function() {
for (i = 0; i < c.length; i++) {
var canvas = c[i];
var ctx = canvas.getContext("2d");
var pattern = ctx.createPattern(toptrim, "repeat");
ctx.beginPath();
ctx.moveTo( ( 150 - ( ProductDesigner.shade.model.radius / 2 ) ) , 80 );
ctx.quadraticCurveTo( 150 , 70, 150 + ( ProductDesigner.shade.model.radius / 2 ), 80);
ctx.lineTo( 150 + ( ProductDesigner.shade.model.radius / 2 ), 83 );
ctx.quadraticCurveTo( 150 , 73, 150 - ( ProductDesigner.shade.model.radius / 2 ), 83);
ctx.fillStyle = pattern;
ctx.fill();
ctx.closePath();
}
}
toptrim.src = "/wp-content/plugins/productdesigner/assets/Trimmings/" + this.shade.color.topTrim + ".jpg";
} else {
for (i = 0; i < c.length; i++) {
var canvas = c[i];
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo( ( 150 - ( ProductDesigner.shade.model.radius / 2 ) ) , 80 );
ctx.quadraticCurveTo( 150 , 70, 150 + ( ProductDesigner.shade.model.radius / 2 ), 80);
ctx.lineTo( 150 + ( ProductDesigner.shade.model.radius / 2 ), 83 );
ctx.quadraticCurveTo( 150 , 73, 150 - ( ProductDesigner.shade.model.radius / 2 ), 83);
ctx.closePath();
ctx.stroke();
}
}

get Y value of quadratic curve given the max height of the curve

When Y is 100 the maximum height of the curve will be (+/-) 60. I need a way to calculate Y when I have the maximum height of the curve.
Code:
point1 and point2 have x, y and z coordinates
this.drawLine = function(point1, point2) {
context = this.getContext();
context.beginPath();
context.moveTo(this.getX(point1), this.getY(point1));
point3 = {
x: ( point1.x + point2.x ) / 2,
y: ( point1.y + point2.y ) / 2,
z: ( point1.z + point2.z ) / 2
}
context.quadraticCurveTo( this.getX(point3), this.getY(point3) + point3.z * 0, this.getX(point2), this.getY(point2));
context.stroke();
}
I need the line of the curve to hit the coordinates of point3 instead of it not reaching the coordinates.
There are still many possible curves with the same maximums. Therefore, you cannot isolate a single curve to figure out your Y value.
I would suggest finding a way to obtain more information about your curve such as a point, property or relation.
Check out these links:
http://www.personal.kent.edu/~bosikiew/Algebra-handouts/quad-extval.pdf
http://hotmath.com/hotmath_help/topics/graphing-quadratic-equations-using-transformations.html
Found my answer: here
this.drawLine = function(point1, point2, style) {
context = this.getContext();
context.beginPath();
context.moveTo(this.getX(point1), this.getY(point1));
point3 = {
x: ( point1.x + point2.x ) / 2,
y: ( point1.y + point2.y ) / 2,
z: ( point1.z + point2.z ) / 2
}
context.strokeStyle = style;
x = this.getX(point3) * 2 - ( this.getX(point1) + this.getX(point2) ) / 2;
y = this.getY(point3) * 2 - ( this.getY(point1) + this.getY(point2) ) / 2;
context.quadraticCurveTo( x, y, this.getX(point2), this.getY(point2));
context.stroke();
}

calculating half-edges/faces of arbitrarily generated lines

I found this script by mrdoob that generates a web of lines. I've figured out where a line begins and where it ends. Now I want to extrude faces from these shapes, however all I have are lines and vertices. I'm trying to read through some half-edges theory, but i don't think I understand it that well.
Is it a matter of following a line until it's a rectangle, checking if it intersects a line or subdivides? I need a bump in the right direction.
// Based on Jared Tarbell's Substrate algorithm concept.
// http://www.complexification.net/gallery/machines/substrate/index.php
var Boid = function ( x, y, angle ) {
this.x = x;
this.y = y;
this.angle = Math.pow( Math.random(), 20 ) + angle;
this.dx = Math.cos( this.angle );
this.dy = Math.sin( this.angle );
this.life = Math.random() * 100 + 100;
this.dead = false;
this.update = function () {
context.strokeStyle = '#000000';
context.beginPath();
context.moveTo( this.x, this.y );
this.x += this.dx * 2;
this.y += this.dy * 2;
this.life -= 2;
context.lineTo( this.x, this.y );
context.stroke();
var index = ( Math.floor( this.x ) + width * Math.floor( this.y ) ) * 4;
if ( this.life <= 0 ) this.kill();
if ( data[ index + 3 ] > 0 ) this.kill();
if ( this.x < 0 || this.x > width ) this.kill();
if ( this.y < 0 || this.y > height ) this.kill();
}
this.kill = function () {
boids.splice( boids.indexOf( this ), 1 );
this.dead = true;
}
}
var width = window.innerWidth;
var height = window.innerHeight;
var canvas = document.getElementById( 'world' );
canvas.width = width;
canvas.height = height;
var context = canvas.getContext( '2d' );
var image, data;
var boids = [];
boids.push( new Boid( width / 2, height / 2, Math.random() * 360 * Math.PI / 180 ) );
setInterval( function () {
image = context.getImageData( 0, 0, width, height );
data = image.data;
for ( var i = 0; i < boids.length; i ++ ) {
var boid = boids[ i ];
boid.update();
if ( !boid.dead && Math.random() > 0.5 && boids.length < 500 ) {
boids.push( new Boid( boid.x, boid.y, ( Math.random() > 0.5 ? 90 : - 90 ) * Math.PI / 180 + boid.angle ) );
}
}
}, 1000 / 60 );
This looks more complicated than I tough. I'm not sure if it is the answer you are asking for, but may help you to decide the next step:
If you have to use this algorithm: I think you are going to need to keep track of every pair of points that makes an edge: the first point at the beginning of the Boid function and the second when the Boid is killed; both points (or the x1, x2, y1 and y2 values) are saved in a new edge object that will be added to an edges array (every edge will be kind of the soul of a death Boid).
There are two problems before applying the half-edges theory: you have an array of edges, but you need to know what other edges are connected to the beginning or end of a given edge. The other problem is that the "collision" between two Boids only affects the Boid currently being updated, which is killed during the collision. In order to use the half-edge theory you'll have to "notify" the other Boid/edge about this collision and split it at that point: a collision point is a vertex of three edges, the one that collides and the two in which the one being collided was split.
Also note that the shapes (faces) are not necessarily made of four edges, I opened the link you provider and there where a lot of shapes with tree and five edges.
If you can use a different algorithm for generating the mesh then you may have a better representation of the edges and vertexes that will help you to find the "corners" that makes every shape.

Categories

Resources