Maybe it's just me.
I spent a couple months learning Javascript just to be able to use D3.js, and enjoyed making fairly complex geometric shapes for intellectual exploration, but then I found a dirty secret.
Even though the math is correct and D3 seems to handle it, there are NO perfectly accurate SVG viewers.
For a quick example of this, create two circles with their centres r * 2 width apart with a radius of r.
Zoom in without recalculating the viewport.
Eventually, the circles will either look like they overlap or not touch at all.
Example with 6 circles, all r * 2 distance apart.
For reference, these screenshots were taken from Affinity as I could not figure out how to get D3 to do this. To Serif Labs' credit, they did make code changes to make rendering at zoom more accurate, and those changes reduced the space to about 1/4 of what it was.
100%
400%
100000% (centre of the image)
Related
I am trying to figure out how to create different zoom factors on the X- and Y-axis in d3. It seems to be created with a single zoom-factor for both axis, and basically I would like to know if there is a way to separate them.
The basics is simple enough: There is excellent support in d3 for an even zoom-effect on x- and y-axises. It is also easy to turn off the zoom for one axis. But I cant find a way to create this intermediate effect. The goal is to have the y-axis zoom 10 times more than the x-axis for each mouse wheel zoom-event.
I have no actual code to show, since I dont know if it is possible. Perhaps a useful hint, is that I work with D3 version 5. The usual, more or less standardized zoom code is used.
I'm writing a drawing program that uses a pressure sensitive table for input. I'd like to be able to simulate the soft pencil effect that many other art programs have (such as Paint Tool SAI, Art Rage). Technique I'm using at the moment is functional, but is missing the cleanness I see in more professional programs.
My algorithm at the moment works like this:
Create a bitmap representing the head of the brush. This is just a transparent bitmap with a black circle drawn on it. The circle has an inner radius that is solid black and an outer radius. The blackness linearly fades from opaque to transparent as you move from the inner to the outer radius.
Capture input events from my tablet. Each point contains an (x, y) coordinate as well as a pressure value
For every point after the first one, draw a line from the previous point to the current one. This is done by drawing (daubing) the brush bitmap several times between the two points. The step size between each daub is chosen so there is an overlap between subsequent daubs.
This works reasonably well, but the result is a line that is somewhat blobby and jagged.
One thing I need to do is somehow smooth out the input points so that the stroke as a whole is smooth.
The other thing I need to do is figure out how to 'drag' the brush head along this path to make the stroke. If the spacing is too far apart, the stroke looks like a line of circles. If too close together, the stroke builds up on itself and becomes very dark. (I tried to fix this by attenuating the brush by the spacing. This does make things more consistent, but stops the stroke from being fully opaque).
Anyhow, I'd expect that there's a lot of research already done on this, if only I knew where to look. Please let me know if there are any better pencil drawing algorithms out there.
Instead of drawing the new circle over what has already been drawn, using the standard blending functions (so that regions of overlap get a higher opacity), you need to keep the maximum opacity so far.
Only after you have built up the complete stroke (as on a white sheet), you can blend it to the existing line art.
The picture illustrates the difference between blending and keeping the maximum opacity.
Having fun with D3 geo orthographic projection to build an interactive globe, based on all the great examples I found.
You can see my simple mockup at http://bl.ocks.org/patricksurry/5721459
I want the user to manipulate the globe like a trackball (http://www.opengl.org/wiki/Trackball). I started with one of Mike's examples (http://mbostock.github.io/d3/talk/20111018/azimuthal.html), and improved slightly to use canvas coordinates and express the mouse locations in 'trackball coordinates' (i.e. rotation around canvas horizontal and vertical axes) so that a fixed mouse movement gives more rotation near the edges of the globe (and works outside the globe if you use the hyberbolic extension explained above), rather than Mike's one:one correspondence.
It works nicely when the globe starts at an unrotated position (north pole vertical), but when the globe is already rotated (manipulate the example so the north pole is facing out of the page) then the trackball controls become non-intuitive because you can't simply express a change in trackball coordinates as a delta in the d3.geo.rotate lat/lon coordinates. D3's 3-axis rotation involves applying a longitude rotation (spin around north pole), then a latitude rotation (spin around a horizontal axis in the canvas plane), and then a 'yaw' rotation (spin around an axis perpendicular to the plane) - see http://bl.ocks.org/mbostock/4282586.
I guess what I need is a method for composing my two rotation matrices (the one currently in the projection, with a new one to rotate the trackball slightly), but I can't see a way to do that in D3, other than digging into the source (https://github.com/mbostock/d3/blob/master/src/geo/rotation.js) and trying to do the math to define the rotation matrix. The code looks elegant but comment-free and I'm not sure I can correctly decipher the closures with the orthographic projection instance.
On the last point, if someone knows the rotation matrix form of d3.geo.projection that would probably solve my problem too.
Any ideas?
There is an alternative solution to patricksurry's answer, by using quaternion representations, as inspired by Jason Davies. I, too, thought D3 would've already supported this composition natively! And hoped Jason Davies posted his code...
Took sometime to figure out the math. A demo is uploaded here, with an attempt to explain the math too. http://bl.ocks.org/ivyywang/7c94cb5a3accd9913263
With my limited math knowledge, I think, one of the advantages quaternion over Euler is the ability to compound multiple rotations over and over, without worrying about coordinate references. So it would always work, no matter where your north pole faces, and no matter how many rotations you'll have. (Someone please correct me, if I got this wrong).
I decided that solving for the combined rotation matrix might not be so hard. I got http://sagemath.org to do most of the hard work, so that I could express the composition of the original projection rotate() orientation plus a trackball rotation as a single equivalent rotate().
This gives much more natural behavior regardless of the orientation of the globe.
I updated the mockup so that it has the improved version - see http://bl.ocks.org/patricksurry/5721459
The sources are at http://bl.ocks.org/patricksurry/5721459 which include an explanation of the math - cool that you can use proper greek letters in javascript for almost readable math sourcecode!
It would still be good if D3 supported composition of rotate operations natively (or maybe it does already?!)
I am in the process of developing a very simple physics engine. The only non-static objects in it will be circles and the only collision detection I will be performing is between circles and line pieces.
For the purpose I am utilizing the principals described in Advanced Character Physics. That is, I do integration by using a simple Verlet integrator. I perform collision detection and response simply by calculating the distance between the circles and the line pieces and in case that the distance is less than the cirles radius I project the circle out of the line piece.
This works very well and the result is a practically perfect moving circle. The current state of the engine can be seen here: http://jsfiddle.net/8K4Wj/. This however, also shows the one major problem I am facing: The circle does not rotate at all.
As far as I can figure out there is three different collision cases that will have to be dealt with seperately:
When the circle is colliding with a line vertex and is not rolling along the line.
When the circle has just hit or rolled of a line. Then the exact point of impact will have to be calculated (how?) and the circle is rotated according to the distance between the impact position and the projected position.
When the circle is rolling along a line. Then is it simply rotated according to the distance traveled since last frame.
Here is the closest I have got to solving the problem: http://jsfiddle.net/vYjzt/. But as the demo shows it doesn't handle the edge cases probably.
I have searched for a solution online but I can not find any material that deals with the given problem specifically (as I said the physics engine is relatively simple and I do not want to bother with complex physic simulation concepts).
What looks wrong in your demo is that you're not considering angular moment and energy when determining the motion.
For the easy case, when the wheel is dropping to the floor in your demo, it stops spinning while in free fall. Angular momentum should keep it going.
A more complicated situation is when the wheel finally lands on the floor, it moves with the same horizontal velocity it had before hitting floor. This would be correct if it wasn't rolling but since it is rolling, some of the kinetic energy will have to go into the spinning motion, and this should slow it down. As a more clear example of this, consider the opposite case where the wheel is spinning quickly but has no linear momentum. When this wheel is set on the floor, it should take off and the spinning should slow. Also, for example, as the wheel rolls down a hill, it accelerates more slowly because the energy needs to go into both linear and circular motion.
It's not too hard to do, but to show a rolling object in a way that looks intuitively correct, I think you'll need to consider the kinetic energy and angular momentum associated with rolling. By "not too hard", I mean that all of your equations will essentially but twice as long, with one term for linear motion and another for angular. I won't recite all of the equations, it's basically just the chapter in rotational motion from any physics text.
(Nice demo, btw!)
I've implemented a canvas element that uses drawarc to create the effect of bubbles rising up at various speeds on the background (it's an underwater themed site for an underwater-themed client) - It looks really good and I'm pretty pleased with it, but I'm noticing a slight performance issue in some browsers (specifically IE9).
I'm drawing the bubbles using drawarc to create semi translucent circles - can anyone tell me if this is more or less expensive (in terms of client side performance) to stamp images/sprites onto the canvas instead?
-Mike
Drawing arcs / circles is much more expensive than drawing images. Drawing images is most likely the most efficient method for drawing anything to a canvas. I wrote my Bachelor Thesis on this subject. It is in german, but basicly when drawing arcs using arc and arcTo you get less than 15.000 operations / sec in IE9. When drawing images you get more than 160.000 operations per second.