So I have this fine legacy Delphi 5 project with a tchart with vertical bars along a datetime bottomaxis. It works very fine.
Now I want to add up to three horizontal "warning"-lines, each with up to three togglable labels. The idea is to show three red limit lines(three 3-element lineseries), and labels at far left, middle and far right showing Yvalue limits. Labels are togglable in order not to clutter data. And it works too. These labels must sit at xmin, mid and xmax even when scrolling. I solved it with having a timer started when first dataseries is redrawn, and then resetting the three labelseries with the chart's new xmin, mid, xmax. When scrolling, the labels follow.
But when I zoom in, something is lost. I print the xmin, xmax and line coordinates in the statusbar as it is recalculated (for debugging), it looks quite right, but the three horizontal lines slip away to the left. Leftmost point is out of sight, rightmost is drifting to the left, worse with increased zoom. Yvalues are correct.
Is there a best way to do plot-eventdriven recalculation of plotdata?
(Or must I rebuild it all in my XE10.2? )
I just ran it at home, the same phenomenon appears in XE10.2. When I zoom in, the second series (horizontal line, endpoints recalculated to be at the graph's edges) creeps away to the side.
However if I connect series2 to Topaxis, then everything is fine. Rock solid. Seems like a natural thing. Silly me.
procedure TForm1.Series1AfterDrawValues(Sender: TObject);
var a,b :Double;
begin
a:=(Chart1.LeftAxis.Minimum+chart1.leftAxis.maximum)/2;
b:=chart1.TopAxis.Minimum;
series2.Clear;
series2.addxy(b,a,'Left');
series2.addxy(b+(chart1.topAxis.Maximum-b)/2,a,'Mid');
series2.addxy(chart1.topAxis.Maximum,a,'Right');
end;
Running,line stays put when scrolling
Related
I have two objects: one is a ball, whose velocity is given by a vector of components velocity.x and velocity.y, such that, at every frame, the (x, y) position of the ball gets updated to (x + velocity.x, y + velocity.y); the other is a very thin horizontal rectangle that cannot move. Of course, I'd love the ball to change its trajectory whenever it hits the rectangle either from above or from below.
However, I've run into a problem I don't know how to fix: whenever the ball travels fast enough to go from one side of the rectangle to the other side in just one frame, the collision isn't detected because the ball never actually comes in contact with the rectangle. Being the rectangle very thin, the minimum velocity beyond which this behaviour occurs isn't even too high.
I know this is a problem that usually occurs when you want to keep an object inside the screen: in fact, if you just change the sign of its velocity as soon as it exits the screen, this doesn't necessarily make your object rebound off the side of the window (because it could travel so fast that a part of it gets stuck outside the edge), so you actually have to reposition it inside the window first, and then change the sign of its velocity accordingly. But I cannot use this trick here, because the behaviours of the ball on the two sides of the rectangle are supposed to be different: if the ball hits it from above, it will bounce upwards; if from below, it will bounce downwards. But when the ball manages to go past the rectangle in just one frame, how can I tell the program which side the ball should be repositioned? After all, once that frame is drawn, the program isn't able to know whether the ball came 'from the other side' of the rectangle, or if it's always been on that side.
I hope I managed to explain my problem clearly enough. What can I do to solve it?
Take the previous position of the ball and the current position of the ball, and create a line. Use that line to perform collision detection instead of the ball itself. Test for collision detection between the line and the rectangle.
This is going to be a bit more complicated than testing for collision detection between a circle and a rectangle, but googling "line rectangle collision detection" will return a ton of results. Basically you'll want to break the rectangle down into 4 lines and then check whether each line intersects your path line.
This question might help: How do you detect where two line segments intersect?
I am working on a multi-line animated chart based on [Edit: not Bostock's] example:
http://bl.ocks.org/atmccann/8966400
I want the lines to appear synchronized by the date value on the x axis. If I slow down the graph (say to duration=15000) I can clearly see that in the very early part of the graph the green line is ahead of the black line. Then the black line moves ahead of the green line. Both start and end together.
The issue is accentuated in my chart where I am plotting 20 lines. Some are clearly ahead of the others when plotting. Lines with initial y values of zero shoot way ahead of those that climb to higher y values at the start.
How can I adjust the display so both lines paint for the same date at the same time?
The technique in the bl.ocks.org example (which, btw, is not Bostock's) is animating based on the length of the line, not it's position on the y-axis. If you want to animate based on the y-axis position, you'll have to use a different technique. Especially with 20 lines, I wouldn't recommend trying to dynamically update each line if they have a lot of points. You could do that if there aren't many points, though.
A simple approach would be to add a solid (white) rectangle to the chart that covers all the graph lines. Then animate the left position and width of that rectangle to reveal the lines over time.
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.
I have a general question (I know I should present specific code with a problem, but in my case the problem is of a more general nature).
In Processing, let's say I make an ellipse:
ellipse(30, 30, 10, 10);
Now, is there a way to get the pixels where this ellipse is on the canvas? The reason would be to have a way of creating user interaction with the mouse (for instance). So when someone clicks the mouse over the ellipse, something happens.
I thought of turning everything into objects and use a constructor to somehow store the position of the shape, but this is easier said than done, particularly for more complex shapes. And that is what I am interested in. It's one thing to calculate the position of an ellipse, but what about more complex shapes? Are there any libraries?
Check out the geomerative library. It has a way to check whether the mouse is inside any SVG shape. I can't remember off the top of my head but it works something like you make a shape:
myShape = RG.loadShape("shape.svg");
and a point:
RPoint p = new RPoint(mouseX, mouseY);
and the boolean function contains() will tell you if the point is inside the shape:
myShape.contains(p);
It's better to use a mathematical formula than pixel-by-pixel checking of the mouse position (it's much faster, and involves less code).
For a perfect circle, you can calculate the Euclidean distance using Pythagoras' theorem. Assume your circle is centred at position (circleX,circleY), and has a radius (not diameter) of circleR. You can check if the mouse is over the circle like this:
if(sq(mouseX-circleX)+sq(mouseY-circleY) <= sq(circleR)) {
// mouse is over circle
} else {
// mouse is not over circle
}
This approach basically imagines a right-angled triangle, where the hypotenuse (the longest side) runs from the centre of the circle to the mouse position. It uses Pythagoras' theorem to calculate the length of that hypotenuse, and if it's less than the circle's radius then the mouse is inside the circle. (It includes a slight optimisation though -- it's comparing squares to avoid doing a square root, as that can be comparatively slow.)
An alternative to my original mathematical answer also occurred to me. If you can afford the memory and processing power of drawing all your UI elements twice then you can get good results by using a secondary buffer.
The principle involves having an off-screen graphics buffer (e.g. using PGraphics). It must be exactly the same size as the main display, and have anti-aliasing disabled. Draw all your interactive UI elements (buttons etc.) to this buffer. However, instead of drawing them the normal way, give each one a unique colour which it uses for fill and stroke (don't add any text or images... just solid colours). For example, one button might be entirely red, and another entirely green. Any other RGB value works, as long as each item has a unique colour. Make sure the background has a unique colour too.
The user never sees that buffer, so don't draw it to the screen (unless you're debugging or something). When you want to detect what item the mouse is over, just lookup the mouse position on that off-screen buffer. Get the pixel colour at that location, and match it to the UI element.
After you've done all that, just go ahead and draw everything to the main display as normal.
It's worth noting that you can cut-down the processing time of this approach a lot if your UI elements never (or rarely) move. You only need to redraw the secondary buffer when something appears/disappears, animates, or changes size/position.
I'm looking to chart some time-based data over the course of multiple days (using a simple line chart). I'd like to present the time of day as a gradient of color in the background of the line graph. Noon of each day would be white, midnight is nearly black, and all other hours in between are a smooth greyscale in between.
I can do this very, very clunkily by drawing rectangles before my lines, but it has the following problems:
1. hours without a data point don't get a rectange, leaving a gap in my background
2. the transition is not smooth, but stepped
It seems that the best way to fill in the gaps would be to latch onto the ticks along the x-axis, as those are regularly spaced regardless of the data points. Is there a way for me to apply a gradient, either CSS or SVG, along with the tick marks, that will smoothly flow from one to the other (that is, no gaps between where one gradient ends and the other begins, nor any overlap)? If I add or remove data, the gradient should change accordingly.
Any and all assistance greatly appreciated.
just define the gradient in a <def> section, and place rectangles aligned with the days you are charting. set the fill attribute to url("#the_gradient").
have a look here http://www.w3.org/TR/SVG/pservers.html