Constrain to x value using High Charts addPoint() - javascript

I was reading a bit about the high charts addPoint() function here:
http://api.highcharts.com/highcharts#Series.addPoint()
I'm quite taken the idea of creating a chart like this one:
http://www.highcharts.com/demo/dynamic-click-to-add
...but where I have a fixed x and y scale, and where the user can only place a point on the scale in multiple of 5.. such as a point at x=10 and y=20...
Has this been attempted, and/or is it feasible given the options provided in the API?
Thanks

You can modify this behavior in your click handler - you get the exact click values there, and you can simply round it to the next interval you like:
events: {
click: function(e) {
// find the clicked values and the series
var x = e.xAxis[0].value,
y = e.yAxis[0].value,
series = this.series[0];
// round given click point to intervals
x = Math.ceil(x / 5) * 5;
y = Math.ceil(y / 5) * 5;
// Add it
series.addPoint([x, y]);
}
}
The Demo of this example will give you a starting point.

Related

Reverse gravity / anti-gravity? What elements of a gravitational force algorithm do i need to change for reversing it?

I want to reverse my gravitational force algorithm to produce locations in the "past" of multiple bodies interacting. It's trivial to produce locations in the future by running the algorithm multiple times on the set of bodies but reversing this to write out positions of bodies' previous positions has stumped me. I don't want to store the past positions and since this is deterministic, it should be possible to somehow run the algorithm backwards but I'm not sure how.
In the snippet element each of the bodies that are tested from universe in the loop, tick is the delta time.
function forces(other) {
if (element === other) {
return;
}
var distancePoint = element.point.sub(other.point);
var normal = Math.sqrt(100.0 + distancePoint.lengthSq());
var mag = GravatationalConstant /
Math.pow(normal, 3);
var distPointMulOtherMass = distancePoint
.mul(mag * other.mass);
element.acceleration = element.acceleration.sub(distPointMulOtherMass);
other.acceleration = other
.acceleration
.add(distancePoint
.mul(mag * element.mass)
);
}
element.acceleration = new Point(0,0,0,0);
universe.forEach(forces);
element.velocity = element.velocity.add(element.acceleration.mul(ticks));
element.point = element.point.add(element.velocity.mul(0.5 * ticks));
I tried sending a negative tick as well as negative gravitational constant, but the positions it produces for the "past" didn't seem to follow what the elements appeared to do in the real past.
I don't know much about physics but I was wondering if there is a small change that could be done to reverse this algorithm.
Update
Thanks to Graeme Niedermayer, I've updated my gravity algorithm to the inverse square law and using negative time it appears to produce positions in the past!
function forces(other) {
if (element === other) {
return;
}
var distancePoint = element.point.sub(other.point);
const forceElementMass = GravatationalConstant * element.mass * other.mass /
Math.pow(element.mass,2)
const forceOtherMass = GravatationalConstant * element.mass * other.mass /
Math.pow(other.mass,2)
element.acceleration = element.acceleration
.sub(distancePoint.mul(forceOtherMass))
other.acceleration = other.acceleration
.add(distancePoint.mul(forceElementMass))
}
const ticks = forwards ? dt : -dt;
element.acceleration = new Point(0,0,0,0);
universe.forEach(forces);
element.velocity = element.velocity.add(element.acceleration.mul(ticks));
element.point = element.point.add(element.velocity.mul(0.5 * ticks));
Outlined circles are at the current position and the "past" positions are others fading out to zero opacity.
Update 2
Realised that I used the wrong equation in Update 1 (both force constants used the same mass object). I looked into a few more examples and have updated the code, but now I'm not sure where i should add the delta time ticks which is currently just set to 1 for forwards and -1 back backwards. Below is an image of what is looks like if I multiply the acceleration by ticks before adding it to the velocity each frame body.velocity = body.velocity.add(body.acceleration.mul(ticks)) or if I make one of the masses negative const force = G * body.mass * (forward ? other.mass : -other.mass) / d ** 2.
As you can see the "past" positions (red outline) of the green body go over to the left and above. I was hoping to have them appear to "follow" the current position but I'm not sure how to reverse or invert the equation to show the "past" positions, basically if the body was traveling in the opposite direction. Is there a way to do this?
In this next image I have multiplied the velocity by delta time ticks before adding it to the position body.point = body.point.add(body.velocity.mul(ticks)) this results in a similar path to a recorded path the body traveled (by writing each position to an array and drawing a line between those positions) but it is slightly off. This solution is similar to what I was seeing in Update 1. Is there a reason that this is "almost" correct?
Code below is without any additions to reverse the position.
function forces(other, ticks) {
if (body === other) {
return;
}
// Calculate direction of force
var distanceVector = other.point.sub(body.point)
// Distance between objects
var d = distanceVector.mag()
// Normalize vector (distance doesn't matter here, we just want this vector for direction)
const forceNormalized = distanceVector.normalized()
// Calculate gravitational force magnitude
const G = 6.674
const force = G * body.mass * other.mass / d ** 2
// Get force vector --> magnitude * direction
const magDirection = forceNormalized.mul(force)
const f = magDirection.div(body.mass)
body.acceleration = body.acceleration.add(f)
}
body.acceleration = body.acceleration.mul(0)
universe.forEach(body => forces(body, ticks))
body.velocity = body.velocity.add(body.acceleration)
body.point = body.point.add(body.velocity)
Update 3
I ended up removing the negative mass and the velocity multiplied by ticks and just reversed the way the acceleration is applied to the position:
if (forward) {
universe.forEach(body => forces(body, ticks));
body.velocity = body.velocity.add(body.acceleration)
body.point = body.point.add(body.velocity)
} else {
body.point = body.point.sub(body.velocity)
universe.forEach(body => forces(body, ticks));
body.velocity = body.velocity.sub(body.acceleration)
}
Resulting in being able to generate positions forwards and backwards in time from the current position. In the image it appears so the "past" positions follow the recorded trail of the current position.
To generate a step in the "past" it subtracts the current velocity from the current position, putting it in the last position it was in. Next it gets the acceleration by checking the forces from other bodies then subtracts the new acceleration (using negative mass would do the same) from the velocity so the next position in the "past" will be correct.
You should be able to make one of the masses negative.
The reason why negative time doesn't work is because you are implicit using euler's method. Euler's method is unstable when using negative steps.
Also the physics you using is also a little weird. Gravity is usually a squared law.

canvas draw - change rotation axis without clearing old state

I'm using html5 canvas to create a simple 3d polygon program. the program allows to change the rotation of each axis - x,y,z. on the event of change x/y/z angle, a corresponding call to the drawing function is done. the problem is every time I make a new call to the draw function it clears the older position and the result is it jumps. basically each function works on its own but they do not work together.
example code:
var Perspective = function(rotate){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//clear
...
switch(rotate){
case "x" : {
var transform = Mat3.rotationX(Math.radians(rotateX.getValue())); //rotation x
break;
}
case "y" : {
var transform = Mat3.rotationY(Math.radians(rotateY.getValue())); //rotation y
break;
}
case "z" : {
var transform = Mat3.rotationZ(Math.radians(rotateZ.getValue())); //rotation Z
}
...
draw(...settings..)
}
set a listener to each slider change event (also for Y and Z). AngleX makes the call to Perspective, passing the string "x" as rotate param.
var angleX = $('#AngleX').slider()
.on('slide change', AngleX)
.data('slider');
how can i make the changes if different axis more dynamic ?
anyway i'v solved it no thanks to you QBM5 .. the switch case was a mistake, i had to multiply all axis transformation matrixs like this :
var transform = Mat3.rotationX(-Math.radians(rotateY.getValue())) .multiply(Mat3.rotationY(Math.radians(rotateX.getValue())));

mouse position to isometric tile including height

Struggeling translating the position of the mouse to the location of the tiles in my grid. When it's all flat, the math looks like this:
this.position.x = Math.floor(((pos.y - 240) / 24) + ((pos.x - 320) / 48));
this.position.y = Math.floor(((pos.y - 240) / 24) - ((pos.x - 320) / 48));
where pos.x and pos.y are the position of the mouse, 240 and 320 are the offset, 24 and 48 the size of the tile. Position then contains the grid coordinate of the tile I'm hovering over. This works reasonably well on a flat surface.
Now I'm adding height, which the math does not take into account.
This grid is a 2D grid containing noise, that's being translated to height and tile type. Height is really just an adjustment to the 'Y' position of the tile, so it's possible for two tiles to be drawn in the same spot.
I don't know how to determine which tile I'm hovering over.
edit:
Made some headway... Before, I was depending on the mouseover event to calculate grid position. I just changed this to do the calculation in the draw loop itself, and check if the coordinates are within the limits of the tile currently being drawn. creates some overhead tho, not sure if I'm super happy with it but I'll confirm if it works.
edit 2018:
I have no answer, but since this ha[sd] an open bounty, help yourself to some code and a demo
The grid itself is, simplified;
let grid = [[10,15],[12,23]];
which leads to a drawing like:
for (var i = 0; i < grid.length; i++) {
for (var j = 0; j < grid[0].length; j++) {
let x = (j - i) * resourceWidth;
let y = ((i + j) * resourceHeight) + (grid[i][j] * -resourceHeight);
// the "+" bit is the adjustment for height according to perlin noise values
}
}
edit post-bounty:
See GIF. The accepted answer works. The delay is my fault, the screen doesn't update on mousemove (yet) and the frame rate is low-ish. It's clearly bringing back the right tile.
Source
Intresting task.
Lets try to simplify it - lets resolve this concrete case
Solution
Working version is here: https://github.com/amuzalevskiy/perlin-landscape (changes https://github.com/jorgt/perlin-landscape/pull/1 )
Explanation
First what came into mind is:
Just two steps:
find an vertical column, which matches some set of tiles
iterate tiles in set from bottom to top, checking if cursor is placed lower than top line
Step 1
We need two functions here:
Detects column:
function getColumn(mouseX, firstTileXShiftAtScreen, columnWidth) {
return (mouseX - firstTileXShiftAtScreen) / columnWidth;
}
Function which extracts an array of tiles which correspond to this column.
Rotate image 45 deg in mind. The red numbers are columnNo. 3 column is highlighted. X axis is horizontal
function tileExists(x, y, width, height) {
return x >= 0 & y >= 0 & x < width & y < height;
}
function getTilesInColumn(columnNo, width, height) {
let startTileX = 0, startTileY = 0;
let xShift = true;
for (let i = 0; i < columnNo; i++) {
if (tileExists(startTileX + 1, startTileY, width, height)) {
startTileX++;
} else {
if (xShift) {
xShift = false;
} else {
startTileY++;
}
}
}
let tilesInColumn = [];
while(tileExists(startTileX, startTileY, width, height)) {
tilesInColumn.push({x: startTileX, y: startTileY, isLeft: xShift});
if (xShift) {
startTileX--;
} else {
startTileY++;
}
xShift = !xShift;
}
return tilesInColumn;
}
Step 2
A list of tiles to check is ready. Now for each tile we need to find a top line. Also we have two types of tiles: left and right. We already stored this info during building matching tiles set.
function getTileYIncrementByTileZ(tileZ) {
// implement here
return 0;
}
function findExactTile(mouseX, mouseY, tilesInColumn, tiles2d,
firstTileXShiftAtScreen, firstTileYShiftAtScreenAt0Height,
tileWidth, tileHeight) {
// we built a set of tiles where bottom ones come first
// iterate tiles from bottom to top
for(var i = 0; i < tilesInColumn; i++) {
let tileInfo = tilesInColumn[i];
let lineAB = findABForTopLineOfTile(tileInfo.x, tileInfo.y, tiles2d[tileInfo.x][tileInfo.y],
tileInfo.isLeft, tileWidth, tileHeight);
if ((mouseY - firstTileYShiftAtScreenAt0Height) >
(mouseX - firstTileXShiftAtScreen)*lineAB.a + lineAB.b) {
// WOHOO !!!
return tileInfo;
}
}
}
function findABForTopLineOfTile(tileX, tileY, tileZ, isLeftTopLine, tileWidth, tileHeight) {
// find a top line ~~~ a,b
// y = a * x + b;
let a = tileWidth / tileHeight;
if (isLeftTopLine) {
a = -a;
}
let b = isLeftTopLine ?
tileY * 2 * tileHeight :
- (tileX + 1) * 2 * tileHeight;
b -= getTileYIncrementByTileZ(tileZ);
return {a: a, b: b};
}
Please don't judge me as I am not posting any code. I am just suggesting an algorithm that can solve it without high memory usage.
The Algorithm:
Actually to determine which tile is on mouse hover we don't need to check all the tiles. At first we think the surface is 2D and find which tile the mouse pointer goes over with the formula OP posted. This is the farthest probable tile mouse cursor can point at this cursor position.
This tile can receive mouse pointer if it's at 0 height, by checking it's current height we can verify if this is really at the height to receive pointer, we mark it and move forward.
Then we find the next probable tile which is closer to the screen by incrementing or decrementing x,y grid values depending on the cursor position.
Then we keep on moving forward in a zigzag fashion until we reach a tile which cannot receive pointer even if it is at it's maximum height.
When we reach this point the last tile found that were at a height to receive pointer is the tile that we are looking for.
In this case we only checked 8 tiles to determine which tile is currently receiving pointer. This is very memory efficient in comparison to checking all the tiles present in the grid and yields faster result.
One way to solve this would be to follow the ray that goes from the clicked pixel on the screen into the map. For that, just determine the camera position in relation to the map and the direction it is looking at:
const camPos = {x: -5, y: -5, z: -5}
const camDirection = { x: 1, y:1, z:1}
The next step is to get the touch Position in the 3D world. In this certain perspective that is quite simple:
const touchPos = {
x: camPos.x + touch.x / Math.sqrt(2),
y: camPos.y - touch.x / Math.sqrt(2),
z: camPos.z - touch.y / Math.sqrt(2)
};
Now you just need to follow the ray into the layer (scale the directions so that they are smaller than one of your tiles dimensions):
for(let delta = 0; delta < 100; delta++){
const x = touchPos.x + camDirection.x * delta;
const y = touchPos.y + camDirection.y * delta;
const z = touchPos.z + camDirection.z * delta;
Now just take the tile at xz and check if y is smaller than its height;
const absX = ~~( x / 24 );
const absZ = ~~( z / 24 );
if(tiles[absX][absZ].height >= y){
// hanfle the over event
}
I had same situation on a game. first I tried with mathematics, but when I found that the clients wants to change the map type every day, I changed the solution with some graphical solution and pass it to the designer of the team. I captured the mouse position by listening the SVG elements click.
the main graphic directly used to capture and translate the mouse position to my required pixel.
https://blog.lavrton.com/hit-region-detection-for-html5-canvas-and-how-to-listen-to-click-events-on-canvas-shapes-815034d7e9f8
https://code.sololearn.com/Wq2bwzSxSnjl/#html
Here is the grid input I would define for the sake of this discussion. The output should be some tile (coordinate_1, coordinate_2) based on visibility on the users screen of the mouse:
I can offer two solutions from different perspectives, but you will need to convert this back into your problem domain. The first methodology is based on coloring tiles and can be more useful if the map is changing dynamically. The second solution is based on drawing coordinate bounding boxes based on the fact that tiles closer to the viewer like (0, 0) can never be occluded by tiles behind it (1,1).
Approach 1: Transparently Colored Tiles
The first approach is based on drawing and elaborated on here. I must give the credit to #haldagan for a particularly beautiful solution. In summary it relies on drawing a perfectly opaque layer on top of the original canvas and coloring every tile with a different color. This top layer should be subject to the same height transformations as the underlying layer. When the mouse hovers over a particular layer you can detect the color through canvas and thus the tile itself. This is the solution I would probably go with and this seems to be a not so rare issue in computer visualization and graphics (finding positions in a 3d isometric world).
Approach 2: Finding the Bounding Tile
This is based on the conjecture that the "front" row can never be occluded by "back" rows behind it. Furthermore, "closer to the screen" tiles cannot be occluded by tiles "farther from the screen". To make precise the meaning of "front", "back", "closer to the screen" and "farther from the screen", take a look at the following:
.
Based on this principle the approach is to build a set of polygons for each tile. So firstly we determine the coordinates on the canvas of just box (0, 0) after height scaling. Note that the height scale operation is simply a trapezoid stretched vertically based on height.
Then we determine the coordinates on the canvas of boxes (1, 0), (0, 1), (1, 1) after height scaling (we would need to subtract anything from those polygons which overlap with the polygon (0, 0)).
Proceed to build each boxes bounding coordinates by subtracting any occlusions from polygons closer to the screen, to eventually get coordinates of polygons for all boxes.
With these coordinates and some care you can ultimately determine which tile is pointed to by a binary search style through overlapping polygons by searching through bottom rows up.
It also matters what else is on the screen. Maths attempts work if your tiles are pretty much uniform. However if you are displaying various objects and want the user to pick them, it is far easier to have a canvas-sized map of identifiers.
function poly(ctx){var a=arguments;ctx.beginPath();ctx.moveTo(a[1],a[2]);
for(var i=3;i<a.length;i+=2)ctx.lineTo(a[i],a[i+1]);ctx.closePath();ctx.fill();ctx.stroke();}
function circle(ctx,x,y,r){ctx.beginPath();ctx.arc(x,y,r,0,2*Math.PI);ctx.fill();ctx.stroke();}
function Tile(h,c,f){
var cnv=document.createElement("canvas");cnv.width=100;cnv.height=h;
var ctx=cnv.getContext("2d");ctx.lineWidth=3;ctx.lineStyle="black";
ctx.fillStyle=c;poly(ctx,2,h-50,50,h-75,98,h-50,50,h-25);
poly(ctx,50,h-25,2,h-50,2,h-25,50,h-2);
poly(ctx,50,h-25,98,h-50,98,h-25,50,h-2);
f(ctx);return ctx.getImageData(0,0,100,h);
}
function put(x,y,tile,image,id,map){
var iw=image.width,tw=tile.width,th=tile.height,bdat=image.data,fdat=tile.data;
for(var i=0;i<tw;i++)
for(var j=0;j<th;j++){
var ijtw4=(i+j*tw)*4,a=fdat[ijtw4+3];
if(a!==0){
var xiyjiw=x+i+(y+j)*iw;
for(var k=0;k<3;k++)bdat[xiyjiw*4+k]=(bdat[xiyjiw*4+k]*(255-a)+fdat[ijtw4+k]*a)/255;
bdat[xiyjiw*4+3]=255;
map[xiyjiw]=id;
}
}
}
var cleanimage;
var pickmap;
function startup(){
var water=Tile(77,"blue",function(){});
var field=Tile(77,"lime",function(){});
var tree=Tile(200,"lime",function(ctx){
ctx.fillStyle="brown";poly(ctx,50,50,70,150,30,150);
ctx.fillStyle="forestgreen";circle(ctx,60,40,30);circle(ctx,68,70,30);circle(ctx,32,60,30);
});
var sheep=Tile(200,"lime",function(ctx){
ctx.fillStyle="white";poly(ctx,25,155,25,100);poly(ctx,75,155,75,100);
circle(ctx,50,100,45);circle(ctx,50,80,30);
poly(ctx,40,70,35,80);poly(ctx,60,70,65,80);
});
var cnv=document.getElementById("scape");
cnv.width=500;cnv.height=400;
var ctx=cnv.getContext("2d");
cleanimage=ctx.getImageData(0,0,500,400);
pickmap=new Uint8Array(500*400);
var tiles=[water,field,tree,sheep];
var map=[[[0,0],[1,1],[1,1],[1,1],[1,1]],
[[0,0],[1,1],[1,2],[3,2],[1,1]],
[[0,0],[1,1],[2,2],[3,2],[1,1]],
[[0,0],[1,1],[1,1],[1,1],[1,1]],
[[0,0],[0,0],[0,0],[0,0],[0,0]]];
for(var x=0;x<5;x++)
for(var y=0;y<5;y++){
var desc=map[y][x],tile=tiles[desc[0]];
put(200+x*50-y*50,200+x*25+y*25-tile.height-desc[1]*20,
tile,cleanimage,x+1+(y+1)*10,pickmap);
}
ctx.putImageData(cleanimage,0,0);
}
var mx,my,pick;
function mmove(event){
mx=Math.round(event.offsetX);
my=Math.round(event.offsetY);
if(mx>=0 && my>=0 && mx<cleanimage.width && my<cleanimage.height && pick!==pickmap[mx+my*cleanimage.width])
requestAnimationFrame(redraw);
}
function redraw(){
pick=pickmap[mx+my*cleanimage.width];
document.getElementById("pick").innerHTML=pick;
var ctx=document.getElementById("scape").getContext("2d");
ctx.putImageData(cleanimage,0,0);
if(pick!==0){
var temp=ctx.getImageData(0,0,cleanimage.width,cleanimage.height);
for(var i=0;i<pickmap.length;i++)
if(pickmap[i]===pick)
temp.data[i*4]=255;
ctx.putImageData(temp,0,0);
}
}
startup(); // in place of body.onload
<div id="pick">Move around</div>
<canvas id="scape" onmousemove="mmove(event)"></canvas>
Here the "id" is a simple x+1+(y+1)*10 (so it is nice when displayed) and fits into a byte (Uint8Array), which could go up to 15x15 display grid already, and there are wider types available too.
(Tried to draw it small, and it looked ok on the snippet editor screen but apparently it is still too large here)
Computer graphics is fun, right?
This is a special case of the more standard computational geometry "point location problem". You could also express it as a nearest neighbour search.
To make this look like a point location problem you just need to express your tiles as non-overlapping polygons in a 2D plane. If you want to keep your shapes in a 3D space (e.g. with a z buffer) this becomes the related "ray casting problem".
One source of good geometry algorithms is W. Randolf Franklin's website and turf.js contains an implementation of his PNPOLY algorithm.
For this special case we can be even faster than the general algorithms by treating our prior knowledge about the shape of the tiles as a coarse R-tree (a type of spatial index).

Display vertical line on intersection point

I'm trying to represent a Pareto chart with Highcharts, as you can see here.
The horizontal line shows the 80% value, but now I wanted to display a vertical line where that horizontal 80% line intersects with the "Acumulated" chart series.
This is an example of what I'm trying to achieve:
Is there a way to do it?
Another option would be to get the "x" value of the "Acumulated" spline where it's "y" value is "80", that way I could then draw the line manually.
Is this even possible with the Highcharts API?
I know that it's possible to get the values of a point in a series, but that isn't enough in this case:
var point = chart.get('accumulated').data[2];
I have find it for 80:20 calculation.
First I have find the first value in series from Spline data which greater than or equal to 80.
i.e. >= 80
Suppose it is DataX
Then find out the that index in array plus one for DataX.
i.e. DataX location is DataIndex = index+1
(as array start from 0th calculation need plus one)
formula is
DataX : DataIndex :: 80: ?
let the question mark is xIndexOf80
then xIndexOf80 = (DataIndex *80)/(DataX ).
xIndexOf80 is nothing but position of 80 on X axis.
which gives you exact marks on X-Axis
function findInetrSectionPoint(arrSplineData) {
var intLen = arrSplineData.length;
for (var index = 0; index < intLen; index++) {
if (arrSplineData[index] >= 80) {
interSectPoint = ((index + 1) * 80) / arrSplineData[index] - 1;
break;
}
}
return interSectPoint;
}
Here is the Plunker
You can calculate position of 80% point and then use http://api.highcharts.com/highstock#Renderer rect. Apart from that you can also check this option http://api.highcharts.com/highstock#Axis.addPlotLine() / http://api.highcharts.com/highstock#yAxis.plotLines

Get curved result set rather than angular in JavaScript (maths help needed)

I've got a script that creates a gradient by shading cells based on their distance from a set of coordinates. What I want to do is make the gradient circular rather than the diamond shape that it currently is. You can see an en example here: http://jsbin.com/uwivev/9/edit
var row = 5, col = 5, total_rows = 20, total_cols = 20;
$('table td').each(function(index, item) {
// Current row and column
var current_row = $(item).parent().index(),
current_col = $(item).index();
// Percentage based on location, always using positive numbers
var percentage_row = Math.abs(current_row-row)/total_rows;
var percentage_col = Math.abs(current_col-col)/total_cols;
// I'm thinking this is what I need to change to achieve the curve I'm after
var percentage = (percentage_col+percentage_row)/2;
$(this).find('div').fadeTo(0,percentage*3);
});
If you can give me hand with the right maths function to get the curve I'm after that would be great! Thanks!
Darren
// Current row and column
var current_row = $(item).parent().index(),
current_col = $(item).index();
// distance away from the bright pixel
var dist = Math.sqrt(Math.pow(current_row - row, 2) + Math.pow(current_col - col, 2))
// do something with dist, you might change this
var percentage = dist / total_cols;
$(this).find('div').fadeTo(0,percentage*3);
You can use the square of the distance formula:
((current_row - row)*(current_row - row) + (current_col - col)*(current_col - col))
then multiply it by whatever scale factor you need.
Here is a circle drawing procudure I wrote many moons ago in Pascal which you can use as pseudo code to understand how to color pixels at the radius from an (X,Y) and work your way in. Multiple shrinking circles should cover the entire area you need. The code also gives you the formula for accessing the radius.
PROCEDURE DrawCircle(X,Y,Radius:Integer);
VAR A,B,Z:LongInt;
BEGIN
Z:=Round(Sqrt(Sqr(LongInt(Radius))/2));
FOR A:=Z TO Radius DO
FOR B:=0 TO Z DO
IF Radius=Round(Sqrt(A*A+B*B)) THEN
BEGIN
PutPixel(X+A,Y+B,8);
PutPixel(X+A,Y-B,9);
PutPixel(X-A,Y+B,10);
PutPixel(X-A,Y-B,11);
PutPixel(X+B,Y+A,12);
PutPixel(X+B,Y-A,13);
PutPixel(X-B,Y+A,14);
PutPixel(X-B,Y-A,15);
END;
END;
NB: "Longint()" is a compiler typecast for larger numeric computations so don't let that worry you.
NB: Inner-most brackets are executed first.

Categories

Resources