I have a series of paths, mostly straight lines, or almost straight lines.
I'd like to categorize them as horizontal, vertical, diagonal, and also the direction in which they are drawn (up->down, down->up, left->right, right->left etc). some of the lines are L shaped, and I'd like that info too.
this can probably be done if i knew the endpoints of the path, but i don't know how to extract that info. Also, I need more than that for L shaped lines since the endpoints would indicate a diagonal. I've looked on all the reference pages, and can't find that sort of info.
so, if you know that, or another way to get the information i'm looking for ... thanks
The only way you can access the underlying structure is using the CGPathApply method on it. You pass a C function that is passed each of the elements(CGPathElement) in the bezier path. You should be able to discern what type of line it is in that method.
There is a good example on using CGPathApply. It's not exactly what you need but looks like a good starting point.
Related
Im drawing a simple map in spotfire using US cities as geo location. The values I want to show on the map is the location of 'specific gas stations' by the geo code.
For larger cities there are many but im only able to get one 'shape'. I can work on the coloring or size. But im interested to get all 5 dots next to each other or a call-out highlighting there are five..?
Is there a way to show all values, or does spotfire need to combine them?
I know I can get more details with lat/long but that is not an option.
are your shapes literally being combined? that shouldn't happen unless you are doing a "Marker by: City". double check this setting.
if they aren't being literally combined into one point on the map, but instead they are sitting on top of each other, you could adjust the jitter settings on your Marker Layer (check the Appearance page in the Properties dialog) to spread them out a little bit.
if that doesn't suit your needs, and the former case is true, please update your question with some screencaps of your map chart's configuration and I'll see if I can provide a better answer :)
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:...)
I have a CGPath, and on that path I detect touches. The path is basically a line or a curve, but it is not filled. The idea is that the user strokes the path, so wherever the user has stroked along the path I'd like to draw the path with a different stroke/color etc.
First, to find if the touches are inside the path, and to give the user some room for error, I'm using CGPathCreateCopyByStrokingPath, and CGPointInsidePath. This works fine.
Next, I need to find how far along the path the user has stroked. That is today's question.
When that is done, and I have an answer like 33%, then I'd be a simple assignment to strokeEnd on the path. (two copies, one complete path, and one on top with strokeEnd set to whatever percentage of the complete path the user has stroked with his finger so far).
Any ideas how to find how far along the path the user has stroked his finger?
I have worked on this quite a while, and would like to share my answer (I'm the one who asked the question btw).
I want to detect touches along a path (e.g a Bezier Curve). Problem is that it can only tell you if a touch hit the path, but not where (using CGPathContainsPoint).
To avoid having the user hit exactly on the path, create a fatter version with CGPathCreateCopyByStrokingPath), so that's the one to check for touch on.
The main problem still is, where along the path did the touch hit. What I did was to create a dashed path copy with CGPathCreateCopyByDashingPath with minimal spacing. This path is never actually displayed. Then I got every part of it with the CGPathApply saving every path element in an array.
When a touch is detected, and is within the "fat path", then I just loop through the array of path-dash-elements, checking the distance (just regular Pythagoras) to the start-point of each path-dash-element.
If the touch-point is closest to the 14'th element, and there are e.g. 140 elements total, that means we're 10% along the way.
Now that we have the percentage. What I want now is to paint the path as far as the touch. I tried to use the suggested strokeEnd property on a path. That didn't match my calculated percentage at all. Actually, it seemed to me to be quite inaccurate. Or maybe my calculation is.
Anyway, since we already have all the path-elements, and know which one to stop at (the 14th element), what I did was to build a new path using the path-elements. Since I didn't want a dashed path (that was just a trick to find out where the touch was on the long continuous path), I just skipped all the moveTo path-elements (except the very first). That will create a continous path.
CGPathApply - by request
// MARK: - Stuff for CGPathApply
typealias MyPathApplier = #convention(block) (UnsafePointer<CGPathElement>) -> Void
// http://stackoverflow.com/questions/24274913/equivalent-of-or-alternative-to-cgpathapply-in-swift
// Note: You must declare MyPathApplier as #convention(block), because
// if you don't, you get "fatal error: can't unsafeBitCast between
// types of different sizes" at runtime, on Mac OS X at least.
func myPathApply(path: CGPath!, block: MyPathApplier) {
let callback: #convention(c) (UnsafeMutablePointer<Void>, UnsafePointer<CGPathElement>) -> Void = { (info, element) in
let block = unsafeBitCast(info, MyPathApplier.self)
block(element)
}
CGPathApply(path, unsafeBitCast(block, UnsafeMutablePointer<Void>.self), unsafeBitCast(callback, CGPathApplierFunction.self))
}
I have a utility class GHPathUtilies.m which includes a method:
+(CGFloat) totalLengthOfCGPath:(CGPathRef)pathRef
This is all written in Objective-C, but presumably you could use the same technique to walk along the path elements, using CGPathApply, until you are near enough, or have passed the target point. The general idea is to break the curves between each element into small line segments and keep a running sum of the length of each segment.
Of course if the path doubles back on itself, you'll have to figure out which point is the touch point.
I would like to implement karaoke-like progress highlight for iOS.
I know I could use NSAttributedString and highlight the text character by character. However, I would like the highlight to progress pixel by pixel, not character by character.
Any ideas?
P.S. No need for sample code, just point me to the right direction.
Here is an example:
I can't think of any automatic way to do that. There would be several problems to solve. It would be pretty hard, I think.
The hardest would probably be figuring out the pixel position of each word so you can pace the coloring to match the timing within the music. With text and attributed layout, you could probably get the text engine to give you the boundaries of each word and then apply the color attribute to each word as it's spoken/sung. You'd have to have data about the time offset for the beginning and end of each word's being sung.
You might have to use Core Text to get layout information about the bounding rectangles of each word.
Once you get that you could build a path (UIBezierPath or CGPath; they're pretty interchangeable) that follows the flow of the text, and then install that path in to a shape layer. You could then make the text transparent, make the shape layer a colored background that shows through, and animate the shape layer's strokeStart and/or strokeEnd properties to make it fill the text. You might need to do it word by word with a short animation that interpolates between one word and the next to get the timing right.
You probably want to have a look at Core Text, which is the lower level framework used for laying out text, using this you can obtain necessary paths that you need to render said effect (I suggest starting from answers similar to this)
There are plenty of answers for alternative, perhaps simpler answers, for example character by character or word-by-word, which may be easier to implement.
I'm reading a 3-d party Delphi sources and stuck with a line, where Rect is initialized with another Rect's coordinates, but swapped, like this:
r, rsrc: TRect;
...
r := Rect(rsrc.right + 1, rsrc.bottom + 1, rsrc.left, rsrc.top);
rsrc is filled with proper on-screen coordinates, so (left,top) is always less than (right,bottom).
What does this mean? I can't find any mentions of possible purpose for this in the Delphi documentation.
Strictly speaking, a TRect is only a a collection of four integers. The meaning of these numbers depends entirely on the context. Most often, they specify a rectangle.
That is, it does not make sense at all to expect the Delphi documentation to say anything about the current issue! It is like seeing a car making a U-turn on a small road and asking, "Why doesn't the car's manual explain why someone would make a U-turn on this particular road?"
It doesn't mean anything, just as SomeVarName := 7 doesn't mean anything on it's own. Look further down into the code and see what the r is supposed to be used for; Also look for how rsrc was obtained.
It might simply be that the coordinates for rsrc were obtained using some math and it was determined that the resulting rectangle is up side down, hence the code rotates the rectangle to be top-side-up.