I'm trying to get LineChart's plots' coordinate.
I've searched several hours, but I found only one solution, but it depends on xAxis only and always set CGPoint.y to zero.
I want to get the X and Y coordinates.
The reason is that the graph's xAxis is on hour base and showing year based, so it's really hard the tap the point to show a marker even I spread the graph. I tried many things, but I couldn't figure it and not succeeded to detect the tap.
Then I thought that if I can get the point's coordinate, I can build a bd-tree to store them and find the nearest coordinates from the tapped point.
Thank you for your help.
You have to implement the ChartViewDelegate and then implement the following method to get the touch point in your chartview
-(void)chartValueNothingSelected:(ChartViewBase *)chartView{
NSArray *gestureRecognizers = chartView.gestureRecognizers;
int count = 0;
for(UIGestureRecognizer *gesture in chartView.gestureRecognizers){
if([gesture isKindOfClass:[UITapGestureRecognizer class]] && gesture.state == UIGestureRecognizerStateEnded){
float xVal = [self.chartDataView getValueByTouchPointWithPt:[gesture locationInView:self.chartDataView] axis:AxisDependencyLeft].x;
}
}
}
It's too much to explain here.
There is ChartTransformer, which is used to convert data coordinate space into pixel coordinate space and vice versa.
So, in ChartTransformer, there are several methods like pointValueToPixel and pixelToValue to get the job done.
You can try figure out a clever way to write more methods or delegates to pass the coordinates you want.
You have to look at the code in detail to know how to use them. A good example is x axis renderer's drawGridLine.
Related
I have some experience with Metal and quite a bit with Unity and am familiar with setting up meshes, buffers, and the backing data for drawing; but not so much the math/shader side. What I'm struggling with is how to get an endless scrolling world. So if I pan far to the right side I can see the left side and keep going.
The application of this would be a seamless terrain that a player could scroll in any direction forever and have it just wrap.
I don't want to duplicate everything on draw and offset it, that seems horrendously inefficient. I am hoping for a way to either use some magic matrix math or some sort of shader to get things wrapping/drawing where they should when panning the map. I've searched all over for some sort of guide or explanation of how to get this working but haven't come up with anything.
I know a lot of old (dos) games did this somehow, is it still possible? Is there a reason why it seems the industry has migrated away from this type of scrolling (bounding to edges vs wrapping)?
I have created a simple example demonstrating what you're looking for (I think).
The basic idea of it is that you draw the map in a repeating grid, using the drawPrimitives(type:vertexStart:vertexCount:instanceCount:) method on MTLRenderCommandEncoder. As the instance count you want to pass in the number of identical maps you want to draw, extending it as far as needed to not see where it ends. In my example I used a simple 5x5 grid.
To not have the user see the edge of the map, we're gonna calculate their position modulo 1 (or whatever size your map is):
func didDrag(dx: CGFloat, dy: CGFloat) {
// Move user position on drag, adding 1 to not get below 0
x += Float(dx) * draggingSpeed + 1
z += Float(dy) * draggingSpeed + 1
x.formTruncatingRemainder(dividingBy: 1)
z.formTruncatingRemainder(dividingBy: 1)
}
This is how it looks:
Just a follow up on what I have actually implemented. First I essentially have an array of x,y points with altitude, terrain type and all that jazz. Using some simple % and additions/subtractions it is trivial to get the nodes around a point to generate triangles
On a draw I calculate the first showing point and the last showing point and calculate the groups of triangles shown between those points. The first/last point take into account wrapping, it is then pretty trivial to have an endless wrapping world. For each group a translation offset is passed via a uniform matrix for that group which will position that section where it should belong.
I set it via renderEncoder.setVertexBytes(&uniform, length:..., offset:...)
what I want to do is the following. I have a linechart with some data points on it. I want to allow user to select chunk of the chart and highlight it by dragging a finger.
I tried a few hacky approaches using ChartTransformer and tracking pixels of the UIPanGestureRecognizer and then programmatically highlighting the appropriate xIndexes, but it looks terrible.
I was wondering if there is a better way to do it. Thank you.
I would say your approaches should be right, what you mean it looks terrible?
I would check when the pan gesture ended, I will calculate how many xIndex has been chosen, and highlight every data entry for that Index.
The logic to determine the xIndex - when user start panning, I know the location, and I will translate it into the closest xIndex; same as the ending point, so we know the start xIndex and end xIndex
Is there an equivalent to CGRectIntersectsRect that would be something more along the lines of points intersecting... I'm making a game and RectIntersectsRect works for what I want it to do but it looks bad because sometimes the corner of the one object will intersect the corner of the other and it will call the method, and you can barely see that the two objects touched, so it looks like it just glitches. Is there a CGPointIntersectsPoint or something along the lines of that? Thanks.
You can use CGRectContainsPoint to see if one of your rectangle contains a corner of the other, but you will get the same issue.
You can look for the intersection of the two rectangles using CGRectIntersection. It will give you an other CGRect, which represents the area in common from your two rectangles. From this rectangle, you can check width and height to see if the intersection is "big enough"
CGRect intersection = CGRectIntersection(rect1, rect2);
if (CGRectGetWidth(intersection) > kHorizontalThreshold || CGRectGetHeight (intersection) > kVerticalThreshold)
{
// call your intersection method here
}
Try CGRectContainsPoint. If you want to just compare two points use CGPointEqualToPoint.
You can't really have a point intersecting another point as they're two exact points in space. The only way they can "intersect" is by being equal.
I'm wondering why the following thing does not work correctly.
Before the nodes are drawn, I analyze if two specific nodes intersect by using:
[[self playerSpriteNode] intersectsNode: [self pSKLabelNode]]
When pSKLabelNode touches desiredSpriteNode it works perfect! (By returning true, or false when it doesn't intersect)
But when it "passes" by a few pixels away from the SKLabel it still intersects and returns true.
Is there some setup that are recommended to fix the frame size of the nodes, or solutions that you think that will fix the problem?
I have the same problem when I try to intersects static node (that located left) with node that have rotation (and flying from the right side). I fix it like this
if ([ninja intersectsNode:node] &&
CGRectGetMinX(node.frame) <= CGRectGetMaxX(ninja.frame) &&
CGRectGetMaxX(node.frame) >= CGRectGetMinX(ninja.frame))
{
//and here I have intersects
}
So I fix it by adding additional parameters
The intersectNode method is optimized for running fast on devices with lots of iterations per second. Due to this, it actually "estimates" collision based on math, which sometimes goes wrong at a margin of a few pixels, specially when we are speaking of square corners of PNGs.
I had this problem once too, and since i used circles I calculated distance between circles as a second verification.
So, what you can do is a custom verification INSIDE the intersectsNode if case. Assuming you handle squares, you could verify wether the x or y collides after the intersectNode. It could be something like like:
if([[self playerSpriteNode] intersectsNode: [self pSKLabelNode]]){
if(distance between x1 and x2 < size1.width/2 + size2.width/2 || distance between y1 y2 < size1.height/2 + size2.height/2){
//Your code goes here
}
}
Note that we compare central x distances with half each widths summed. This is only an example that works with squares, and most generic sprites.
I would like to point out that, while intersectsNode is slightly imprecise, this is NEEDED in order to run your game swiftly, as perfect and precise calculations per update can be very exhaustive to your device.
So, should you do a custom verification, ALWAYS call it after intersectsNode returns true, as a second verification rather than the only one.
The answer provided above by Roman pretty much does what i said, in shorter code; I just wanted to leave an explanation about why.
Swift 2.1:
For increased results do your check in the update( _:) loop, is where things happen before the next drawing:
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if goodDude.intersectsNode(badDude){
print("bad dude v.s. Ninja")
}else{
print("not dude at all")
}
}
In my App, I am using Coreplot to draw a CPTScatterPlot. Now i want to do a scanner on the chart and this animation of UIView (a line) should be like a Line aligned with Y-axis and travels through x=0 to whatever the last value of x is.
I want to perform an action based on the y value while this custom UIView (scanner) travels.
Any help would be appreciated.
Thanks,
i have something similar in an app of mine, the way i went about it was to add a bar graph on top of the scatter plot, i used that bar graph to represent the line that tracks the user's touch.
then i have a UIView that is overlaid on the plot and tracks the scatter plot touches and displays details of the point being touched.
if you just want to display a line, adding a bar graph is probably the easiest, then you don't have to worry about plot space coordinates vs superview coordinates.
the bar graph data source is only returning a value for the location the user is touching, with a height to match the size of the scatter plot.
the quick version is you can use handlePlotTouchEventInSpace:atPoint:isNewEvent to track the user's touches on the graph.
from there you can use the plotPoint:forPlotAreaViewPoint method on the plot space to get the coordinates of the touch.
something like this is a good starting point. it's a bit of a journey to get it all working, but its not too bad once you get the puzzle started.
-(void)handlePlotTouchEventInSpace:(CPTPlotSpace *)space atPoint:(CGPoint)point isNewEvent:(BOOL)newEvent {
NSDecimal plotPoint[2];
CPTXYPlotSpace *xySpace = (CPTXYPlotSpace *)space;
[xySpace plotPoint:plotPoint forPlotAreaViewPoint:point];
after that plotPoint will contain the x and y location of the touch inside the plot space.