iOS CG dashed double line path - ios

I want draw underground way symbol on map.
Actually the same path is drawed two times.
first with:CGContextSetLineDash(ctx, 0, lengths, cnt);
and second, no dashed, more tiny as first
result is:
Question is: how to draw double line as one path (not two with offset), dashed, transparent in middle?

Related

iOS - Find white pixels/area enclosed by a black curve and create path

Using Swift methods touchBegan, touchMoved and touchEnded I save the touch points and than I draw a line using UIGraphicsGetCurrentContext() with methods beginPath(), move(to: Point), addLine(to: Point) and strokePath().
This line is repeated on 4 quadrants plus their negative values, therefore 8 lines are drawn.
Here is an example:
Example image
I save this drawing as an Image when the user taps the tick (Done green button at top-right) for later manipulations.
I wonder if it's possible to create e closed path/shape with white pixels enclosed by the black lines. I want to fill the white area with custom color when the user touches inside it.
The shape is created by user input and I have no idea how it would look like.
Would be thankful to whoever finds the time to give it's contribute.
Thank you
Maybe what you want is the "Flood Fill" algorithm, please see the article.

What do the coordinates mean in love.graphics.polygon

I don't know which numbers do what in the coordinates example here. I imagine they mean things like place the top left corner at this position and the bottom right corner at this position, but I don't know which number corresponds to which position.
I've been trying to fool around with the numbers to get a small green rectangle but keep getting weird results like the following, and don't know which numbers need to be what is order to make the rectangle symmetrical and at the bottom
This is what the rectangle should look like
The height of the rectangle is 50, the height of the screen is 1000, and the width of the screen is 1700.
Here's my draw function
function love.draw()
love.graphics.setColor(0.28, 0.63, 0.05) -- set the drawing color to green for the ground
love.graphics.polygon("fill", objects.ground.body:getWorldPoints(objects.ground.shape:getPoints())) -- draw a "filled in" polygon using the ground's coordinates
-- These are the grounds coordinates. -11650 950 13350 950 13350 1000 -11650 1000
love.graphics.setColor(0.76, 0.18, 0.05) --set the drawing color to red for the ball
love.graphics.circle("fill", objects.ball.body:getX(), objects.ball.body:getY(), objects.ball.shape:getRadius())
love.graphics.setColor(0.20, 0.20, 0.20) -- set the drawing color to grey for the blocks
love.graphics.polygon("fill", objects.block1.body:getWorldPoints(objects.block1.shape:getPoints()))
love.graphics.polygon("fill", objects.block2.body:getWorldPoints(objects.block2.shape:getPoints()))
print(objects.block1.body:getWorldPoints(objects.block1.shape:getPoints()))
end
As described at https://love2d.org/wiki/love.graphics, Löve's coordinate system has (0, 0) at the upper left corner of the screen. X values increase to the right, Y values increase down.
The polygon function expects the drawing mode as it's first parameter, and the the remaining (variable) parameters are the coordinates of the vertices of the polygon you wish to draw. Since you want to draw a rectangle you need four vertices/eight numbers. You do not have to list the upper left corner of the rectangle first, but that's probably the easiest thing to do.
So in your case, you want something like:
love.graphics.polygon('fill', 0, 950, 0, 1000, 1700, 1000, 1700, 950)
I've not worked with the physics system, so I'm not quite sure how it's coordinate system relates to "screen" coordinates. The values you show in the comment in your code listing seem like they should give a rectangle (although x = -11650 wouldn't be on screen). You might try experimenting without the physics system first.
Also, since the physics system in Löve is just a binding to Box2D, you might want to read its documentation (http://box2d.org/about/). Not really sure what you're trying to do with feeding shape:getPoints into body:getWorldPoints.

CGPath copy lineJoin and miterLimit has no apparent affect

I am offsetting a CGPath using copy(strokingWithWidth:lineCap:lineJoin:miterLimit:transform‌​:). The problem is the offset path introduces all kinds of jagged lines that seem to be the result of a miter join. Changing the miterLimit to 0 has no effect, and using a bevel line join also makes no difference.
In this image there is the original path (before applying strokingWithWidth), an offset path using miter join, and an offset path using bevel join. Why doesn't using bevel join have any affect?
Code using miter (Note that using CGLineJoin.round produces identical results):
let pathOffset = path.copy(strokingWithWidth: 4.0,
lineCap: CGLineCap.butt,
lineJoin: CGLineJoin.miter,
miterLimit: 20.0)
context.saveGState()
context.setStrokeColor(UIColor.red.cgColor)
context.addPath(pathOffset)
context.strokePath()
context.restoreGState()
Code using bevel:
let pathOffset = path.copy(strokingWithWidth: 4.0,
lineCap: CGLineCap.butt,
lineJoin: CGLineJoin.bevel,
miterLimit: 0.0)
context.saveGState()
context.setStrokeColor(UIColor.red.cgColor)
context.addPath(pathOffset)
context.strokePath()
context.restoreGState()
Here is a path consisting of two line segments:
Here's what it looks like if I stroke it with bevel joins at a line width of 30:
If I make a stroked copy of the path with the same parameters, the stroked copy looks like this:
Notice that triangle in there? That appears because Core Graphics creates the stroked copy in a simple way: it traces along the each segment of the original path, creating a copied segment that is offset by 15 points. It joins each of these copied segments with straight lines (because I specified bevel joins). In slow motion, the copy operation looks like this:
So on the inside of the joint, we get a triangle, and on the outside, we get the flat bevel.
When Core Graphics strokes the original path, that triangle is harmless, because Core Graphics uses the non-zero winding rule to fill the stroke. But when you stroke the stroked copy, the triangle becomes visible.
Now, if I scale down the line width used when I make the stroked copy, the triangle becomes smaller. And if I then increase the line width used to draw the stroked copy, and draw the stroked copy with mitered joins, the triangle can actually end up looking like it's filled in:
Now, suppose I replace that single joint in the original path with two joints connected by a very short line, creating a (very small) flat spot on the bottom:
When I make a stroked copy of this path, the copy has two internal triangles, and if I stroke the stroked copy, it looks like this:
So that's where those weird shapes star shapes come from when you make a stroked copy of your paths: very short segments creating overlapping triangles.
Note that I made my copies with bevel joins. Using miter joins when making the copy also creates the hidden triangles, because the choice of join only affects the outside of the joint, not the inside of the joint.
However, the choice of join does matter when stroking the stroked copy, because the use of miter joins makes the stars larger. See this document for a good illustration of how much the join style can affect the appearance of an acute angle.
So the miter joins make the triangles' points stick out quite far, which makes the overlapping triangles look like a star. Here's the result if I stroke the stroked copy using bevel joins instead:
The star is nigh-invisible here because the triangles are drawn with blunted corners.
If the inner triangles are unacceptable to you, you will have to write your own function (or find one on the Internet) to make a stroked copy of the path without the triangles, or to eliminate the triangles from the copy.
If your path consists entirely of flat segments, the easiest solution is probably to use an existing polygon-clipping library. The “union” operation, applied to the stroked copy, should eliminate the inner triangles. See this answer for example. Note that these libraries tend to be written in C++, so you'll probably have to write some Objective-C++ code since Swift cannot call C++ code directly.
In case you're wondering how I generated the graphics for this answer, I did it using this Swift playground.

Wavy text inside of UIBezierPath in iOS

I saw a trekking app on Android which built routes on selected criteria. It also could built routes for provided gpx-files. All those routes were very wavy. And above each highlighted route I could see its name — also as a very wavy text moving along with the highlighted path, repeating all the curls and waves. I wonder how it is possible to create the same effect in iOS.
What I have is a gpx-file. Shortly speaking, it's just a very long array of tuples:
typealias Coordinates = (Double, Double) // x and y
let points: [Coordinates] = [ (120, 120), (130, 135), (135, 125), (138, 122) ]
Coordinates are represented by pixels, and I use catmull rom interpolation algorithm to build UIBezierPath with smooth rounded corners.
I can draw a wavy text by changing angles for each letter in a playground. But calculating all that transformation stuff for an array of pixels looks too complicated.
Probably there's a better solution?

How to get a path's outline?

I have some point like below:
[[1,4],[2,8]]
[[5,4],[3,8],[5,4]]
Then I make a line (lat's say the width is 2) , I want to get the line's outline(path), see the Example Image's black line.
In one world, I have wall corner's coordinate, I want to figure out the outline's path of the wall(In the Example image, the red part is the coordinate, and the black lines are what I want to get )
Example Image
I've been working on a similar project. I decided to use vectors to get the parallel lines along the path by getting the cross product of the UP vector and the vector of points 1 to 2 which will get you a vector that is pointing away from the line that you can use to get the begin and end point of the parallel line
CVec3 a, v1, v2, zero, up(0, 1.0f, 0);
zero.set(0,0,0);
v1.sub(points[1], points[0]);
v2.sub(points[2], points[1]);
a.crossProduct(up, v1);
a.normalise();
result[0] = result[1] = a;
result[0].mult(wallwidth).add(points[0]);
result[1].mult(-wallwidth).add(points[0]);
result[2].set(result[0]).add(v1);
result[3].set(result[1]).add(v1);
result[0] to result[2] is line in one side while result[1] to result[3] will be the other one. I haven't figure out how to connect the lines so they make corner without deforming the line width

Resources