I want to do this animation - Water level rises in sea engulfing a small mountain having pits. When water recedes some of it stays in the pockets and again when water level rises it all becomes one. This animation continues indefinitely. Now i have tried doing this by using two approaches,
1) Drawing and clearing the water in pool with the flow of water in sea.
ctx.bezierCurveTo(x1,y1,x2,y2,end_x,end_y);
I changed first and second control points with the flow of water to make the base change from little flat to spherical and vice-versa. But wasn't smooth and also second pit has irregular base so impossible.
2) I made the required pockets filled with water and played with opacity so that pocket water mixes with sea water when submerged. Again this approach doesn't give smooth look.
Here's what it should look like:
The base image is background of canvas, i just have to control water flow.
Please suggest what to do.
You can use compositing to have your sea water seamlessly intrude on your mountain
In particular "source-out" compositing allows you to draw new content only where it doesn't overlap any existing content.
Therefore "source-out" compositing will allow you to draw new sea-water only where it doesn't overlap the existing mountain.
When the water is rising:
clear canvas
set globalCompositeOperation="source-over" // the default, new drawings will overdraw
draw your mountain
set globalCompositeOperation="source-out" // new sea water will not overdraw existing mountains
draw the rising sea water
increase the height of the sea water
repeat with #1 until your sea water is at desired height
When the water is falling:
clear canvas
set globalCompositeOperation="source-over" // the default, new drawings will overdraw
draw your mountain
set globalCompositeOperation="source-out" // new sea water will not overdraw existing mountains
draw the retained sea water only in the pit of your mountain
draw the falling sea water
decrease the height of the sea water
repeat with #1 until your sea water is at desired height
After much thinking found a 2-step approach.
Step-1 >>
1) Draw water in sea (Destination)
2) Set ctx.globalCompositeOperation="destination-out";
3) Draw pool water (Source)
This will remove part of source overlapping with dest. thus creating sea water with a hollow space(transparency) in place of pool. Now this image with the hole becomes the dest. image on which i have to draw only pool water so that the consistency of water is maintained.
Step-2 >>
1) Set ctx.globalCompositeOperation="destination-atop";
2) Draw pool water (Source)
This will draw dest. only where dest. and source overlap i.e. when dest. image with hole(transparency in place of pool) and pool overlap sea water is created in hollow area. Point to be noted - pool water is like a subset of sea water so i don't have to worry about pool water(Source) to be created as it is with "destination-atop".
Related
What is the Cesium(https://cesiumjs.org/)'s height value meaning?
Altitude value from Ellipsoid? Or, above sea level?
Note: difference of altitude and above sea level is, [altitude] = [above sea level] + [Geoid value]
What I want to do is set Cesium's camera to same position of real GPS value get from Smartphone's GPS, but GPS's height value is altitude, so if Cesium use above sea level as it's height reference, Camera's position is set to too much high position...
Anyone know this?
I found the answer by myself:
https://cesiumjs.org/Cesium/Build/Documentation/Cartographic.html
"The height, in meters, above the ellipsoid."
I have a molecular dynamics trajectory of a micelle in a water box. For each frame, I want to get center of mass (COM) of the micelle and calculate the density of water molecules from COM to the sides of the water box. Does anybody know what is the best way to do that? I was wondering whether somebody has dealt with such an issue before.
Thanks
Sadegh
First - a lot of useful commands and how to use them are written here.
You should select your lipids (I suppose micelle is build from phospholipids) than selecting by type - lipids:
set sel1 [atomselect top "lipids"]
or by resname :
set sel1 [atomselect top resname DPC]
And than:
center_of_mass $sel1
calculate the density of water molecules from COM to the sides of the
water box
I don't know what exactly you are talking about - there are some water molecules inside the micelle? Or waterbox is water molecules within certain distance from the micelle? Please, give some more info (better some pics of the system with descriptions).
This question already has answers here:
Formula for controlling the movement of a tank-like vehicle?
(10 answers)
Closed 7 years ago.
I'm trying to simulate a tank-like/skid-steered vehicle, i.e. both of the wheels (one on each side) have separate velocities, and steering is done by increasing or decreasing the velocity of one of the sides.
For example, If I set the velocity of the left wheel to 5, and the right wheel to 3, it will turn right. What I'd like to know is, given the velocities of the wheels Vl and Vr, and the distance between the wheels D, by how many degrees will the direction the vehicle is pointing in change in one tick?
I've tried looking at Formula for controlling the movement of a tank-like vehicle?, and the links on that question, but haven't come up with anything. All my best guesses have failed.
First: the really easy edge cases. if V_l and V_r are zero, don't move. If they're the same, don't turn.
Second, if only one of V_l and V_r are zero, the tank pivots around the stationary tread, and the moving tread traces out an arc of length V_big with a radius of curvature D. theta = Vbig/D, plus or minus some sign conventions based on your coordinates. (the tank base also translates some distance but the calculations for that are dependent on where the center of rotation of the tank is defined to be and your coordinate system, so that detail is left as an exercise for the reader.)
Third, symmetry concerns! Obviously tank treads turning is left/right symmetric. If the left tread is twice as fast as the right the tank should turn the same amount as if the right tread is twice as fast as the left, just in a different direction. Ditto for going backwards.
Fourth: Meat and potatoes! I'm assuming neither tank tread can slip whatsoever. The faster tread traces an arc of length V_fast on a circle of radius r+D marked out by an angle theta. If you recall your trig V_fast=(r+D)*theta. The slower wheel traces out an arc of length V_slow on a circle of radius r marked out by the same angle.(V_slow = theta*r) Divide one equation by the other, receive V_fast/V_slow = (r+D)/r. Apply algebra to provide r=D/((V_fast/V_slow)-1) Note that this explodes appropriately when V_slow is zero or when V_fast=V_slow, and you appropriately receive r=D when V_fast=2*V_slow Recall that theta=V_slow*r: theta=(V_fast-V_slow)/D
IN RADIANS, mind you That's a crucial detail.
NOTE: If you define 'turning right' as positive theta and turning left as negative theta, it all works out and theta=(V_l-V_r)/D, even for negative speeds. The tank won't turn around to face the direction of travel, it'll keep facing the correct way.
I split my canvas into two. I need to draw on each side, defining a clipping region for both. Each side has to do similar things, like drawing text in colours, drawing circles etc.
I have read that you should keep your fillStyle and strokeStyle changes to a minimum. However I have also read you must keep your save and restores to a minimum as well.
So what is faster?
Save the canvas, clip the left hand side, do ALL the drawing for that side for the multiple colours, then restore and repeat for the right hand side?
Or ... Set the first text colour. Clip the left hand side. Draw all text for this colour. Then clip the right hand side (without restting fillStyle) and draw all the same colour text for the right hand side. Then set the next fillStyle and then clip each side and draw text for this colour? Etc
Anyone know?
Also if I set one clip region, then set another clip region without saving and restoring, what actually happens?
As always, you must performance test with your own project's code.
The context maintains internal variables relating to its current state (colors, transforms, current path, compositing applied, etc).
You can save a copy of the current context state using context.save. Then after altering the context state, you can restore the original context state with context.restore. Note: you can nest multiple save/restore if needed.
fillStyle is a context state so changing fillStyle='green' followed later by fillStyle='blue' is faster than save/restore because just 1 state variable is being reset rather than every state variable that's done during save/restore.
The point is that you often gain performance by saving+resetting individual state values rather than doing a full context.save/context.restore.
Minimizing state changes will maximize performance, so for example, batching all green drawings will help performance.
Clipping is a complex operation and is more expensive than simple state changes like changing fillStyle. With GPU acceleration the clipping is accomplished much more efficiently and is therefore considerably less costly than clipping without a GPU.
About changing clipping regions: Clipping is always done only on the last path defined. So setting another clipping region will undo the previous clipping region (unless the previous and current path are identical).
About left and right clipping regions: If your design permits, you might want to define both the left and right clipping regions at once into 1 combined clipping region. Since paths can be disconnected, defining 1 clipping path with 2 non-intersecting parts is allowed.
As the car companies warn: "Your mileage may vary". But you might perf test this method:
Define your left and right clipping regions in 1 clipping path
Set fillStyle="red" and do all your red drawings at once (both right and left)
Reset fillStyle="blue" and do all your blue drawings at once, etc, etc.
One final thought: All projects have their own distinct requirements so you must perf test your actual code rather than relying exclusively on general rules. Don't skip the perf tests--especially if you will be deploying on mobile where canvas is slow by nature.
Good luck with your project!
[ Additional note about clipping ]
A clipping region is semi-permanent. Once it is set it remains even if the context.clip command is issued again. The new clip command will further restrict all previous clipping regions.
To clear a clipping path you must wrap your clips inside context.save & context.restore(). Alternatively, resizing the canvas will force the context state to be restored to defaults--but resizing will also clear all canvas content: canvas.width=canvas.width
Here's and example of a single path consisting of a left and right square:
// left square
ctx.beginPath();
ctx.moveTo(50,50);
ctx.lineTo(150,50);
ctx.lineTo(150,150);
ctx.lineTo(50,150);
ctx.closePath();
// right square
ctx.moveTo(200,50);
ctx.lineTo(300,50);
ctx.lineTo(300,150);
ctx.lineTo(200,150);
ctx.closePath();
ctx.strokeStyle="red";
ctx.stroke();
Create a clipping region from this left+right path.
// create a clipping region from the left+right path
ctx.clip();
Fill the entire canvas with green. The green will only be drawn inside the clipping region (inside the left and right squares).
// draw a green rect over the entire canvas
// the green will only be drawn inside the clipping region
ctx.fillStyle="green";
ctx.fillRect(0,0,canvas.width,canvas.height);
If you add a second clipping region, the result is that drawing will only be visible in the union of all clipping paths.
So if the second clipping region slightly overlaps the first, all drawings will only be visible inside the union of the first and second clipping regions. The blue section in the following illustration is the union of the 2 clipping paths.
ctx.beginPath();
ctx.moveTo(0,115);
ctx.lineTo(canvas.width,115);
ctx.lineTo(canvas.width,135);
ctx.lineTo(0,135);
ctx.clip();
ctx.closePath();
ctx.fillStyle="blue";
ctx.fillRect(0,0,canvas.width,canvas.height);
A few ideas :
To handle your two screens, you might use two canvases side by side.
Even if you keep only one canvas, you can reduce the use of clipping by doing :
- erase left half of screen
- draw left part
- erase right part
- clip on right half
- draw right part
Thus you clip only once.
For your color vs clip concern, clipping is much costly than changing color.
And if one keeps on clipping with no save/restore, clipping zones will add-up.
For your strokeStyle/fillStyle, yes there's a cost, especially if using color names ('blue'), or rgb 'rgb()' strings or worse 'hsl()' strings.
So here's a trick : pre-compute and store the colors whenever you can. Simply use the context to convert !
var blue = 'hsl(23, 75%, 75%)';
context.fillStyle = blue ;
blue = context.fillStyle ;
This is my firs excursion on the HTML5 canvas, I have working knowledge of jQuery and Javascript.
I'm trying to create a "spinning globe" effect with it.
The idea is to have a circle and meridians "spinning" on it, to give the effect of a rotating globe.
I've drawn the circle and now I'm trying to create lines that start from the right (following the curve of the circle), move towards the centre straightnening up (in the middle they are straight) and follow the inverse curvature on the left, ending with the circle.
I'm trying to do this with the HTML5 canvas and jQuery but I'm not sure of where to start... should I create an arc and then try to animate it?
I'm even wondering if the canvas is the right tool or if I should use anything else.
Any suggestion is welcome!
Sebastian
You could use a quadratic bezier curve, which is basically just a curve with a start point, an end point, and a "control point" in the middle, which is what you would want to change as the globe spins. In this case, all of your lines would start and end at the north and south poles, respectively, of your "globe". For example, to make one of these lines:
// start drawing a line
canvas.beginPath();
// move the the top of your globe
canvas.moveTo(0,0);
/* draw a curve with the control point specified by the first two args,
* end point by the second two:
* (in your case, the control point would be in the middle of the globe) */
canvas.quadraticCurveTo(control_point_x, control_point_y, 0, 50);
// finish drawing, stroke and end
canvas.stroke();
canvas.closePath();
You would also have to take in to account how you will clear the lines after each frame, of course.
See: The Canvas element API, Complex Paths
This is what I got, didn't have the time to proceed any further: http://jsfiddle.net/Z6h3Z/
I use bezier curves where the two control points are in a sort of oval arc centered at the poles.
What I got stuck at is the distribution of points along the arc to look more realistic.