Building circle meter gauge - html

I was wondering if someone could help me with a circle meter gauage i have taken some code from a different example and i am just protypting stuff to see if i can get it to work here is a working example.
http://jsbin.com/ixuyid/28/edit
Click run with javascript
Code below
var context;
canvas = document.getElementById('myCanvas');
context = canvas.getContext('2d');
//use a reusable function
function drawCircle(num){
console.log(num);
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 0 * Math.PI;
var endAngle = num * Math.PI;
var counterClockwise = false;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.lineWidth = 5;
// line color
context.strokeStyle = 'black';
context.stroke();
}
drawCircle();
var num = 1;
setInterval(function(){
},1000);
+function(){
var ctx = new webkitAudioContext()
, url = '//kevincennis.com/sound/loudpipes.mp3'
, audio = new Audio(url)
// 2048 sample buffer, 1 channel in, 1 channel out
, processor = ctx.createJavaScriptNode(2048, 1, 1)
, meter = document.getElementById('meter')
, source
audio.addEventListener('canplaythrough', function(){
source = ctx.createMediaElementSource(audio)
source.connect(processor)
source.connect(ctx.destination)
processor.connect(ctx.destination)
audio.play()
}, false);
// loop through PCM data and calculate average
// volume for a given 2048 sample buffer
processor.onaudioprocess = function(evt){
var input = evt.inputBuffer.getChannelData(0)
, len = input.length
, total = i = 0
, rms
while ( i < len ) total += Math.abs( input[i++] )
rms = Math.sqrt( total / len )
meter.style.width = ( rms * 100 ) + '%';
context.clearRect(100,50,200,200);
drawCircle(rms);
}
}()
I seem to be having issue with the levels???
Any help

Change these two lines in the drawCircle function:
var startAngle = 0; //multiplying with 0 will result in 0
var endAngle = 360 * num * Math.PI / 180;
Your num seem to be a value between 0 and 1 so we need to add what we're using that with, here 360 degrees, then convert by using PI / 180.
The other problem is that the clearRect wasn't extended far enough so it left part of the arc uncleared to the right.
Tip: To make it look more realistic you can update your rms only when the new rms is higher, and if not just subtract a small value for each frame.
For example:
//global scope
var oldRMS = 0;
Inside your processor.onaudioprocess after vars:
if (rms > oldRMS) oldRMS = rms;
meter.style.width = ( oldRMS * 100 ) + '%';
context.clearRect(100,50,canvas.width,canvas.height);
drawCircle(oldRMS);
oldRMS -= 0.04; //speed of fallback
Modifcations:
http://jsbin.com/ixuyid/29/edit

Related

Calculate the area of a polygon with latitude and longitude

I have this code, written using this: source1 and this: source 2
public static double CalculatePolygonArea(IList<GpsLocation> coordinates)
{
double area = 0;
if (coordinates.Count > 2)
{
for (var i = 0; i < coordinates.Count-1; i++)
{
GpsLocation p1, p2;
p1 = coordinates[i];
p2 = coordinates[i + 1];
area += ToRad(p2.Longitude - p1.Longitude) * (2 + Math.Sin(ToRad(p1.Latitude))
+ Math.Sin(ToRad(p2.Latitude)));
area = area * R * R / 2;
}
}
return Math.Abs(area);
}
Here is my test code:
[Fact]
public void GpsPolygonAreaTest()
{
var poly = new List<GpsLocation>();
var p1 = new GpsLocation(0, 0);
poly.Add(p1);
var p2 = GpsHelper.CreateLocationBasedOnBearingDistance(p1, 5, 100);
poly.Add(p2);
var p3 = GpsHelper.CreateLocationBasedOnBearingDistance(p2, 95, 100);
poly.Add(p3);
var p4 = GpsHelper.CreateLocationBasedOnBearingDistance(p3, 185, 100);
poly.Add(p4);
poly.Add(p1);
var area = GpsHelper.CalculatePolygonArea(poly);
area.Should().Be(10000);
}
I confirmed that my polygon is 100m x 100m, see image:
My test result is: Expected value to be 10000, but found 1.28153883377486E+48.
Any ideas what wrong with my code?
I'm pretty sure this statement:
area = area * R * R / 2;
should be placed after the loop over the vertices, rather than repeated on each iteration.

How do I generate a visually distinct, non-random color from a single input number?

In Flash AS3, how would I write a function that will:
Take in an integer (a list index, for example)
return a visually distinct hex color based on that number (and will consistently return that same color given that same number)
The purpose is to provide a visually distinct color for each item in varying-length list of items. The most I expect to support is around 200, but I don't see the count going far above 20 or so for most.
Here's my quick and dirty:
public static function GetAColor(idx:int):uint {
var baseColors:Array = [0xff0000, 0x00ff00, 0xff0080, 0x0000ff, 0xff00ff, 0x00ffff, 0xff8000];
return Math.round(baseColors[idx % baseColors.length] / (idx + 1) * 2);
}
It does OK, but it would be nice to see a more distinct set of colors that are not so visually close to one another
You could go with generator of random values that supports seed, so you will be able return same color. As for color you could build it - by randomValue * 0xFFFFFF, where randomValue between 0 and 1. And exclude values (colors) that are close.
Second option: build palette of 200 colors with step - 0xFFFFFF / 200 and shuffle palette with predefined logic, so you will have same colors.
Third option: as for really distinct colors, you could go with big jumps in every channel. Example: 0xFF * 0.2 - 5 steps in every channel.
Fourth option: go with HSV. It's easy to understand(watch image, rotate hue from 0 to 360, change saturation and value from 0 to 100) how to manipulate parameters to get distinct color:
//Very simple demo, where I'm only rotating Hue
var step:uint = 15;
var position:uint = 0;
var colors:Array = [];
for (; position < 360; position += step) {
colors.push(HSVtoRGB(position, 100, 100));
}
//Visualisation for demo
var i:uint, len:uint = colors.length, size:uint = 40, shape:Shape, posX:uint, posY:uint;
for (i; i < len; ++i) {
shape = new Shape();
shape.graphics.beginFill(colors[i]);
shape.graphics.drawRect(0, 0, size, size);
addChild(shape);
shape.x = posX;
shape.y = posY;
posX += size;
if (posX + size >= stage.stageWidth) {
posX = 0;
posY += size;
}
}
public function HSVtoRGB(h:Number, s:Number, v:Number):uint {
var r:Number = 0;
var g:Number = 0;
var b:Number = 0;
var tempS:Number = s / 100;
var tempV:Number = v / 100;
var hi:int = Math.floor(h / 60) % 6;
var f:Number = h / 60 - Math.floor(h / 60);
var p:Number = (tempV * (1 - tempS));
var q:Number = (tempV * (1 - f * tempS));
var t:Number = (tempV * (1 - (1 - f) * tempS));
switch (hi) {
case 0:
r = tempV;
g = t;
b = p;
break;
case 1:
r = q;
g = tempV;
b = p;
break;
case 2:
r = p;
g = tempV;
b = t;
break;
case 3:
r = p;
g = q;
b = tempV;
break;
case 4:
r = t;
g = p;
b = tempV;
break;
case 5:
r = tempV;
g = p;
b = q;
break;
}
return (Math.round(r * 255) << 16 | Math.round(g * 255) << 8 | Math.round(b * 255));
}
And last one, if you want go with this task like a pro, this wiki article could be helpful for you.

3D Particles Ball

If I'd like to make a circle with particles, I'd define random coordinates for particles like this:
for(var i:int = 0; i != 100; i++)
{
var angle:Number = Math.random() * 360;
var r:Number = 600;
var nX:Number = r * Math.cos(angle / 180 * Math.PI);
var nY:Number = r * Math.sin(angle / 180 * Math.PI);
}
But I want to make a ball with particles on 3d space but I don't know how to define random coordinates for particles. Radius is fixed again but there should be a "nZ" value. Can you help me to define these coordinates?
for(var i:int = 0; i != 100; i++)
{
var angle:Number = Math.random() * 360;
var r:Number = 600;
var nX:Number = ???
var nY:Number = ???
var nZ:Number = ???
}
Thanks in advance...
Spherical coordinates are what you want.
You need two angles:
for(var i:int = 0; i != 100; i++)
{
var azimuthAngle:Number = Math.random() * 360;
var elevationAngle:Number = (Math.random() * 180) - 90;
var r:Number = 600;
var nX:Number =
r * Math.cos(azimuthAngle / 180 * Math.PI) * Math.sin(elevationAngle / 180 * Math.PI);
var nY:Number =
r * Math.sin(azimuthAngle / 180 * Math.PI) * Math.sin(elevationAngle / 180 * Math.PI);
var nZ:Number =
r * Math.cos(elevationAngle / 180 * Math.PI);
}

Google Maps determine distance along Line

I am trying to determine the distance of a point along a given Polyline (from the start point) in Google maps (given that the user clicks on the Polyline and I get the point coordinates in the event).
So far, this is the only thing that comes to mind:
Iterate over all segments in the Polyline until I find one such that
d(line, point) ~= 0, keeping track of the distance covered so far.
Interpolate on the segment the point is on to find its distance
relative to the start of the segment.
Sadly, this seems rather complicated for something that should be straightforward to do.
Is there any easier way?
P.S.: I'm using API v3
So, after much searching I decided to implement the algorithm as described above. Turned out it isn't as bad as I thought. Should anyone ever land on this page, the full code is below:
var DistanceFromStart = function (/*latlng*/ markerPosition) {
var path = this.polyline.getPath();
var minValue = Infinity;
var minIndex = 0;
var x = markerPosition.lat();
var y = markerPosition.lng();
for (var i = 0; i < path.getLength() - 1; i++) {
var x1 = path.getAt(i).lat();
var y1 = path.getAt(i).lng();
var x2 = path.getAt(i + 1).lat();
var y2 = path.getAt(i + 1).lng();
var dist = pDistance(x, y, x1, y1, x2, y2);
if (dist < minValue) {
minIndex = i;
minValue = dist;
}
}
var gdist = google.maps.geometry.spherical.computeDistanceBetween;
var dinit = gdist(markerPosition, path.getAt(minIndex));
var dtotal = gdist(path.getAt(minIndex), path.getAt(minIndex + 1));
var distanceFromStart = 0;
for (var i = 0; i <= minIndex - 1; i++) {
distanceFromStart += gdist(path.getAt(i), path.getAt(i + 1));
}
distanceFromStart += dtotal * dinit / dtotal;
return distanceFromStart;
}
function pDistance(x, y, x1, y1, x2, y2) {
var A = x - x1;
var B = y - y1;
var C = x2 - x1;
var D = y2 - y1;
var dot = A * C + B * D;
var len_sq = C * C + D * D;
var param = dot / len_sq;
var xx, yy;
if (param < 0 || (x1 == x2 && y1 == y2)) {
xx = x1;
yy = y1;
}
else if (param > 1) {
xx = x2;
yy = y2;
}
else {
xx = x1 + param * C;
yy = y1 + param * D;
}
var dx = x - xx;
var dy = y - yy;
return Math.sqrt(dx * dx + dy * dy);
}
If you see anything to improve, do let me know.
If you get the coordinates for the start and end points, then use the haversine algorithm to calculate the distance you can easily find the distance between two points taking into consideration the curvature of the earth.
Here is the formula (you may need to convert in into the language you are using):
var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var lat1 = lat1.toRad();
var lat2 = lat2.toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
variable d is your distance.
Hope this helps

Iterating each pixel of a Bitmap image in ActionScript

Is it possible to iterate each pixel of a bitmap image? Eventually what I'm trying to achieve is that I need to get the coordinate values of each pixel of a bitmap image and change the color of those pixels according to their coordinate values. As I see it, I need to use the getPixels() method but I still did not understand exactly what I should do.
( too slow :) )
so this is the sae as above with a linear loop instead of 2 nested loops.
//creates a new BitmapData, with transparency, white 0xFFFFFF
var bd:BitmapData = new BitmapData( 100, 100, false, 0xFFFFFF );
//stores the width and height of the image
var w:int = bd.width;
var h:int = bd.height;
var i:int = w * h;
var x:int, y:int, col;
//decremental loop are said to be faster :)
while ( i-- )
{
//this is the position of each pixel in x & y
x = i % w;
y = int( i / w );
//gets the current color of the pixel ( 0xFFFFFF )
col = bd.getPixel( x, y );
//assign the 0xFF0000 ( red ) color to the pixel
bd.setPixel( x, y, 0xFF0000 );
}
addChild( new Bitmap( bd ) );//a nice red block
note that if you're using a bitmapData with an alpha channel (say if you load the image, the alpha will be turned on automatically ) you 'll have to use
bd.getPixel32( x, y );// returns a uint : 0xFF000000
//and
bd.setPixel32( x, y, UINT );// 0xFF000000
EDIT : I 've done a quick bench :
package
{
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.utils.getTimer;
public class pixels extends Sprite
{
private var bd:BitmapData = new BitmapData( 100, 100, false, 0xFFFFFF );
public function pixels()
{
var i:int, total:int = 100, t:int = 0;
t = getTimer();
i = total;
while( i-- )
{
whileLoop( bd );
}
trace( 'while:', getTimer() - t );
t = getTimer();
i = total;
while( i-- )
{
forLoop( bd );
}
trace( 'for:', getTimer() - t );
}
private function forLoop( bd:BitmapData ):void
{
var i:int, j:int;
var col:int;
for ( i = 0; i < bd.width; i++ )
{
for ( j = 0; j < bd.height; j++ )
{
col = bd.getPixel( i, j ); // +/- 790 ms
}
}
//for ( i = 0; i < bd.width; i++ ) for ( j = 0; j < bd.height; j++ ) col = bd.getPixel( i, j ); // +/-530 ms
//var w:int = bd.width;
//var h:int = bd.height;
//for ( i = 0; i < w; i++ ) for ( j = 0; j < h; j++ ) col = bd.getPixel( i, j ); // +/-250 ms
}
private function whileLoop( bd:BitmapData ):void
{
var w:int = bd.width;
var h:int = bd.height;
var i:int = w * h;
var col:int;
while ( i-- )
{
col = bd.getPixel( i % w, int( i / w ) ); // +/- 580 ms
}
//while ( i-- ) col = bd.getPixel( i % w, int( i / w ) ); // +/- 330 ms
}
}
}
for 100 * ( 100 * 100 ) getPixel, the fastest (on my machine) is the one-line for loop with local variables. ( +/- 250 ms ) then the one-line while( +/- 330 ms ) :)
storing local variables w and h for width and height makes the for loops twice faster :)
good to know
If, as you say, you are only setting the pixels based on their x and y, you need neither getPixel() nor getPixels()!
myBitmapData.lock();
for( var j:int = 0; j < myBitmapData.height; j++ )
{
for( var i:int = 0; i < myBitmapData.width; i++ )
{
var alpha:uint = 0xFF000000; // Alpha is always 100%
var red:uint = 0x00FF0000 * ( i / myBitmapData.width ); // Set red based on x
var green:uint = 0x0000FF00 * ( j / myBitmapData.height ); // Set green based on y
var newColor:uint = alpha + red + green; // Add the components
// Set the new pixel value (setPixel32() includes alpha, e.g. 0xFFFF0000 => alpha=FF, red=FF, green=00, blue=00)
myBitmapData.setPixel32( i, j, newColor );
}
}
myBitmapData.unlock();
If, however, you want to read the pixels' current value, let me join the speed competition.
In addition to earlier answers, here's much more speed increase!
Instead of numerous calls to getPixel(), you can use getPixels() to get a byteArray of the pixel data.
myBitmapData.lock();
var numPixels:int = myBitmapData.width * myBitmapData.height;
var pixels:ByteArray = myBitmapData.getPixels( new Rectangle( 0, 0, myBitmapData.width, myBitmapData.height ) );
for( var i:int = 0; i < numPixels; i++ )
{
// Read the color data
var color:uint = pixels.readUnsignedInt();
// Change it if you like
// Write it to the pixel (setPixel32() includes alpha, e.g. 0xFFFF0000 => alpha=FF, red=FF, green=00, blue=00)
var theX:int = i % myBitmapData.width;
myBitmapData.setPixel32( theX, ( i - theX ) / myBitmapData.width, color );
}
myBitmapData.unlock();
You need a BitmapData object. Then, it's a simple straight-forward nested loop :
var pix : int; //AS3 uses int even for uint types
for (var x:int = 0; x < myBitmapData.width; x++)
{
for (var y:int = 0; y < myBitmapData.height; y++)
{
// This'll get you the pixel color as RGB
pix = myBitmapData.getPixel(x,y);
// To change the color, use the setPixel method + the uint corresponding
// to the new color.
}
}