I'm trying to develop heat map, now initially I would have to draw the intensity mask, and since I'm using GWT so I have randomly generated some coordinates and placed my circles ( with required gradience ) at those locations so the output comes out to be circles overlapping each other. And If I look at the intensity mask from Dylan Vester, it comes to be very smooth How can I draw my heat map ?? Also how the output is achieved similar to Dylan Vester?? Question also is if I'm drawing circles then how to decide the intensity at the intersection of two or more circles, how they have achieved ?? Here is my code
// creating the object for the heat points
Heat_Point x = new Heat_Point();
// Variables for random locations
int Min = 1,Max = 300;
int randomx,randomy;
// Generating set of random values
for( int i = 0 ; i < 100 ; i++ ) {
// Generating random x and y coordinates
randomx = Min + (int)(Math.random() * ((Max - Min) + 1));
randomy = Min + (int)(Math.random() * ((Max - Min) + 1));
// Drawing the heat points at generated locations
x.Draw_Heatpoint(c1, randomx, randomy);
}
And Here is how I'm plotting my heat point that is Heat_Point class
Context con1 = c1.getContext2d(); // c1 is my canvas
CanvasGradient x1;
x1 = ((Context2d) con1).createRadialGradient(x,y,10,x,y,20);
x1.addColorStop(0,"black");
x1.addColorStop(1,"white");
((Context2d) con1).beginPath();
((Context2d) con1).setFillStyle(x1);
((Context2d) con1).arc(x,y,20, 0, Math.PI * 2.0, true);
((Context2d) con1).fill();
((Context2d) con1).closePath();`
here I was supposed to add some images but I didn't have enough reputation :D :P
I took a quick look at HeatmapJS (http://www.patrick-wied.at/static/heatmapjs/) and it seems he uses radial gradients (like you have above) and he also uses opacity and a color filter called "multiply blend" to smooth out the intensity of the colors in the heat map.
His code is quite impressive. It's open source, so you might want to check it out!
Related
i have a little math/coding problem witch i don`t have any idea how could i do it work in a simple way, so the problem is is need to make a line shorter, with 15
in my program i have :
http://gyazo.com/aff5ff61fb9ad3ecedde3118d9c0895e
the line takes the center coordinates of both circles and draws from one to another, but i need it to be from the circumference of the circles, so it wont get inside
the code im using is :
var line:Shape = new Shape();
line.graphics.lineStyle(3,0xFF0000,2);
line.graphics.moveTo(sx,sy);
line.graphics.lineTo(fx,fy);
this.addChild(line);
arrow2(sx,sy,fx,fy);
var rline:Shape = new Shape();
rline.graphics.lineStyle(3,0xFF0000,2);
rline.graphics.moveTo(fx,fy);
rline.graphics.lineTo(xa,ya);
this.addChild(rline);
var rline2:Shape = new Shape();
rline2.graphics.lineStyle(3,0xFF0000,2);
rline2.graphics.moveTo(fx,fy);
rline2.graphics.lineTo(xb,yb);
this.addChild(rline2);
the rline and rline2 function is for the arrow lines, now my question is how do i make it shorter not depending on it direction so it will not overlap the circle
You can use vectors to solve your problem; they're pretty easy to get the hang of, and pretty much indispensable for things like game dev or what you're trying to do. You can get an overview here: http://www.mathsisfun.com/algebra/vectors.html or by searching "vector math" in google
So first step is to get a vector from one circle to another (pretty much what you've done):
var vector:Point = new Point( circle2.x - circle1.x, circle2.y - circle1.y );
var length:Number = vector.length; // store the length of the vector for later
This is the equivalent of saying "if you start at circle1 and move along vector, you'll arrive at circle2"
Next thing we're going to do is normalise it; all this does is set the length to 1 - the direction is unchanged - this makes it easier to work with for what you're looking to do. A vector with length 1.0 is called a unit vector:
vector.normalize( 1.0 ); // you can pass any length you like, but for this example, we'll stick with 1.0
Now, to draw a line from one circle to another, but starting from the outside, we simply find the start and the end points. The starting point is simple the position of circle1 plus vector (normalised to unit length) multiplied by the radius of circle1:
var sx:Number = circle1.x + vector.x * circle1.radius; // or circle1.width * 0.5 if you don't store the radius
var sy:Number = circle1.y + vector.y * circle1.radius;
The ending point can be found by starting at our start point, and continuing along our vector for a distance equal to the distance between the two circles (minus their radii). The length value that we created earlier is the distance between your two circles, from one center point to another, so we can use that to get the distance minus the radii:
var dist:Number = length - ( circle1.radius + circle2.radius ); // or circle1.width * 0.5 etc
And so the end point:
var ex:Number = sx + vector.x * dist;
var ey:Number = sy + vector.y * dist;
And to draw the line between them:
var line:Shape = new Shape;
line.graphics.lineStyle( 1.0, 0x000000 );
line.graphics.moveTo( sx, sy );
line.graphics.lineTo( ex, ey );
this.addChild( line )
As many people knew, HTML5 Canvas lineTo() is going to give you a very jaggy line at each corner. At this point, a more preferable solution would be to implement quadraticCurveTo(), which is a very great way to generate smooth drawing. However, I desire to create a smooth, yet accurate, draw on canvas HTML5. Quadratic curve approach works well in smoothing out the draw, but it does not go through all the sample points. In other word, when I try to draw a quick curve using quadratic curve, sometime the curve appears to be "corrected" by the application. Instead of following my drawing path, some of the segment is curved out of its original path to follow a quadratic curve.
My application is intended for a professional drawing on HTML5 canvas, so it is very crucial for the drawing to be both smooth and precise. I am not sure if I am asking for the impossible by trying to put HTML5 canvas on the same level as photoshop or any other painter applications (SAI, painterX, etc.)
Thanks
What you want is a Cardinal spline as cardinal splines goes through the actual points you draw.
Note: to get a professional result you will also need to implement moving average for short thresholds while using cardinal splines for larger thresholds and using knee values to break the lines at sharp corner so you don't smooth the entire line. I won't be addressing the moving average or knee here (nor taper) as these are outside the scope, but show a way to use cardinal spline.
A side note as well - the effect that the app seem to modify the line is in-avoidable as the smoothing happens post. There exists algorithms that smooth while you draw but they do not preserve knee values and the lines seem to "wobble" while you draw. It's a matter of preference I guess.
Here is an fiddle to demonstrate the following:
ONLINE DEMO
First some prerequisites (I am using my easyCanvas library to setup the environment in the demo as it saves me a lot of work, but this is not a requirement for this solution to work):
I recommend you to draw the new stroke to a separate canvas that is on top of the main one.
When stroke is finished (mouse up) pass it through the smoother and store it in the stroke stack.
Then draw the smoothed line to the main.
When you have the points in an array order by X / Y (ie [x1, y1, x2, y2, ... xn, yn]) then you can use this function to smooth it:
The tension value (ts, default 0.5) is what smooths the curve. The higher number the more round the curve becomes. You can go outside the normal interval [0, 1] to make curls.
The segment (nos, or number-of-segments) is the resolution between each point. In most cases you will probably not need higher than 9-10. But on slower computers or where you draw fast higher values is needed.
The function (optimized):
/// cardinal spline by Ken Fyrstenberg, CC-attribute
function smoothCurve(pts, ts, nos) {
// use input value if provided, or use a default value
ts = (typeof ts === 'undefined') ? 0.5 : ts;
nos = (typeof nos === 'undefined') ? 16 : nos;
var _pts = [], res = [], // clone array
x, y, // our x,y coords
t1x, t2x, t1y, t2y, // tension vectors
c1, c2, c3, c4, // cardinal points
st, st2, st3, st23, st32, // steps
t, i, r = 0,
len = pts.length,
pt1, pt2, pt3, pt4;
_pts.push(pts[0]); //copy 1. point and insert at beginning
_pts.push(pts[1]);
_pts = _pts.concat(pts);
_pts.push(pts[len - 2]); //copy last point and append
_pts.push(pts[len - 1]);
for (i = 2; i < len; i+=2) {
pt1 = _pts[i];
pt2 = _pts[i+1];
pt3 = _pts[i+2];
pt4 = _pts[i+3];
t1x = (pt3 - _pts[i-2]) * ts;
t2x = (_pts[i+4] - pt1) * ts;
t1y = (pt4 - _pts[i-1]) * ts;
t2y = (_pts[i+5] - pt2) * ts;
for (t = 0; t <= nos; t++) {
// pre-calc steps
st = t / nos;
st2 = st * st;
st3 = st2 * st;
st23 = st3 * 2;
st32 = st2 * 3;
// calc cardinals
c1 = st23 - st32 + 1;
c2 = st32 - st23;
c3 = st3 - 2 * st2 + st;
c4 = st3 - st2;
res.push(c1 * pt1 + c2 * pt3 + c3 * t1x + c4 * t2x);
res.push(c1 * pt2 + c2 * pt4 + c3 * t1y + c4 * t2y);
} //for t
} //for i
return res;
}
Then simply call it from the mouseup event after the points has been stored:
stroke = smoothCurve(stroke, 0.5, 16);
strokes.push(stroke);
Short comments on knee values:
A knee value in this context is where the angle between points (as part of a line segment) in the line is greater than a certain threshold (typically between 45 - 60 degrees). When a knee occur the lines is broken into a new line so that only the line consisting of points with a lesser angle than threshold between them are used (you see the small curls in the demo as a result of not using knees).
Short comment on moving average:
Moving average is typically used for statistical purposes, but is very useful for drawing applications as well. When you have a cluster of many points with a short distance between them splines doesn't work very well. So here you can use MA to smooth the points.
There is also point reduction algorithms that can be used such as the Ramer/Douglas/Peucker one, but it has more use for storage purposes to reduce amount of data.
I need to move many objects in a curve path across screen randomly. The objects start path and towards path also should take randomly. I had searched on google and finally i found one usefull tutorial to draw a curve. But i don't know how to move the objects using that curve path. But i am sure there would be some formula in as3 which has to use sin and cos theta. So please let me know if anybody have a solution for my problem. And also if i got any sample projects also would be very usefull for me.
And the link which i got to draw curve is as follows.
http://active.tutsplus.com/tutorials/actionscript/the-math-and-actionscript-of-curves-drawing-quadratic-and-cubic-curves/?search_index=4.
Thanks in advance.Immediate Help would be appreciated.
A quick'n'dirty would be using polar to cartesian coordinates(sin and cos) as you mentioned:
import flash.events.Event;
var a:Number = 0;//angle
var ra:Number = .01;//random angle increment
var rx:Number = 100;//random trajectory width
var ry:Number = 100;//random trajectory height
graphics.lineStyle(1);
addEventListener(Event.ENTER_FRAME,function (event:Event):void{
a += ra;//increment angle
rx += a;//fidle with radii otherwise it's gonna be a circle
ry += a;//feel free to play with these
graphics.lineTo(225 + (Math.cos(a) * rx),//offset(225,200)
200 + (Math.sin(a) * ry));//and use pol to car conversion
if(a > Math.PI) reset();//reset at 180 or any angle you like
});
function reset():void{
trace('reset');//more values to tweak here
a = Math.random();
ra = Math.random() * .0001;
rx = 20 + Math.random() * 200;
ry = 20 + Math.random() * 200;
}
Random numbers need tweaking to get mostly rounder ellipses (rather than flatter ones), but the principle is the same.
If you don't mind using libraries, why not try TweenLite's BezierPlugin or BezierThroughPlugin. Should be easy to randomize start/end points.
Also you can check out the first part of this older answer on quadratic,cubic and hermite interpolation
In my example I'm drawing a path, but of course, you could use those computed x,y coordinates to plug into a DisplayObject to move it on screen.
I want to draw a oval in html5 canvas,and i found a good method for it in stackoverflow.but I have another quesition.
function drawEllipse(ctx, x, y, w, h) {
var kappa = 0.5522848;
ox = (w / 2) * kappa, // control point offset horizontal
oy = (h / 2) * kappa, // control point offset vertical
xe = x + w, // x-end
ye = y + h, // y-end
xm = x + w / 2, // x-middle
ym = y + h / 2; // y-middle
ctx.beginPath();
ctx.moveTo(x, ym);
ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
ctx.closePath();
ctx.stroke();
}
the method in the above link has use bezierCurveTo to draw a ellipse,but it has draw bezierCurveTo 4 times. but I think just 2 bezierCurveTo can draw a ellipse.like this:
but i'm weak in Mathematics,could someone tell me the relationship of "the control point" and "the oval point" please? or we must draw four bezier Curve to draw a oval?
thanks everybody
My background isn't in mathematics so if I'm wrong I'm sure someone will correct me, but from my understanding we can draw a pretty good approximation of an ellipse with just two cubic bezier curves but the coordinates will be a little tricky.
To answer your question about the relation between the oval point and the control points I think it best be answered by watching this video from the point I've selected if you're familiar with interpolation or from the beginning if you are not. Don't worry it is short.
One problem we're probably going to run into is that when we start from the top and do a bezierCurveTo the bottom of the ellipse with the corners of the rectangle (of the same width and height) as the control points, the ellipses width is going to be smaller than the rectangle. .75 times the size we want. So we can just scale the control points accordingly.
Our control point's x would be adjusted like so (assuming width is the width of the ellipse and we're dividing by two to get its offset from the origin)
var cpx = (width / .75) / 2;
Put together a visualization where you can play with the width and height and see the drawn ellipse.
The red ellipse is how we wanted it to be drawn, with the inner one how it would be drawn if we didnt reposition the control points. The lines illustrate De Casteljau's algorithm that was shown in the video.
Here's a screenshot of the visualization
You only need two cubic bezier curves to draw an ellipse. Here's a simplified version of DerekR's code that uses the original function arguments that you provided--assuming you want x and y to be the center of the ellipse:
jsFiddle
function drawEllipse(ctx, x, y, w, h) {
var width_over_2 = w / 2;
var width_two_thirds = w * 2 / 3;
var height_over_2 = h / 2;
ctx.beginPath();
ctx.moveTo(x, y - height_over_2);
ctx.bezierCurveTo(x + width_two_thirds, y - height_over_2, x + width_two_thirds, y + height_over_2, x, y + height_over_2);
ctx.bezierCurveTo(x - width_two_thirds, y + height_over_2, x - width_two_thirds, y - height_over_2, x, y -height_over_2);
ctx.closePath();
ctx.stroke();
}
Big thanks to BKH.
I used his code with two bezier curves to complete my ellipse drawing with any rotation angle. Also, I created an comparison demo between ellipses drawn by bezier curves and native ellipse() function (for now implemented only in Chrome).
function drawEllipseByBezierCurves(ctx, x, y, radiusX, radiusY, rotationAngle) {
var width_two_thirds = radiusX * 4 / 3;
var dx1 = Math.sin(rotationAngle) * radiusY;
var dy1 = Math.cos(rotationAngle) * radiusY;
var dx2 = Math.cos(rotationAngle) * width_two_thirds;
var dy2 = Math.sin(rotationAngle) * width_two_thirds;
var topCenterX = x - dx1;
var topCenterY = y + dy1;
var topRightX = topCenterX + dx2;
var topRightY = topCenterY + dy2;
var topLeftX = topCenterX - dx2;
var topLeftY = topCenterY - dy2;
var bottomCenterX = x + dx1;
var bottomCenterY = y - dy1;
var bottomRightX = bottomCenterX + dx2;
var bottomRightY = bottomCenterY + dy2;
var bottomLeftX = bottomCenterX - dx2;
var bottomLeftY = bottomCenterY - dy2;
ctx.beginPath();
ctx.moveTo(bottomCenterX, bottomCenterY);
ctx.bezierCurveTo(bottomRightX, bottomRightY, topRightX, topRightY, topCenterX, topCenterY);
ctx.bezierCurveTo(topLeftX, topLeftY, bottomLeftX, bottomLeftY, bottomCenterX, bottomCenterY);
ctx.closePath();
ctx.stroke();
}
You will find this explained slightly more math-based in http://pomax.github.io/bezierinfo/#circles_cubic, but the gist is that using a cubic bezier curve for more than a quarter turn is usually not a good idea. Thankfully, using four curves makes finding the required control points rather easy. Start off with a circle, in which case each quarter circle is (1,0)--(1,0.55228)--(0.55228,1)--(0,1) with scaled coordinates for your ellipse. Draw that four times with +/- signs swapped to effect a full circle, scale the dimensions to get your ellipse, and done.
If you use two curves, the coordinates become (1,0)--(1,4/3)--(-1,4/3)--(-1,0), scaled for your ellipse. It may still look decent enough in your application, it depends a bit on how big your drawing ends up being.
It can be mathematically proven, that circle can not be made with Bézier curve of any degree. You can make "almost circle" by approximating it.
Say you want to draw a quarter of circle around [0,0]. Cubic bézier coordinates are:
[0 , 1 ]
[0.55, 1 ]
[1 , 0.55]
[1 , 0 ]
It is a very good approximation. Transform it linearly to get an ellpise.
I am trying to find a way to create an overlay for Google Maps API V3 that shows the sunlit areas of the world. This is the basic result I am looking for:
http://www.daylightmap.com/index.php
But want more control over the appearance (ideally just a 10% black overlay with no city lights). I can draw the shape in a canvas element but can not figure out how to calculate the shape based on earth's tilt and rotation etc.
Any help would be appreciated.
EDIT: Javascript
I still don't know where to implement the y-offset variable below. I also need to figure out how to adjust/stretch the y-offset from this (equal distant latitudinal lines) to mercator (closer at poles).
// Get the canvas element
var ctx = document.getElementById('canvas').getContext('2d');
ctx.clearRect( 0, 0, 800, 620 );
// Current time
var map_width = $("#canvas").width();
var map_height = $("#canvas").height();
var now = new Date();
var cur_hour = now.getHours();
var cur_min = now.getMinutes();
var cur_sec = now.getSeconds();
var cur_jul = now.julianDate() - 1;
var equinox_jul = new Date(now.getFullYear(),2,20,24,-now.getTimezoneOffset(),0,0).julianDate() - 1;
var offset_x = Math.round(((cur_hour*3600 + cur_min*60 + cur_sec)/86400) * map_width); // Resulting offset X
var offset_sin = ((365.25 - equinox_jul + cur_jul)%365.25)/365.25; // Day offset, mapped on the equinox offset
var offset_sin_factor = Math.sin(offset_sin * 2 * Math.PI); // Sine wave offset
var offset_y = offset_sin_factor * 23.44; // Map onto angle. Maximum angle is 23.44° in both directions
var degrees_per_radian = 180.0 / Math.PI;
var offset_y_mercator = Math.atan( offset_y.sinh() ) * degrees_per_radian;
// Global wave variables
var period = 1 / 6.28291; // Original value 2Pi: 6.28291
var amplitude = (map_height/2);
// Draw vertical lines: One for each horizontal pixel on the map
for( var x = 0; x <= map_width; x++ ) {
ctx.beginPath();
// Start at the bottom of the map
ctx.moveTo(x,map_height);
// Get the y value for the x pixel on the sine wave
var y = (map_height/2) - (Math.sin( (offset_x / map_width) / period ) * amplitude);
offset_x++;
// Draw the line up to the point on the sine wave
ctx.lineTo(x,y);
ctx.stroke();
}
If you want it to be physically accurate, you actually need to consider two offsets: a vertical (depending on the current date) and a horizontal (depending on the current time).
The horizontal offset X may be calculated by looking at the current time on some fixed geographic location on earth. The shadow offset will be 0 at midnight and will increase by 1/86400 for each seconds after midnight. So the formular is
offsetX = (curHour*3600 + curMinute*60 + curSeconds)/86400
The vertical offset will change between the Solstices on June 21st and Dec 22nd (if it's not a leap year, where the Solstices are on June 20th and Dec 21st). The maximum angles are 23.44° in both directions. We have 90° per hemisphere and 365/2 = 182.5 days between the two solstices, and we are working with a mapping of a circular motion, so a sin()-function has to be used. The wavelength of a sinus wave is 2pi, so we need pi for half the vertical offset Y of one year.
Please note, that I did not take leap seconds into account, so the calculation might be a bit off in the distant past/future.
// current time
$curHour = date("H");
$curMin = date("i");
$curSec = date("s");
// resulting offset X
$offsetX = ($curHour*3600 + $curMin*60 + $curSec)/86400;
echo "======== OFFSET X ==========\n";
echo "curHour: $curHour\n";
echo "curMin: $curMin\n";
echo "curSec: $curSec\n";
echo "offsetX: $offsetX\n\n";
// spring equinox date as day of year
$equinox = date("z", mktime(0, 0, 0, 3, 20));
// current day of year
// first line is for testing purposes
//$curDay = date("z", mktime(0, 0, 0, 6, 21));
$curDay = date("z");
// Day offset, mapped on the equinox offset
$offsetSin = ((365.25 - $equinox + $curDay)%365.25)/365.25;
// sinus wave offset
$offsetSinFactor = sin($offsetSin * 2 * pi());
// map onto angle
$offsetY = $offsetSinFactor * 23.44;
// optional: Mercator projection
$degreesPerRadian = 180.0 / pi();
$offsetYmercator = atan(sinh($offsetY)) * $degreesPerRadian;
// missing: mapping onto canvas height (it's currently
// mapped on $offsetY = 90 as the total height of the
// canvas.
echo "========= OFFSET Y =========\n";
echo "equinox day: $equinox\n";
echo "curDay: $curDay\n";
echo "offsetSin: $offsetSin\n";
echo "offsetSinFac: $offsetSinFactor\n";
echo "offsetY: $offsetY\n";
echo "offsetYmerc: $offsetYmercator\n";
You should be able to port this calculation to any language you want.
You asked for more control over appearance
Check out the Geocommons JS api, which may be more suited to your purpose than Google Maps.
If you're going for flexibility, GEOS would be preferable to drawing the shape for a specific projection. I know there are php bindings, but I haven't used them myself.
Helmer Aslaksen has a great writeup about heavenly mathematics that should help you create an alorithm to draw a sunlit-area polygon using geos. You can test your code against measured sunrise/sunset times for accuracy.
Edit 1
Must be Python and Google Maps, you say?
You can overlay data with KML,
which will allow you to set a background color as you request.
I like using the interactive sampler to get a feel for how things will look.
Check out the Shapely package on pypi,
and a discussion on how to create kml from it.