Can I draw a thumbnail for a polyline?

If I have a path for a polyline saved as string ,

From google maps sdk: path.encodedPath()

Or I have a series of latlng dots,

Can I create a sketch for this path?

I don’t want to draw it on a mapView , I wonder if I can draw it in any other form, for example, imageView or something like that.

+5
source share
2 answers

I created swift 3 code that you can simply copy and paste into the playground and immediately see the results

the code is here:

 import UIKit import PlaygroundSupport var str = "Hello, playground" //All you need is to create a path with that points and create image or layer with that path //To perpare for this let make some extensions with helper code //Extension for UIBeziePath to easily create it from points extension UIBezierPath { convenience init(points:[CGPoint]) { self.init() //connect every points by line. //the first point is start point for (index,aPoint) in points.enumerated() { if index == 0 { self.move(to: aPoint) } else { self.addLine(to: aPoint) } } } } //to create image from path you can use this class function extension UIImage { class func imageFrom(path:UIBezierPath,lineColor:UIColor,fillColor:UIColor)->UIImage { //create context to draw in use path bounds as context size. assume that path is inzide of rect with start corener at 0,0 coordinate UIGraphicsBeginImageContextWithOptions(path.bounds.size, false, 0) print("path bounds \(path.bounds) lineWidth:\(path.lineWidth)") let context = UIGraphicsGetCurrentContext() //set fill color context?.setFillColor(fillColor.cgColor) //set line coolor context?.setStrokeColor(lineColor.cgColor) context?.setLineWidth(path.lineWidth) //draw a path context?.addPath(path.cgPath) context?.drawPath(using: .fillStroke) //get image from context let image = UIGraphicsGetImageFromCurrentImageContext()! //finish context UIGraphicsEndImageContext() return image } } //2. To create layer use this extension extension CAShapeLayer { convenience init(path:UIBezierPath, lineColor:UIColor, fillColor:UIColor) { self.init() self.path = path.cgPath self.strokeColor = lineColor.cgColor self.fillColor = fillColor.cgColor self.lineWidth = path.lineWidth self.opacity = 1 self.frame = path.bounds } } //how to use: //1. assume you recieved points let points:[CGPoint] = [CGPoint(x: 0, y: 0),CGPoint(x: 150, y: 50),CGPoint(x: 75, y:140),CGPoint(x: 0, y: 80)] //2. create path let path = UIBezierPath(points: points) //3. you can specify path line width path.lineWidth = 2 //4. as a joinstyle too path.lineJoinStyle = .round //5. a)now you can create image from path with helper function let image = UIImage.imageFrom(path: path, lineColor: UIColor.purple, fillColor: UIColor.red) print(image) //and set it to imageView let imageView = UIImageView(image: image) imageView.frame.origin = CGPoint(x: 200, y: 200) imageView.backgroundColor = UIColor.green //5. Maybe you will need to specify content mode for imageView imageView.contentMode = .scaleAspectFit //5 b.) Or you can create a Layer. Add add it to someone layer layter //if you need, you can apply transform to path - this is special way to //adjust scale, rotation an lots of other cool stuff on layers, paths. //Create special struct which descripbes transformation //Identity is a special case which does not make any transformations at all var transform = CGAffineTransform.identity //scale it by 0.5 for x and 0.5 for y. if you need to increse scale by //100 times, just pass 100 for x and y arguments transform = transform.scaledBy(x: 0.5, y: 0.5) //no apply transform to path. path.apply(transform) let layer = CAShapeLayer(path: path, lineColor: UIColor.blue, fillColor: UIColor.brown) //6. let see results let container = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400)) container.backgroundColor = UIColor.white //for imageView container.addSubview(imageView) //for CAShapeLayer container.layer.addSublayer(layer) //for playGround you can set this to see result there //Do not forget to select from menu //View -> Assistant Editor-> Show Assistance Editor PlaygroundPage.current.liveView = container PlaygroundPage.current.needsIndefiniteExecution = true 

// Also I have to mention that the CAShapeLayer solution takes up less memory, which is crucial for really large images // but UIImage is easier to use

brown shape is a layer with a path scaled to 0.5, red - imageView

enter image description here

+3
source

If you have a series of long lats, you can know the maximum and minimum long lats, for example: maxLat, maxLong, minLat, minLong . Please do not assume that both maximum values ​​should not belong to the same coordinate. The same goes for both minimum values.

You can use this to get a rectangle:

  let rect = CGRect(x: minLng , y: minLat, width: (maxLng - minLng), height: (maxLat - minLat)) 

Now all the other long longs are points in this rectangle. You can get each coordinate corresponding CGPoint value on

  let point = CGPoint(x: maxLng - coordinate.longitude, y: maxLat - coordinate.latitude) 

Using this rectangle and a series of CGPoints you created, you can draw a path (starting from the first point and add all subsequent points to it) in the form (for example, the image that you mentioned in your answer), or create a graphic context to create a thumbnail of your paths and save it as an image.

Refer to the drawing and printing manual if you are not familiar with drawing in CGContexts.

However, if you want to put this equivalent of the path sketch on the image, then the real problem is how you would know the position. A simple trick would be to get the minimum map coordinates equivalent on the map on which you want to overlay the thumbnail of the path, and use these minimum values ​​to create the path and context. Then you can center the thumbnail on the image.

Your project sounds interesting. Enjoy and good luck.

+2
source

Source: https://habr.com/ru/post/1260516/


All Articles